Add option to disable labels in prometheus output for string fields (#3765)

This commit is contained in:
S 2018-02-16 23:07:26 +01:00 committed by Daniel Nelson
parent c48b15e620
commit 17e1bff028
3 changed files with 52 additions and 5 deletions

View File

@ -23,4 +23,8 @@ This plugin starts a [Prometheus](https://prometheus.io/) Client, it exposes all
# Expiration interval for each metric. 0 == no expiration # Expiration interval for each metric. 0 == no expiration
expiration_interval = "60s" expiration_interval = "60s"
# Send string metrics as Prometheus labels.
# Unless set to false all string metrics will be sent as labels.
string_as_label = true
``` ```

View File

@ -61,6 +61,7 @@ type PrometheusClient struct {
ExpirationInterval internal.Duration `toml:"expiration_interval"` ExpirationInterval internal.Duration `toml:"expiration_interval"`
Path string `toml:"path"` Path string `toml:"path"`
CollectorsExclude []string `toml:"collectors_exclude"` CollectorsExclude []string `toml:"collectors_exclude"`
StringAsLabel bool `toml:"string_as_label"`
server *http.Server server *http.Server
@ -89,6 +90,10 @@ var sampleConfig = `
## Collectors to enable, valid entries are "gocollector" and "process". ## Collectors to enable, valid entries are "gocollector" and "process".
## If unset, both are enabled. ## If unset, both are enabled.
collectors_exclude = ["gocollector", "process"] collectors_exclude = ["gocollector", "process"]
# Send string metrics as Prometheus labels.
# Unless set to false all string metrics will be sent as labels.
string_as_label = true
` `
func (p *PrometheusClient) basicAuth(h http.Handler) http.Handler { func (p *PrometheusClient) basicAuth(h http.Handler) http.Handler {
@ -326,11 +331,13 @@ func (p *PrometheusClient) Write(metrics []telegraf.Metric) error {
} }
// Prometheus doesn't have a string value type, so convert string // Prometheus doesn't have a string value type, so convert string
// fields to labels. // fields to labels if enabled.
for fn, fv := range point.Fields() { if p.StringAsLabel {
switch fv := fv.(type) { for fn, fv := range point.Fields() {
case string: switch fv := fv.(type) {
labels[sanitize(fn)] = fv case string:
labels[sanitize(fn)] = fv
}
} }
} }
@ -465,6 +472,7 @@ func init() {
outputs.Add("prometheus_client", func() telegraf.Output { outputs.Add("prometheus_client", func() telegraf.Output {
return &PrometheusClient{ return &PrometheusClient{
ExpirationInterval: internal.Duration{Duration: time.Second * 60}, ExpirationInterval: internal.Duration{Duration: time.Second * 60},
StringAsLabel: true,
fam: make(map[string]*MetricFamily), fam: make(map[string]*MetricFamily),
now: time.Now, now: time.Now,
} }

View File

@ -22,6 +22,7 @@ func setUnixTime(client *PrometheusClient, sec int64) {
func NewClient() *PrometheusClient { func NewClient() *PrometheusClient {
return &PrometheusClient{ return &PrometheusClient{
ExpirationInterval: internal.Duration{Duration: time.Second * 60}, ExpirationInterval: internal.Duration{Duration: time.Second * 60},
StringAsLabel: true,
fam: make(map[string]*MetricFamily), fam: make(map[string]*MetricFamily),
now: time.Now, now: time.Now,
} }
@ -450,6 +451,40 @@ func TestWrite_StringFields(t *testing.T) {
require.False(t, ok) require.False(t, ok)
} }
func TestDoNotWrite_StringFields(t *testing.T) {
now := time.Now()
p1, err := metric.New(
"foo",
make(map[string]string),
map[string]interface{}{"value": 1.0, "status": "good"},
now,
telegraf.Counter)
p2, err := metric.New(
"bar",
make(map[string]string),
map[string]interface{}{"status": "needs numeric field"},
now,
telegraf.Gauge)
var metrics = []telegraf.Metric{p1, p2}
client := &PrometheusClient{
ExpirationInterval: internal.Duration{Duration: time.Second * 60},
StringAsLabel: false,
fam: make(map[string]*MetricFamily),
now: time.Now,
}
err = client.Write(metrics)
require.NoError(t, err)
fam, ok := client.fam["foo"]
require.True(t, ok)
require.Equal(t, 0, fam.LabelSet["status"])
fam, ok = client.fam["bar"]
require.False(t, ok)
}
func TestExpire(t *testing.T) { func TestExpire(t *testing.T) {
client := NewClient() client := NewClient()