diff --git a/config/config.go b/config/config.go index 91d91db49..ece179305 100644 --- a/config/config.go +++ b/config/config.go @@ -723,6 +723,29 @@ func (c *RelabelConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { // Regexp encapsulates a regexp.Regexp and makes it YAML marshallable. type Regexp struct { regexp.Regexp + original string +} + +// NewRegexp creates a new anchored Regexp and returns an error if the +// passed-in regular expression does not compile. +func NewRegexp(s string) (*Regexp, error) { + regex, err := regexp.Compile("^(?:" + s + ")$") + if err != nil { + return nil, err + } + return &Regexp{ + Regexp: *regex, + original: s, + }, nil +} + +// MustNewRegexp works like NewRegexp, but panics if the regular expression does not compile. +func MustNewRegexp(s string) *Regexp { + re, err := NewRegexp(s) + if err != nil { + panic(err) + } + return re } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -731,18 +754,18 @@ func (re *Regexp) UnmarshalYAML(unmarshal func(interface{}) error) error { if err := unmarshal(&s); err != nil { return err } - regex, err := regexp.Compile(s) + r, err := NewRegexp(s) if err != nil { return err } - re.Regexp = *regex + *re = *r return nil } // MarshalYAML implements the yaml.Marshaler interface. func (re *Regexp) MarshalYAML() (interface{}, error) { if re != nil { - return re.String(), nil + return re.original, nil } return nil, nil } diff --git a/config/config_test.go b/config/config_test.go index 9f7546e02..cbd9034e7 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -17,7 +17,6 @@ import ( "encoding/json" "io/ioutil" "reflect" - "regexp" "strings" "testing" "time" @@ -86,7 +85,7 @@ var expectedConf = &Config{ SourceLabels: model.LabelNames{"job", "__meta_dns_srv_name"}, TargetLabel: "job", Separator: ";", - Regex: &Regexp{*regexp.MustCompile("(.*)some-[regex]$")}, + Regex: MustNewRegexp("(.*)some-[regex]"), Replacement: "foo-${1}", Action: RelabelReplace, }, @@ -126,7 +125,7 @@ var expectedConf = &Config{ RelabelConfigs: []*RelabelConfig{ { SourceLabels: model.LabelNames{"job"}, - Regex: &Regexp{*regexp.MustCompile("(.*)some-[regex]$")}, + Regex: MustNewRegexp("(.*)some-[regex]"), Separator: ";", Action: RelabelDrop, }, @@ -139,7 +138,7 @@ var expectedConf = &Config{ }, { SourceLabels: model.LabelNames{"__tmp_hash"}, - Regex: &Regexp{*regexp.MustCompile("^1$")}, + Regex: MustNewRegexp("1"), Separator: ";", Action: RelabelKeep, }, @@ -147,7 +146,7 @@ var expectedConf = &Config{ MetricRelabelConfigs: []*RelabelConfig{ { SourceLabels: model.LabelNames{"__name__"}, - Regex: &Regexp{*regexp.MustCompile("expensive_metric.*$")}, + Regex: MustNewRegexp("expensive_metric.*"), Separator: ";", Action: RelabelDrop, }, diff --git a/config/testdata/conf.good.yml b/config/testdata/conf.good.yml index 239c507ca..979c79bc3 100644 --- a/config/testdata/conf.good.yml +++ b/config/testdata/conf.good.yml @@ -40,7 +40,7 @@ scrape_configs: relabel_configs: - source_labels: [job, __meta_dns_srv_name] - regex: (.*)some-[regex]$ + regex: (.*)some-[regex] target_label: job replacement: foo-${1} # action defaults to 'replace' @@ -71,19 +71,19 @@ scrape_configs: relabel_configs: - source_labels: [job] - regex: (.*)some-[regex]$ + regex: (.*)some-[regex] action: drop - source_labels: [__address__] modulus: 8 target_label: __tmp_hash action: hashmod - source_labels: [__tmp_hash] - regex: ^1$ + regex: 1 action: keep metric_relabel_configs: - source_labels: [__name__] - regex: expensive_metric.*$ + regex: expensive_metric.* action: drop - job_name: service-y diff --git a/retrieval/relabel_test.go b/retrieval/relabel_test.go index 90eb21347..633b83b4e 100644 --- a/retrieval/relabel_test.go +++ b/retrieval/relabel_test.go @@ -15,7 +15,6 @@ package retrieval import ( "reflect" - "regexp" "testing" "github.com/prometheus/common/model" @@ -38,7 +37,7 @@ func TestRelabel(t *testing.T) { relabel: []*config.RelabelConfig{ { SourceLabels: model.LabelNames{"a"}, - Regex: &config.Regexp{*regexp.MustCompile("f(.*)")}, + Regex: config.MustNewRegexp("f(.*)"), TargetLabel: model.LabelName("d"), Separator: ";", Replacement: "ch${1}-ch${1}", @@ -61,7 +60,7 @@ func TestRelabel(t *testing.T) { relabel: []*config.RelabelConfig{ { SourceLabels: model.LabelNames{"a", "b"}, - Regex: &config.Regexp{*regexp.MustCompile("^f(.*);(.*)r$")}, + Regex: config.MustNewRegexp("f(.*);(.*)r"), TargetLabel: model.LabelName("a"), Separator: ";", Replacement: "b${1}${2}m", // boobam @@ -69,7 +68,7 @@ func TestRelabel(t *testing.T) { }, { SourceLabels: model.LabelNames{"c", "a"}, - Regex: &config.Regexp{*regexp.MustCompile("(b).*b(.*)ba(.*)")}, + Regex: config.MustNewRegexp("(b).*b(.*)ba(.*)"), TargetLabel: model.LabelName("d"), Separator: ";", Replacement: "$1$2$2$3", @@ -90,11 +89,11 @@ func TestRelabel(t *testing.T) { relabel: []*config.RelabelConfig{ { SourceLabels: model.LabelNames{"a"}, - Regex: &config.Regexp{*regexp.MustCompile("o$")}, + Regex: config.MustNewRegexp(".*o.*"), Action: config.RelabelDrop, }, { SourceLabels: model.LabelNames{"a"}, - Regex: &config.Regexp{*regexp.MustCompile("f(.*)")}, + Regex: config.MustNewRegexp("f(.*)"), TargetLabel: model.LabelName("d"), Separator: ";", Replacement: "ch$1-ch$1", @@ -110,7 +109,7 @@ func TestRelabel(t *testing.T) { relabel: []*config.RelabelConfig{ { SourceLabels: model.LabelNames{"a"}, - Regex: &config.Regexp{*regexp.MustCompile("(b)")}, + Regex: config.MustNewRegexp(".*(b).*"), TargetLabel: model.LabelName("d"), Separator: ";", Replacement: "$1", @@ -129,7 +128,7 @@ func TestRelabel(t *testing.T) { relabel: []*config.RelabelConfig{ { SourceLabels: model.LabelNames{"a"}, - Regex: &config.Regexp{*regexp.MustCompile("no-match")}, + Regex: config.MustNewRegexp("no-match"), Action: config.RelabelDrop, }, }, @@ -144,7 +143,22 @@ func TestRelabel(t *testing.T) { relabel: []*config.RelabelConfig{ { SourceLabels: model.LabelNames{"a"}, - Regex: &config.Regexp{*regexp.MustCompile("no-match")}, + Regex: config.MustNewRegexp("f|o"), + Action: config.RelabelDrop, + }, + }, + output: model.LabelSet{ + "a": "foo", + }, + }, + { + input: model.LabelSet{ + "a": "foo", + }, + relabel: []*config.RelabelConfig{ + { + SourceLabels: model.LabelNames{"a"}, + Regex: config.MustNewRegexp("no-match"), Action: config.RelabelKeep, }, }, @@ -157,7 +171,7 @@ func TestRelabel(t *testing.T) { relabel: []*config.RelabelConfig{ { SourceLabels: model.LabelNames{"a"}, - Regex: &config.Regexp{*regexp.MustCompile("^f")}, + Regex: config.MustNewRegexp("f.*"), Action: config.RelabelKeep, }, }, @@ -173,7 +187,7 @@ func TestRelabel(t *testing.T) { relabel: []*config.RelabelConfig{ { SourceLabels: model.LabelNames{"a"}, - Regex: &config.Regexp{*regexp.MustCompile("^f")}, + Regex: config.MustNewRegexp("f"), TargetLabel: model.LabelName("b"), Replacement: "bar", Action: config.RelabelReplace, @@ -213,7 +227,7 @@ func TestRelabel(t *testing.T) { }, relabel: []*config.RelabelConfig{ { - Regex: &config.Regexp{*regexp.MustCompile("^(b.*)")}, + Regex: config.MustNewRegexp("(b.*)"), Replacement: "bar_${1}", Action: config.RelabelLabelMap, }, @@ -235,7 +249,7 @@ func TestRelabel(t *testing.T) { }, relabel: []*config.RelabelConfig{ { - Regex: &config.Regexp{*regexp.MustCompile("^__meta_(my.*)")}, + Regex: config.MustNewRegexp("__meta_(my.*)"), Replacement: "${1}", Action: config.RelabelLabelMap, }, diff --git a/retrieval/target_test.go b/retrieval/target_test.go index 94278dd87..4b7518343 100644 --- a/retrieval/target_test.go +++ b/retrieval/target_test.go @@ -23,7 +23,6 @@ import ( "net/http/httptest" "net/url" "reflect" - "regexp" "strings" "testing" "time" @@ -181,12 +180,12 @@ func TestTargetScrapeMetricRelabelConfigs(t *testing.T) { testTarget.metricRelabelConfigs = []*config.RelabelConfig{ { SourceLabels: model.LabelNames{"__name__"}, - Regex: &config.Regexp{*regexp.MustCompile(".*drop.*")}, + Regex: config.MustNewRegexp(".*drop.*"), Action: config.RelabelDrop, }, { SourceLabels: model.LabelNames{"__name__"}, - Regex: &config.Regexp{*regexp.MustCompile(".*(relabel|up).*")}, + Regex: config.MustNewRegexp(".*(relabel|up).*"), TargetLabel: "foo", Replacement: "bar", Action: config.RelabelReplace, diff --git a/retrieval/targetmanager_test.go b/retrieval/targetmanager_test.go index 2ba8666b0..f6b9344ea 100644 --- a/retrieval/targetmanager_test.go +++ b/retrieval/targetmanager_test.go @@ -16,7 +16,6 @@ package retrieval import ( "net/url" "reflect" - "regexp" "testing" "time" @@ -219,7 +218,7 @@ func TestTargetManagerConfigUpdate(t *testing.T) { { // Copy out the URL parameter. SourceLabels: model.LabelNames{"__param_testParam"}, - Regex: &config.Regexp{*regexp.MustCompile("^(.*)$")}, + Regex: config.MustNewRegexp("(.*)"), TargetLabel: "testParam", Replacement: "$1", Action: config.RelabelReplace, @@ -255,7 +254,7 @@ func TestTargetManagerConfigUpdate(t *testing.T) { RelabelConfigs: []*config.RelabelConfig{ { SourceLabels: model.LabelNames{model.AddressLabel}, - Regex: &config.Regexp{*regexp.MustCompile(`^test\.(.*?):(.*)`)}, + Regex: config.MustNewRegexp(`test\.(.*?):(.*)`), Replacement: "foo.${1}:${2}", TargetLabel: model.AddressLabel, Action: config.RelabelReplace, @@ -263,7 +262,7 @@ func TestTargetManagerConfigUpdate(t *testing.T) { { // Add a new label for example.* targets. SourceLabels: model.LabelNames{model.AddressLabel, "boom", "foo"}, - Regex: &config.Regexp{*regexp.MustCompile("^example.*?-b([a-z-]+)r$")}, + Regex: config.MustNewRegexp("example.*?-b([a-z-]+)r"), TargetLabel: "new", Replacement: "$1", Separator: "-", @@ -272,7 +271,7 @@ func TestTargetManagerConfigUpdate(t *testing.T) { { // Drop an existing label. SourceLabels: model.LabelNames{"boom"}, - Regex: &config.Regexp{*regexp.MustCompile(".*")}, + Regex: config.MustNewRegexp(".*"), TargetLabel: "boom", Replacement: "", Action: config.RelabelReplace,