From 13600366cfc6340ca353d34ec32145c17931ca16 Mon Sep 17 00:00:00 2001 From: david birdsong Date: Fri, 4 Mar 2016 20:05:10 +0000 Subject: [PATCH] fix prometheus output if i understand the prometheus data model correctly, the current output for this plugin is unusable prometheus only accepts a single value per measurement. prior to this change, the range loop causes a measurement to end up w/ a random value for instance: net,dc=sjc1,grp_dashboard=1,grp_home=1,grp_hwy_fetcher=1,grp_web_admin=1,host=sjc1-b4-8,hw=app,interface=docker0,state=live bytes_recv=477596i,bytes_sent=152963303i,drop_in=0i,drop_out=0i,err_in=0i,err_out=0i,packets_recv=7231i,packets_sent=11460i 1457121990003778992 this 'net' measurent would have all it's tags copied to prometheus labels, but any of 152963303, or 0, or 7231 as a value for 'net' depending on which field is last in the map iteration this change expands the fields into new measurements by appending the field name to the influxdb measurement name. ie, the above example results with 'net' dropped and new measurements to take it's place: net_bytes_recv net_bytes_sent net_drop_in net_err_in net_packets_recv net_packets_sent i hope this can be merged, i love telegraf's composability of tags and filtering --- .../prometheus_client/prometheus_client.go | 35 ++++++++++--------- .../prometheus_client_test.go | 8 ++--- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/plugins/outputs/prometheus_client/prometheus_client.go b/plugins/outputs/prometheus_client/prometheus_client.go index df546c192..50a9224cd 100644 --- a/plugins/outputs/prometheus_client/prometheus_client.go +++ b/plugins/outputs/prometheus_client/prometheus_client.go @@ -73,42 +73,43 @@ func (p *PrometheusClient) Write(metrics []telegraf.Metric) error { } } - if _, ok := p.metrics[key]; !ok { - p.metrics[key] = prometheus.NewUntypedVec( - prometheus.UntypedOpts{ - Name: key, - Help: fmt.Sprintf("Telegraf collected point '%s'", key), - }, - labels, - ) - prometheus.MustRegister(p.metrics[key]) - } - l := prometheus.Labels{} for tk, tv := range point.Tags() { l[tk] = tv } - for _, val := range point.Fields() { + for n, val := range point.Fields() { + mname := fmt.Sprintf("%s_%s", key, n) + if _, ok := p.metrics[mname]; !ok { + p.metrics[mname] = prometheus.NewUntypedVec( + prometheus.UntypedOpts{ + Name: mname, + Help: fmt.Sprintf("Telegraf collected point '%s'", mname), + }, + labels, + ) + prometheus.MustRegister(p.metrics[mname]) + } + switch val := val.(type) { default: log.Printf("Prometheus output, unsupported type. key: %s, type: %T\n", - key, val) + mname, val) case int64: - m, err := p.metrics[key].GetMetricWith(l) + m, err := p.metrics[mname].GetMetricWith(l) if err != nil { log.Printf("ERROR Getting metric in Prometheus output, "+ "key: %s, labels: %v,\nerr: %s\n", - key, l, err.Error()) + mname, l, err.Error()) continue } m.Set(float64(val)) case float64: - m, err := p.metrics[key].GetMetricWith(l) + m, err := p.metrics[mname].GetMetricWith(l) if err != nil { log.Printf("ERROR Getting metric in Prometheus output, "+ "key: %s, labels: %v,\nerr: %s\n", - key, l, err.Error()) + mname, l, err.Error()) continue } m.Set(val) diff --git a/plugins/outputs/prometheus_client/prometheus_client_test.go b/plugins/outputs/prometheus_client/prometheus_client_test.go index 16414a8e4..5793e1569 100644 --- a/plugins/outputs/prometheus_client/prometheus_client_test.go +++ b/plugins/outputs/prometheus_client/prometheus_client_test.go @@ -46,8 +46,8 @@ func TestPrometheusWritePointEmptyTag(t *testing.T) { value float64 tags map[string]string }{ - {"test_point_1", 0.0, tags}, - {"test_point_2", 1.0, tags}, + {"test_point_1_value", 0.0, tags}, + {"test_point_2_value", 1.0, tags}, } var acc testutil.Accumulator @@ -78,8 +78,8 @@ func TestPrometheusWritePointEmptyTag(t *testing.T) { name string value float64 }{ - {"test_point_3", 0.0}, - {"test_point_4", 1.0}, + {"test_point_3_value", 0.0}, + {"test_point_4_value", 1.0}, } require.NoError(t, p.Gather(&acc))