mirror of
https://github.com/prometheus/prometheus.git
synced 2024-11-09 23:24:05 -08:00
Fix GetMetricForFingerprint() metric mutability.
Some users of GetMetricForFingerprint() end up modifying the returned metric labelset. Since the memory storage's implementation of GetMetricForFingerprint() returned a pointer to the metric (and maps are reference types anyways), the external mutation propagated back into the memory storage. The fix is to make a copy of the metric before returning it.
This commit is contained in:
parent
98e512d755
commit
83c60ad43a
|
@ -116,7 +116,7 @@ func (v *viewAdapter) GetValueAtTime(fingerprints model.Fingerprints, timestamp
|
||||||
}
|
}
|
||||||
if samplePair != nil {
|
if samplePair != nil {
|
||||||
samples = append(samples, model.Sample{
|
samples = append(samples, model.Sample{
|
||||||
Metric: *m,
|
Metric: m,
|
||||||
Value: samplePair.Value,
|
Value: samplePair.Value,
|
||||||
Timestamp: timestamp,
|
Timestamp: timestamp,
|
||||||
})
|
})
|
||||||
|
@ -140,7 +140,7 @@ func (v *viewAdapter) GetBoundaryValues(fingerprints model.Fingerprints, interva
|
||||||
}
|
}
|
||||||
|
|
||||||
sampleSet := model.SampleSet{
|
sampleSet := model.SampleSet{
|
||||||
Metric: *m,
|
Metric: m,
|
||||||
Values: samplePairs,
|
Values: samplePairs,
|
||||||
}
|
}
|
||||||
sampleSets = append(sampleSets, sampleSet)
|
sampleSets = append(sampleSets, sampleSet)
|
||||||
|
@ -162,7 +162,7 @@ func (v *viewAdapter) GetRangeValues(fingerprints model.Fingerprints, interval *
|
||||||
}
|
}
|
||||||
|
|
||||||
sampleSet := model.SampleSet{
|
sampleSet := model.SampleSet{
|
||||||
Metric: *m,
|
Metric: m,
|
||||||
Values: samplePairs,
|
Values: samplePairs,
|
||||||
}
|
}
|
||||||
sampleSets = append(sampleSets, sampleSet)
|
sampleSets = append(sampleSets, sampleSet)
|
||||||
|
|
|
@ -172,17 +172,15 @@ func GetMetricForFingerprintTests(p MetricPersistence, t test.Tester) {
|
||||||
t.Errorf("Expected one element.")
|
t.Errorf("Expected one element.")
|
||||||
}
|
}
|
||||||
|
|
||||||
v, e := p.GetMetricForFingerprint(result[0])
|
metric, err := p.GetMetricForFingerprint(result[0])
|
||||||
if e != nil {
|
if err != nil {
|
||||||
t.Error(e)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v == nil {
|
if metric == nil {
|
||||||
t.Fatal("Did not expect nil.")
|
t.Fatal("Did not expect nil.")
|
||||||
}
|
}
|
||||||
|
|
||||||
metric := *v
|
|
||||||
|
|
||||||
if len(metric) != 1 {
|
if len(metric) != 1 {
|
||||||
t.Errorf("Expected one-dimensional metric.")
|
t.Errorf("Expected one-dimensional metric.")
|
||||||
}
|
}
|
||||||
|
@ -203,20 +201,43 @@ func GetMetricForFingerprintTests(p MetricPersistence, t test.Tester) {
|
||||||
t.Errorf("Expected one element.")
|
t.Errorf("Expected one element.")
|
||||||
}
|
}
|
||||||
|
|
||||||
v, e = p.GetMetricForFingerprint(result[0])
|
metric, err = p.GetMetricForFingerprint(result[0])
|
||||||
|
|
||||||
if v == nil {
|
if metric == nil {
|
||||||
t.Fatal("Did not expect nil.")
|
t.Fatal("Did not expect nil.")
|
||||||
}
|
}
|
||||||
|
|
||||||
metric = *v
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
if e != nil {
|
|
||||||
t.Error(e)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(metric) != 2 {
|
if len(metric) != 2 {
|
||||||
t.Errorf("Expected one-dimensional metric.")
|
t.Errorf("Expected two-dimensional metric.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if metric["request_type"] != "your_dad" {
|
||||||
|
t.Errorf("Expected metric to match.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if metric["one-off"] != "value" {
|
||||||
|
t.Errorf("Expected metric to match.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that mutating a returned metric does not result in the mutated
|
||||||
|
// metric to be returned at the next GetMetricForFingerprint() call.
|
||||||
|
metric["one-off"] = "new value"
|
||||||
|
metric, err = p.GetMetricForFingerprint(result[0])
|
||||||
|
|
||||||
|
if metric == nil {
|
||||||
|
t.Fatal("Did not expect nil.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(metric) != 2 {
|
||||||
|
t.Errorf("Expected two-dimensional metric.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if metric["request_type"] != "your_dad" {
|
if metric["request_type"] != "your_dad" {
|
||||||
|
|
|
@ -45,7 +45,7 @@ type MetricPersistence interface {
|
||||||
GetFingerprintsForLabelName(model.LabelName) (model.Fingerprints, error)
|
GetFingerprintsForLabelName(model.LabelName) (model.Fingerprints, error)
|
||||||
|
|
||||||
// Get the metric associated with the provided fingerprint.
|
// Get the metric associated with the provided fingerprint.
|
||||||
GetMetricForFingerprint(model.Fingerprint) (*model.Metric, error)
|
GetMetricForFingerprint(model.Fingerprint) (model.Metric, error)
|
||||||
|
|
||||||
GetValueAtTime(model.Fingerprint, time.Time) model.Values
|
GetValueAtTime(model.Fingerprint, time.Time) model.Values
|
||||||
GetBoundaryValues(model.Fingerprint, model.Interval) (first model.Values, second model.Values)
|
GetBoundaryValues(model.Fingerprint, model.Interval) (first model.Values, second model.Values)
|
||||||
|
|
|
@ -772,7 +772,7 @@ func (l *LevelDBMetricPersistence) GetFingerprintsForLabelName(labelName model.L
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LevelDBMetricPersistence) GetMetricForFingerprint(f model.Fingerprint) (m *model.Metric, err error) {
|
func (l *LevelDBMetricPersistence) GetMetricForFingerprint(f model.Fingerprint) (m model.Metric, err error) {
|
||||||
defer func(begin time.Time) {
|
defer func(begin time.Time) {
|
||||||
duration := time.Since(begin)
|
duration := time.Since(begin)
|
||||||
|
|
||||||
|
@ -790,16 +790,12 @@ func (l *LevelDBMetricPersistence) GetMetricForFingerprint(f model.Fingerprint)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
metric := model.Metric{}
|
m = model.Metric{}
|
||||||
|
|
||||||
for _, v := range unmarshaled.LabelPair {
|
for _, v := range unmarshaled.LabelPair {
|
||||||
metric[model.LabelName(*v.Name)] = model.LabelValue(*v.Value)
|
m[model.LabelName(*v.Name)] = model.LabelValue(*v.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicit address passing here shaves immense amounts of time off of the
|
|
||||||
// code flow due to less tight-loop dereferencing.
|
|
||||||
m = &metric
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -199,13 +199,16 @@ func (s memorySeriesStorage) GetFingerprintsForLabelName(l model.LabelName) (fin
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s memorySeriesStorage) GetMetricForFingerprint(f model.Fingerprint) (metric *model.Metric, err error) {
|
func (s memorySeriesStorage) GetMetricForFingerprint(f model.Fingerprint) (metric model.Metric, err error) {
|
||||||
series, ok := s.fingerprintToSeries[f]
|
series, ok := s.fingerprintToSeries[f]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
metric = &series.metric
|
metric = model.Metric{}
|
||||||
|
for label, value := range series.metric {
|
||||||
|
metric[label] = value
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -596,7 +596,7 @@ func (t *TieredStorage) GetFingerprintsForLabelSet(labelSet model.LabelSet) (fin
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the metric associated with the provided fingerprint.
|
// Get the metric associated with the provided fingerprint.
|
||||||
func (t *TieredStorage) GetMetricForFingerprint(f model.Fingerprint) (m *model.Metric, err error) {
|
func (t *TieredStorage) GetMetricForFingerprint(f model.Fingerprint) (m model.Metric, err error) {
|
||||||
m, err = t.memoryArena.GetMetricForFingerprint(f)
|
m, err = t.memoryArena.GetMetricForFingerprint(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue