From 337aed06a6d6b80ca09f88d6edc0066cedfe1c26 Mon Sep 17 00:00:00 2001 From: Cyril Tovena Date: Thu, 8 Jul 2021 16:14:09 +0200 Subject: [PATCH] Fixes negative gauge in Promtail. (#3971) * Fixes negative gauge in Promtail. Fixes #3281 Signed-off-by: Cyril Tovena * got linted. Signed-off-by: Cyril Tovena --- clients/pkg/logentry/stages/metrics.go | 11 +++--- clients/pkg/logentry/stages/metrics_test.go | 42 ++++++++++++++++++++- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/clients/pkg/logentry/stages/metrics.go b/clients/pkg/logentry/stages/metrics.go index 8dd61139dcd34..e93c87419a592 100644 --- a/clients/pkg/logentry/stages/metrics.go +++ b/clients/pkg/logentry/stages/metrics.go @@ -48,7 +48,7 @@ func validateMetricsConfig(cfg MetricsConfig) error { return errors.New(ErrEmptyMetricsStageConfig) } for name, config := range cfg { - //If the source is not defined, default to the metric name + // If the source is not defined, default to the metric name if config.Source == nil { cp := cfg[name] nm := name @@ -201,7 +201,7 @@ func (m *metricStage) recordCounter(name string, counter *metric.Counters, label counter.With(labels).Inc() case metric.CounterAdd: f, err := getFloat(v) - if err != nil || f < 0 { + if err != nil { if Debug { level.Debug(m.logger).Log("msg", "failed to convert extracted value to positive float", "metric", name, "err", err) } @@ -232,7 +232,7 @@ func (m *metricStage) recordGauge(name string, gauge *metric.Gauges, labels mode switch gauge.Cfg.Action { case metric.GaugeSet: f, err := getFloat(v) - if err != nil || f < 0 { + if err != nil { if Debug { level.Debug(m.logger).Log("msg", "failed to convert extracted value to positive float", "metric", name, "err", err) } @@ -245,7 +245,7 @@ func (m *metricStage) recordGauge(name string, gauge *metric.Gauges, labels mode gauge.With(labels).Dec() case metric.GaugeAdd: f, err := getFloat(v) - if err != nil || f < 0 { + if err != nil { if Debug { level.Debug(m.logger).Log("msg", "failed to convert extracted value to positive float", "metric", name, "err", err) } @@ -254,7 +254,7 @@ func (m *metricStage) recordGauge(name string, gauge *metric.Gauges, labels mode gauge.With(labels).Add(f) case metric.GaugeSub: f, err := getFloat(v) - if err != nil || f < 0 { + if err != nil { if Debug { level.Debug(m.logger).Log("msg", "failed to convert extracted value to positive float", "metric", name, "err", err) } @@ -293,7 +293,6 @@ func (m *metricStage) recordHistogram(name string, histogram *metric.Histograms, // getFloat will take the provided value and return a float64 if possible func getFloat(unk interface{}) (float64, error) { - switch i := unk.(type) { case float64: return i, nil diff --git a/clients/pkg/logentry/stages/metrics_test.go b/clients/pkg/logentry/stages/metrics_test.go index 39dbf93ab140c..41461f9077f5c 100644 --- a/clients/pkg/logentry/stages/metrics_test.go +++ b/clients/pkg/logentry/stages/metrics_test.go @@ -69,6 +69,7 @@ var testMetricLogLine1 = ` "level" : "WARN" } ` + var testMetricLogLine2 = ` { "time":"2012-11-01T22:08:41+00:00", @@ -78,6 +79,7 @@ var testMetricLogLine2 = ` "level" : "WARN" } ` + var testMetricLogLineWithMissingKey = ` { "time":"2012-11-01T22:08:41+00:00", @@ -125,6 +127,40 @@ func TestMetricsPipeline(t *testing.T) { } } +func TestNegativeGauge(t *testing.T) { + registry := prometheus.NewRegistry() + testConfig := ` +pipeline_stages: +- regex: + expression: 'vehicle=(?P\d+) longitude=(?P[-]?\d+\.\d+) latitude=(?P\d+\.\d+)' +- labels: + vehicle: +- metrics: + longitude: + type: Gauge + description: "longitude GPS vehicle" + source: longitude + config: + match_all: true + action: set + +` + pl, err := NewPipeline(util_log.Logger, loadConfig(testConfig), nil, registry) + if err != nil { + t.Fatal(err) + } + + <-pl.Run(withInboundEntries(newEntry(nil, model.LabelSet{"test": "app"}, `#<13>Jan 28 14:25:52 vehicle=1 longitude=-10.1234 latitude=15.1234`, time.Now()))) + if err := testutil.GatherAndCompare(registry, + strings.NewReader(` +# HELP promtail_custom_longitude longitude GPS vehicle +# TYPE promtail_custom_longitude gauge +promtail_custom_longitude{test="app",vehicle="1"} -10.1234 +`)); err != nil { + t.Fatalf("mismatch metrics: %v", err) + } +} + func TestPipelineWithMissingKey_Metrics(t *testing.T) { var buf bytes.Buffer w := log.NewSyncWriter(&buf) @@ -267,8 +303,10 @@ func TestDefaultIdleDuration(t *testing.T) { assert.Equal(t, int64(5*time.Minute.Seconds()), ms.(*stageProcessor).Processor.(*metricStage).cfg["total_keys"].maxIdleSec) } -var labelFoo = model.LabelSet(map[model.LabelName]model.LabelValue{"foo": "bar", "bar": "foo"}) -var labelFu = model.LabelSet(map[model.LabelName]model.LabelValue{"fu": "baz", "baz": "fu"}) +var ( + labelFoo = model.LabelSet(map[model.LabelName]model.LabelValue{"foo": "bar", "bar": "foo"}) + labelFu = model.LabelSet(map[model.LabelName]model.LabelValue{"fu": "baz", "baz": "fu"}) +) func TestMetricStage_Process(t *testing.T) { jsonConfig := JSONConfig{