From 79b553499ac0d5a0b155e30dcb322a8a7ed2550e Mon Sep 17 00:00:00 2001 From: 1seal Date: Thu, 29 Jan 2026 11:59:35 +0000 Subject: [PATCH] web/api: compute relabel_steps in single pass Signed-off-by: 1seal --- web/api/v1/api.go | 16 ++++++++---- web/api/v1/api_test.go | 56 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/web/api/v1/api.go b/web/api/v1/api.go index f32fee19f8..07ce482a40 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -1346,13 +1346,19 @@ func (api *API) targetRelabelSteps(r *http.Request) apiFuncResult { rules := scrapeConfig.RelabelConfigs steps := make([]RelabelStep, len(rules)) + lb := labels.NewBuilder(lbls) + keep := true for i, rule := range rules { - outLabels, keep := relabel.Process(lbls, rules[:i+1]...) - steps[i] = RelabelStep{ - Rule: rule, - Output: outLabels, - Keep: keep, + if keep { + keep = relabel.ProcessBuilder(lb, rule) } + + outLabels := labels.EmptyLabels() + if keep { + outLabels = lb.Labels() + } + + steps[i] = RelabelStep{Rule: rule, Output: outLabels, Keep: keep} } return apiFuncResult{&RelabelStepsResponse{Steps: steps}, nil, nil, nil} diff --git a/web/api/v1/api_test.go b/web/api/v1/api_test.go index 797182ce88..96d1cec531 100644 --- a/web/api/v1/api_test.go +++ b/web/api/v1/api_test.go @@ -166,8 +166,8 @@ func (t testTargetRetriever) TargetsDroppedCounts() map[string]int { return r } -func (testTargetRetriever) ScrapePoolConfig(_ string) (*config.ScrapeConfig, error) { - return &config.ScrapeConfig{ +func (testTargetRetriever) ScrapePoolConfig(pool string) (*config.ScrapeConfig, error) { + cfg := &config.ScrapeConfig{ RelabelConfigs: []*relabel.Config{ { Action: relabel.Replace, @@ -182,7 +182,16 @@ func (testTargetRetriever) ScrapePoolConfig(_ string) (*config.ScrapeConfig, err Regex: relabel.MustNewRegexp(`example\.com:.*`), }, }, - }, nil + } + if pool == "testpool3" { + cfg.RelabelConfigs = append(cfg.RelabelConfigs, &relabel.Config{ + Action: relabel.Replace, + TargetLabel: "job", + Regex: relabel.MustNewRegexp(".*"), + Replacement: "should_not_apply", + }) + } + return cfg, nil } func (t *testTargetRetriever) SetMetadataStoreForTargets(identifier string, metadata scrape.MetricMetadataStore) error { @@ -1937,6 +1946,47 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI }, }, }, + { + endpoint: api.targetRelabelSteps, + query: url.Values{"scrapePool": []string{"testpool3"}, "labels": []string{`{"job":"test","__address__":"localhost:9090"}`}}, + response: &RelabelStepsResponse{ + Steps: []RelabelStep{ + { + Rule: &relabel.Config{ + Action: relabel.Replace, + Replacement: "example.com:443", + TargetLabel: "__address__", + Regex: relabel.MustNewRegexp(""), + NameValidationScheme: model.LegacyValidation, + }, + Output: labels.FromMap(map[string]string{ + "job": "test", + "__address__": "example.com:443", + }), + Keep: true, + }, + { + Rule: &relabel.Config{ + Action: relabel.Drop, + SourceLabels: []model.LabelName{"__address__"}, + Regex: relabel.MustNewRegexp(`example\.com:.*`), + }, + Output: labels.EmptyLabels(), + Keep: false, + }, + { + Rule: &relabel.Config{ + Action: relabel.Replace, + TargetLabel: "job", + Regex: relabel.MustNewRegexp(".*"), + Replacement: "should_not_apply", + }, + Output: labels.EmptyLabels(), + Keep: false, + }, + }, + }, + }, // With a matching metric. { endpoint: api.targetMetadata,