diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 7e6bb0edf..7c1475aba 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -44,23 +44,19 @@ }, { "ImportPath": "github.com/prometheus/client_golang/extraction", - "Comment": "0.7.0", - "Rev": "6dbab8106ed3ed77359ac85d9cf08e30290df864" + "Rev": "3a499bf7fc46bc58337ce612d0cbb29c550b8118" }, { "ImportPath": "github.com/prometheus/client_golang/model", - "Comment": "0.7.0", - "Rev": "6dbab8106ed3ed77359ac85d9cf08e30290df864" + "Rev": "3a499bf7fc46bc58337ce612d0cbb29c550b8118" }, { "ImportPath": "github.com/prometheus/client_golang/prometheus", - "Comment": "0.7.0", - "Rev": "6dbab8106ed3ed77359ac85d9cf08e30290df864" + "Rev": "3a499bf7fc46bc58337ce612d0cbb29c550b8118" }, { "ImportPath": "github.com/prometheus/client_golang/text", - "Comment": "0.7.0", - "Rev": "6dbab8106ed3ed77359ac85d9cf08e30290df864" + "Rev": "3a499bf7fc46bc58337ce612d0cbb29c550b8118" }, { "ImportPath": "github.com/prometheus/client_model/go", diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/model/labelname.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/model/labelname.go index 7d071bd72..f41b7ff4a 100644 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/model/labelname.go +++ b/Godeps/_workspace/src/github.com/prometheus/client_golang/model/labelname.go @@ -46,6 +46,10 @@ const ( // will not be attached to time series. MetaLabelPrefix = "__meta_" + // ParamLabelPrefix is a prefix for labels that provide URL parameters + // used to scrape a target. + ParamLabelPrefix = "__param_" + // JobLabel is the label name indicating the job from which a timeseries // was scraped. JobLabel LabelName = "job" diff --git a/retrieval/target.go b/retrieval/target.go index eb3b33e45..0ab77a47d 100644 --- a/retrieval/target.go +++ b/retrieval/target.go @@ -197,10 +197,24 @@ func (t *Target) Update(cfg *config.ScrapeConfig, baseLabels, metaLabels clientm t.url.Scheme = cfg.Scheme t.url.Path = string(baseLabels[clientmodel.MetricsPathLabel]) + params := url.Values{} + for k, v := range cfg.Params { + params[k] = make([]string, len(v)) + copy(params[k], v) + } + for k, v := range baseLabels { + if strings.HasPrefix(string(k), clientmodel.ParamLabelPrefix) { + if len(params[string(k[len(clientmodel.ParamLabelPrefix):])]) > 0 { + params[string(k[len(clientmodel.ParamLabelPrefix):])][0] = string(v) + } else { + params[string(k[len(clientmodel.ParamLabelPrefix):])] = []string{string(v)} + } + } + } + t.url.RawQuery = params.Encode() if cfg.BasicAuth != nil { t.url.User = url.UserPassword(cfg.BasicAuth.Username, cfg.BasicAuth.Password) } - t.url.RawQuery = cfg.Params.Encode() t.scrapeInterval = time.Duration(cfg.ScrapeInterval) t.deadline = time.Duration(cfg.ScrapeTimeout) diff --git a/retrieval/target_test.go b/retrieval/target_test.go index 02a251105..bcf2469c2 100644 --- a/retrieval/target_test.go +++ b/retrieval/target_test.go @@ -390,6 +390,49 @@ func BenchmarkScrape(b *testing.B) { } } +func TestURLParams(t *testing.T) { + server := httptest.NewServer( + http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", `text/plain; version=0.0.4`) + w.Write([]byte{}) + r.ParseForm() + if r.Form["foo"][0] != "bar" { + t.Fatalf("URL parameter 'foo' had unexpected first value '%v'", r.Form["foo"][0]) + } + if r.Form["foo"][1] != "baz" { + t.Fatalf("URL parameter 'foo' had unexpected second value '%v'", r.Form["foo"][1]) + } + }, + ), + ) + defer server.Close() + serverURL, err := url.Parse(server.URL) + if err != nil { + t.Fatal(err) + } + + target := NewTarget( + &config.ScrapeConfig{ + JobName: "test_job1", + ScrapeInterval: config.Duration(1 * time.Minute), + ScrapeTimeout: config.Duration(1 * time.Second), + Scheme: serverURL.Scheme, + Params: url.Values{ + "foo": []string{"bar", "baz"}, + }, + }, + clientmodel.LabelSet{ + clientmodel.AddressLabel: clientmodel.LabelValue(serverURL.Host), + "__param_foo": "bar", + }, + nil) + app := &collectResultAppender{} + if err = target.scrape(app); err != nil { + t.Fatal(err) + } +} + func newTestTarget(targetURL string, deadline time.Duration, baseLabels clientmodel.LabelSet) *Target { t := &Target{ url: &url.URL{ diff --git a/retrieval/targetmanager.go b/retrieval/targetmanager.go index dfb3de2b9..1a18b0236 100644 --- a/retrieval/targetmanager.go +++ b/retrieval/targetmanager.go @@ -329,6 +329,11 @@ func (tm *TargetManager) targetsFromGroup(tg *config.TargetGroup, cfg *config.Sc } labels[clientmodel.AddressLabel] = clientmodel.LabelValue(addr) } + for k, v := range cfg.Params { + if len(v) > 0 { + labels[clientmodel.LabelName(clientmodel.ParamLabelPrefix+k)] = clientmodel.LabelValue(v[0]) + } + } // Copy labels into the labelset for the target if they are not // set already. Apply the labelsets in order of decreasing precedence. labelsets := []clientmodel.LabelSet{ diff --git a/retrieval/targetmanager_test.go b/retrieval/targetmanager_test.go index 886364b5c..07c415745 100644 --- a/retrieval/targetmanager_test.go +++ b/retrieval/targetmanager_test.go @@ -14,6 +14,7 @@ package retrieval import ( + "net/url" "reflect" "regexp" "testing" @@ -157,12 +158,25 @@ func TestTargetManagerConfigUpdate(t *testing.T) { testJob1 := &config.ScrapeConfig{ JobName: "test_job1", ScrapeInterval: config.Duration(1 * time.Minute), + Params: url.Values{ + "testParam": []string{"paramValue", "secondValue"}, + }, TargetGroups: []*config.TargetGroup{{ Targets: []clientmodel.LabelSet{ {clientmodel.AddressLabel: "example.org:80"}, {clientmodel.AddressLabel: "example.com:80"}, }, }}, + RelabelConfigs: []*config.RelabelConfig{ + { + // Copy out the URL parameter. + SourceLabels: clientmodel.LabelNames{"__param_testParam"}, + Regex: &config.Regexp{*regexp.MustCompile("^(.*)$")}, + TargetLabel: "testParam", + Replacement: "$1", + Action: config.RelabelReplace, + }, + }, } testJob2 := &config.ScrapeConfig{ JobName: "test_job2", @@ -226,24 +240,24 @@ func TestTargetManagerConfigUpdate(t *testing.T) { scrapeConfigs: []*config.ScrapeConfig{testJob1}, expected: map[string][]clientmodel.LabelSet{ "test_job1:static:0": { - {clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.org:80"}, - {clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.com:80"}, + {clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.org:80", "testParam": "paramValue"}, + {clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.com:80", "testParam": "paramValue"}, }, }, }, { scrapeConfigs: []*config.ScrapeConfig{testJob1}, expected: map[string][]clientmodel.LabelSet{ "test_job1:static:0": { - {clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.org:80"}, - {clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.com:80"}, + {clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.org:80", "testParam": "paramValue"}, + {clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.com:80", "testParam": "paramValue"}, }, }, }, { scrapeConfigs: []*config.ScrapeConfig{testJob1, testJob2}, expected: map[string][]clientmodel.LabelSet{ "test_job1:static:0": { - {clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.org:80"}, - {clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.com:80"}, + {clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.org:80", "testParam": "paramValue"}, + {clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.com:80", "testParam": "paramValue"}, }, "test_job2:static:0": { {clientmodel.JobLabel: "test_job2", clientmodel.InstanceLabel: "example.org:8080", "foo": "bar", "new": "ox-ba"},