Fix remote read labelset corruption (#3456)

The labelsets returned from remote read are mutated in higher levels
(like seriesFilter.Labels()) and since the concreteSeriesSet didn't
return a copy, the external mutation affected the labelset in the
concreteSeries itself. This resulted in bizarre bugs where local and
remote series would show with identical label sets in the UI, but not be
deduplicated, since internally, a series might come to look like:

{__name__="node_load5", instance="192.168.1.202:12090", job="node_exporter", node="odroid", node="odroid"}

(note the repetition of the last label)
pull/3216/merge
Julius Volz 7 years ago committed by GitHub
parent c8a735ceb6
commit 9f10c63cff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -201,7 +201,7 @@ type concreteSeries struct {
}
func (c *concreteSeries) Labels() labels.Labels {
return c.labels
return labels.New(c.labels...)
}
func (c *concreteSeries) Iterator() storage.SeriesIterator {

@ -16,6 +16,8 @@ package remote
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/pkg/labels"
"github.com/prometheus/prometheus/prompb"
"github.com/prometheus/prometheus/storage"
@ -124,3 +126,22 @@ func TestConcreteSeriesSet(t *testing.T) {
t.Fatalf("Expected Next() to be false.")
}
}
func TestConcreteSeriesClonesLabels(t *testing.T) {
lbls := labels.Labels{
labels.Label{Name: "a", Value: "b"},
labels.Label{Name: "c", Value: "d"},
}
cs := concreteSeries{
labels: labels.New(lbls...),
}
gotLabels := cs.Labels()
require.Equal(t, lbls, gotLabels)
gotLabels[0].Value = "foo"
gotLabels[1].Value = "bar"
gotLabels = cs.Labels()
require.Equal(t, lbls, gotLabels)
}

Loading…
Cancel
Save