Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

veneur-prometheus bugfix: Specifying multiple tags/labels with -a causes sporadic incorrect metric emission #1052

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* A fix for forwarding metrics with gRPC using the kubernetes discoverer. Thanks, [androohan](https://github.com/androohan)!
* Regenerate testing certs/CA that have expired and have broken tests. Thanks, [randallm](https://github.com/randallm)
* The config field `trace_lightstep_access_token` is redacted if printed. Thanks [arnavdugar](https://github.com/arnavdugar)!
* A fix for the -a flag in veneur-prometheus. Thanks, [dmarriner](https://github.com/dmarriner)

# 14.1.0, 2021-03-16

Expand Down
45 changes: 45 additions & 0 deletions cmd/veneur-prometheus/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,51 @@ func TestHistogramsNewBucketsAreTranslatedToDiffs(t *testing.T) {
assert.False(t, hasbucket5)
}

// This test verifies a fix for a previous bug that caused diff calculations to sporadically break when multiple labels
// were added via the -a flag. Labels were stored as key/values in a map and returned in a potentially different order
// each time since map iteration order is random. This caused the translator to emit the cumulative value instead of
// the diffed value, because it would seem as though the metric was new when in fact it had been previously cached
// with a different label ordering. For example, the translator might look for "counter-key2:value2-key1:value1" when
// it had been previously cached as "counter-key1:value1-key2:value2"
func TestCountsWithAddingLabels(t *testing.T) {
counter := prometheus.NewCounter(prometheus.CounterOpts{
Name: "counter",
Help: "A typical counter.",
})

ts, err := testPrometheusEndpoint(
counter,
)
require.NoError(t, err)
defer ts.Close()

cache := new(countCache)
cfg := testConfig(t, ts.URL)
cfg.addedLabels = map[string]string{
"key1": "value1",
"key2": "value2",
}
statsClient, err := statsd.New("localhost:8125", statsd.WithoutTelemetry())
assert.NoError(t, err)

stats, err := collect(context.Background(), cfg, statsClient, cache)
assert.NoError(t, err)
splitStats(stats)

// Run 100 time to ensure we aren't just passing the test we got lucky
for i := 0; i < 100; i++ {
counter.Inc()
counter.Inc()
counter.Inc()

stats, err = collect(context.Background(), cfg, statsClient, cache)
assert.NoError(t, err)
counts, _ := splitStats(stats)
count, _ := countValue(counts, "counter", "key1:value1", "key2:value2")
assert.Equal(t, 3, count)
}
}

func TestHistogramsAreTranslatedToDiffs(t *testing.T) {
histogram := prometheus.NewHistogram(prometheus.HistogramOpts{
Name: "histogram",
Expand Down
13 changes: 11 additions & 2 deletions cmd/veneur-prometheus/translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"math"
"regexp"
"sort"

dto "github.com/prometheus/client_model/go"
"github.com/stripe/veneur/v14/sources/openmetrics"
Expand Down Expand Up @@ -201,8 +202,16 @@ func (t translator) Tags(labels []*dto.LabelPair) []string {
tags = append(tags, fmt.Sprintf("%s:%s", labelName, labelValue))
}

for name, value := range t.added {
tags = append(tags, fmt.Sprintf("%s:%s", name, value))
// Tags need to be returned in sorted order so that metric cache keys are consistent across metric observation
// sweeps
names := make([]string, 0, len(t.added))
for k := range t.added {
names = append(names, k)
}
sort.Strings(names)

for _, name := range names {
tags = append(tags, fmt.Sprintf("%s:%s", name, t.added[name]))
}

return tags
Expand Down
2 changes: 1 addition & 1 deletion cmd/veneur-prometheus/translate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func TestAddTags(t *testing.T) {
"so:good",
}

assert.ElementsMatch(t, expectedTags, tags)
assert.Equal(t, expectedTags, tags)
}

func TestReplaceTags(t *testing.T) {
Expand Down