Merge pull request #117 from erickpintor/dynamic-metric-name

Allow for dynamic metric name
This commit is contained in:
Matthias Rampke 2018-01-17 18:09:07 +01:00 committed by GitHub
commit 9180cd3afd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 7 deletions

View file

@ -123,7 +123,32 @@ 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"
```
The metric name can also contain references to regex matches. The mapping above
could be written as:
```
mappings:
- match: test\.(\w+)\.(\w+)\.counter
match_type: regex
name: "${2}_counter"
labels:
provider: "$1"
```
Please note that metrics with the same name must also have the same set of
labels names.
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: `---