From bb69a3d2843061c3f6728f6e29a13d73730d3457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergiusz=20=27q3k=27=20Baza=C5=84ski?= Date: Thu, 19 Feb 2015 18:58:47 +0100 Subject: [PATCH 1/2] Hide HTTP auth parts from URL This instroduces an extra function in the Target interface (PublicURL) which is used to populate the instance field in scraped metrics. --- retrieval/target.go | 20 +++++++++++++++++--- retrieval/target_test.go | 13 +++++++++++++ retrieval/targetmanager_test.go | 4 ++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/retrieval/target.go b/retrieval/target.go index ddd0a0eb4..030bde0a9 100644 --- a/retrieval/target.go +++ b/retrieval/target.go @@ -17,6 +17,7 @@ import ( "fmt" "math/rand" "net/http" + "net/url" "os" "strings" "sync" @@ -114,6 +115,8 @@ type Target interface { // points in this interface, this one is the best candidate to change given // the ways to express the endpoint. URL() string + // The URL without any auth data in it, used to label data + PublicURL() string // The URL as seen from other hosts. References to localhost are resolved // to the address of the prometheus server. GlobalURL() string @@ -186,8 +189,8 @@ func (t *target) recordScrapeHealth(ingester extraction.Ingester, timestamp clie } healthMetric[clientmodel.MetricNameLabel] = clientmodel.LabelValue(scrapeHealthMetricName) durationMetric[clientmodel.MetricNameLabel] = clientmodel.LabelValue(scrapeDurationMetricName) - healthMetric[InstanceLabel] = clientmodel.LabelValue(t.URL()) - durationMetric[InstanceLabel] = clientmodel.LabelValue(t.URL()) + healthMetric[InstanceLabel] = clientmodel.LabelValue(t.PublicURL()) + durationMetric[InstanceLabel] = clientmodel.LabelValue(t.PublicURL()) healthValue := clientmodel.SampleValue(0) if healthy { @@ -320,7 +323,7 @@ func (t *target) scrape(ingester extraction.Ingester) (err error) { return err } - baseLabels := clientmodel.LabelSet{InstanceLabel: clientmodel.LabelValue(t.URL())} + baseLabels := clientmodel.LabelSet{InstanceLabel: clientmodel.LabelValue(t.PublicURL())} for baseLabel, baseValue := range t.baseLabels { baseLabels[baseLabel] = baseValue } @@ -363,6 +366,17 @@ func (t *target) URL() string { return t.url } +// PublicURL implements Target. +func (t *target) PublicURL() string { + u, err := url.Parse(t.url) + if err != nil { + glog.Warning("Could not parse URL for auth stripping (%s), returning it unchanged", err) + return t.url + } + u.User = nil + return u.String() +} + // GlobalURL implements Target. func (t *target) GlobalURL() string { url := t.url diff --git a/retrieval/target_test.go b/retrieval/target_test.go index cb84ef7e4..67909e5a7 100644 --- a/retrieval/target_test.go +++ b/retrieval/target_test.go @@ -34,6 +34,19 @@ func (i *collectResultIngester) Ingest(s clientmodel.Samples) error { return nil } +func TestTargetHidesURLAuth(t *testing.T) { + testTarget := target{ + state: Unknown, + url: "http://secret:data@host.com/query?args#fragment", + httpClient: utility.NewDeadlineClient(0), + } + expected := "http://host.com/query?args#fragment" + u := testTarget.PublicURL() + if u != expected { + t.Errorf("Expected PublicURL to be %v, actual %v", expected, u) + } +} + func TestTargetScrapeUpdatesState(t *testing.T) { testTarget := target{ state: Unknown, diff --git a/retrieval/targetmanager_test.go b/retrieval/targetmanager_test.go index fe1e97d49..917b5d3ca 100644 --- a/retrieval/targetmanager_test.go +++ b/retrieval/targetmanager_test.go @@ -42,6 +42,10 @@ func (t fakeTarget) URL() string { return "fake" } +func (t fakeTarget) PublicURL() string { + return "fake" +} + func (t fakeTarget) GlobalURL() string { return t.URL() } From 0d0bb3c030dcadd0c16091842c4b2de44ef7cd47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergiusz=20=27q3k=27=20Baza=C5=84ski?= Date: Fri, 20 Feb 2015 16:21:13 +0100 Subject: [PATCH 2/2] Change instance identifiers to be host:port This changes the PublicURL function into InstanceIdentifier, which now returns a simple : string instead of a full URL. --- retrieval/target.go | 31 +++++++++++++++++++++---------- retrieval/target_test.go | 27 +++++++++++++++++---------- retrieval/targetmanager_test.go | 2 +- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/retrieval/target.go b/retrieval/target.go index 030bde0a9..b0aaaf630 100644 --- a/retrieval/target.go +++ b/retrieval/target.go @@ -115,8 +115,8 @@ type Target interface { // points in this interface, this one is the best candidate to change given // the ways to express the endpoint. URL() string - // The URL without any auth data in it, used to label data - PublicURL() string + // Used to populate the `instance` label in metrics. + InstanceIdentifier() string // The URL as seen from other hosts. References to localhost are resolved // to the address of the prometheus server. GlobalURL() string @@ -189,8 +189,8 @@ func (t *target) recordScrapeHealth(ingester extraction.Ingester, timestamp clie } healthMetric[clientmodel.MetricNameLabel] = clientmodel.LabelValue(scrapeHealthMetricName) durationMetric[clientmodel.MetricNameLabel] = clientmodel.LabelValue(scrapeDurationMetricName) - healthMetric[InstanceLabel] = clientmodel.LabelValue(t.PublicURL()) - durationMetric[InstanceLabel] = clientmodel.LabelValue(t.PublicURL()) + healthMetric[InstanceLabel] = clientmodel.LabelValue(t.InstanceIdentifier()) + durationMetric[InstanceLabel] = clientmodel.LabelValue(t.InstanceIdentifier()) healthValue := clientmodel.SampleValue(0) if healthy { @@ -323,7 +323,7 @@ func (t *target) scrape(ingester extraction.Ingester) (err error) { return err } - baseLabels := clientmodel.LabelSet{InstanceLabel: clientmodel.LabelValue(t.PublicURL())} + baseLabels := clientmodel.LabelSet{InstanceLabel: clientmodel.LabelValue(t.InstanceIdentifier())} for baseLabel, baseValue := range t.baseLabels { baseLabels[baseLabel] = baseValue } @@ -366,15 +366,26 @@ func (t *target) URL() string { return t.url } -// PublicURL implements Target. -func (t *target) PublicURL() string { +// InstanceIdentifier implements Target. +func (t *target) InstanceIdentifier() string { u, err := url.Parse(t.url) if err != nil { - glog.Warning("Could not parse URL for auth stripping (%s), returning it unchanged", err) + glog.Warningf("Could not parse instance URL when generating identifier, using raw URL: %s", err) return t.url } - u.User = nil - return u.String() + // If we are given a port in the host port, use that. + if strings.Contains(u.Host, ":") { + return u.Host + } + // Otherwise, deduce port based on protocol. + if u.Scheme == "http" { + return fmt.Sprintf("%s:80", u.Host) + } else if u.Scheme == "https" { + return fmt.Sprintf("%s:443", u.Host) + } + + glog.Warningf("Unknown scheme %s when generating identifier, using raw URL.", u.Scheme) + return t.url } // GlobalURL implements Target. diff --git a/retrieval/target_test.go b/retrieval/target_test.go index 67909e5a7..ddea75ec4 100644 --- a/retrieval/target_test.go +++ b/retrieval/target_test.go @@ -35,15 +35,22 @@ func (i *collectResultIngester) Ingest(s clientmodel.Samples) error { } func TestTargetHidesURLAuth(t *testing.T) { - testTarget := target{ - state: Unknown, - url: "http://secret:data@host.com/query?args#fragment", - httpClient: utility.NewDeadlineClient(0), + testVectors := []string{"http://secret:data@host.com/query?args#fragment", "https://example.net/foo", "http://foo.com:31337/bar"} + testResults := []string{"host.com:80", "example.net:443", "foo.com:31337"} + if len(testVectors) != len(testResults) { + t.Errorf("Test vector length does not match test result length.") } - expected := "http://host.com/query?args#fragment" - u := testTarget.PublicURL() - if u != expected { - t.Errorf("Expected PublicURL to be %v, actual %v", expected, u) + + for i := 0; i < len(testVectors); i++ { + testTarget := target{ + state: Unknown, + url: testVectors[i], + httpClient: utility.NewDeadlineClient(0), + } + u := testTarget.InstanceIdentifier() + if u != testResults[i] { + t.Errorf("Expected InstanceIdentifier to be %v, actual %v", testResults[i], u) + } } } @@ -106,7 +113,7 @@ func TestTargetRecordScrapeHealth(t *testing.T) { expected := &clientmodel.Sample{ Metric: clientmodel.Metric{ clientmodel.MetricNameLabel: scrapeHealthMetricName, - InstanceLabel: "http://example.url", + InstanceLabel: "example.url:80", clientmodel.JobLabel: "testjob", }, Timestamp: now, @@ -121,7 +128,7 @@ func TestTargetRecordScrapeHealth(t *testing.T) { expected = &clientmodel.Sample{ Metric: clientmodel.Metric{ clientmodel.MetricNameLabel: scrapeDurationMetricName, - InstanceLabel: "http://example.url", + InstanceLabel: "example.url:80", clientmodel.JobLabel: "testjob", }, Timestamp: now, diff --git a/retrieval/targetmanager_test.go b/retrieval/targetmanager_test.go index 917b5d3ca..e323a665b 100644 --- a/retrieval/targetmanager_test.go +++ b/retrieval/targetmanager_test.go @@ -42,7 +42,7 @@ func (t fakeTarget) URL() string { return "fake" } -func (t fakeTarget) PublicURL() string { +func (t fakeTarget) InstanceIdentifier() string { return "fake" }