allow for dynamic metric name

This commit is contained in:
Erick Pintor 2018-01-16 11:16:15 -02:00
parent d96145e47f
commit 27ee4050c4
4 changed files with 52 additions and 7 deletions

View file

@ -123,7 +123,17 @@ follows:
test.web-server.foo.bar
=> test_web_server_foo_bar{}
Each mapping in the configuration file must define a `name` for the metric.
Each mapping in the configuration file must define a `name` for the metric. The
metric's name can contain `$n`-style references to be replaced by the n-th
wildcard match in the matching line. That allows for dynamic rewrites, such as:
```yaml
mappings:
- match: test.*.*.counter
name: "${2}_counter"
labels:
provider: "$1"
```
If the default metric help text is insufficient for your needs you may use the YAML
configuration to specify a custom help text for each mapping:

View file

@ -263,7 +263,7 @@ func (b *Exporter) Listen(e <-chan Events) {
help = mapping.HelpText
}
if present {
metricName = mapping.Name
metricName = escapeMetricName(mapping.Name)
for label, value := range labels {
prometheusLabels[label] = value
}

View file

@ -25,12 +25,12 @@ import (
)
var (
identifierRE = `[a-zA-Z_][a-zA-Z0-9_]+`
statsdMetricRE = `[a-zA-Z_](-?[a-zA-Z0-9_])+`
statsdMetricRE = `[a-zA-Z_](-?[a-zA-Z0-9_])+`
templateReplaceRE = `(\$\{?\d+\}?)`
metricLineRE = regexp.MustCompile(`^(\*\.|` + statsdMetricRE + `\.)+(\*|` + statsdMetricRE + `)$`)
labelLineRE = regexp.MustCompile(`^(` + identifierRE + `)\s*=\s*"(.*)"$`)
metricNameRE = regexp.MustCompile(`^` + identifierRE + `$`)
metricNameRE = regexp.MustCompile(`^([a-zA-Z_]|` + templateReplaceRE + `)([a-zA-Z0-9_]|` + templateReplaceRE + `)*$`)
labelNameRE = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]+$`)
)
type mapperConfigDefaults struct {
@ -77,7 +77,7 @@ func (m *metricMapper) initFromYAMLString(fileContents string) error {
// check that label is correct
for k := range currentMapping.Labels {
if !metricNameRE.MatchString(k) {
if !labelNameRE.MatchString(k) {
return fmt.Errorf("invalid label key: %s", k)
}
}
@ -150,11 +150,19 @@ func (m *metricMapper) getMapping(statsdMetric string) (*metricMapping, promethe
continue
}
mapping.Name = string(mapping.regex.ExpandString(
[]byte{},
mapping.Name,
statsdMetric,
matches,
))
labels := prometheus.Labels{}
for label, valueExpr := range mapping.Labels {
value := mapping.regex.ExpandString([]byte{}, valueExpr, statsdMetric, matches)
labels[label] = string(value)
}
return &mapping, labels, true
}

View file

@ -184,6 +184,33 @@ mappings:
`,
configBad: true,
},
// Config with dynamic metric name.
{
config: `---
mappings:
- match: test1.*.*
name: "$1"
labels: {}
- match: test2.*.*
name: "${1}_$2"
labels: {}
- match: test3\.(\w+)\.(\w+)
match_type: regex
name: "${2}_$1"
labels: {}
`,
mappings: mappings{
"test1.total_requests.count": {
name: "total_requests",
},
"test2.total_requests.count": {
name: "total_requests_count",
},
"test3.total_requests.count": {
name: "count_total_requests",
},
},
},
// Config with bad metric name.
{
config: `---