Co-authored-by: Fiona Liao <fiona.liao@grafana.com> Signed-off-by: Carrie Edwards <edwrdscarrie@gmail.com>pull/13699/head
parent
134e8dc7af
commit
60917f628b
@ -0,0 +1,194 @@ |
||||
// Copyright 2017 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tsdb |
||||
|
||||
import ( |
||||
prom_testutil "github.com/prometheus/client_golang/prometheus/testutil" |
||||
"testing" |
||||
|
||||
"github.com/prometheus/prometheus/tsdb/chunkenc" |
||||
|
||||
"github.com/stretchr/testify/require" |
||||
|
||||
"github.com/prometheus/prometheus/model/histogram" |
||||
"github.com/prometheus/prometheus/model/labels" |
||||
"github.com/prometheus/prometheus/storage" |
||||
"github.com/prometheus/prometheus/tsdb/chunks" |
||||
) |
||||
|
||||
const ( |
||||
float = "float" |
||||
) |
||||
|
||||
type tsValue struct { |
||||
Ts int64 |
||||
V int64 |
||||
CounterResetHeader histogram.CounterResetHint |
||||
} |
||||
|
||||
type sampleTypeScenario struct { |
||||
sampleType string |
||||
appendFunc func(appender storage.Appender, lbls labels.Labels, ts, value int64) (storage.SeriesRef, sample, error) |
||||
sampleFunc func(ts, value int64) sample |
||||
} |
||||
|
||||
var sampleTypeScenarios = map[string]sampleTypeScenario{ |
||||
float: { |
||||
sampleType: sampleMetricTypeFloat, |
||||
appendFunc: func(appender storage.Appender, lbls labels.Labels, ts, value int64) (storage.SeriesRef, sample, error) { |
||||
s := sample{t: ts, f: float64(value)} |
||||
ref, err := appender.Append(0, lbls, ts, s.f) |
||||
return ref, s, err |
||||
}, |
||||
sampleFunc: func(ts, value int64) sample { |
||||
return sample{t: ts, f: float64(value)} |
||||
}, |
||||
}, |
||||
//intHistogram: {
|
||||
// sampleType: sampleMetricTypeHistogram,
|
||||
// appendFunc: func(appender storage.Appender, lbls labels.Labels, ts, value int64) (storage.SeriesRef, sample, error) {
|
||||
// s := sample{t: ts, h: tsdbutil.GenerateTestHistogram(int(value))}
|
||||
// ref, err := appender.AppendHistogram(0, lbls, ts, s.h, nil)
|
||||
// return ref, s, err
|
||||
// },
|
||||
// sampleFunc: func(ts, value int64) sample {
|
||||
// return sample{t: ts, h: tsdbutil.GenerateTestHistogram(int(value))}
|
||||
// },
|
||||
//},
|
||||
//floatHistogram: {
|
||||
// sampleType: sampleMetricTypeHistogram,
|
||||
// appendFunc: func(appender storage.Appender, lbls labels.Labels, ts, value int64) (storage.SeriesRef, sample, error) {
|
||||
// s := sample{t: ts, fh: tsdbutil.GenerateTestFloatHistogram(int(value))}
|
||||
// ref, err := appender.AppendHistogram(0, lbls, ts, nil, s.fh)
|
||||
// return ref, s, err
|
||||
// },
|
||||
// sampleFunc: func(ts, value int64) sample {
|
||||
// return sample{t: ts, fh: tsdbutil.GenerateTestFloatHistogram(int(value))}
|
||||
// },
|
||||
//},
|
||||
//gaugeIntHistogram: {
|
||||
// sampleType: sampleMetricTypeHistogram,
|
||||
// appendFunc: func(appender storage.Appender, lbls labels.Labels, ts, value int64) (storage.SeriesRef, sample, error) {
|
||||
// s := sample{t: ts, h: tsdbutil.GenerateTestGaugeHistogram(int(value))}
|
||||
// ref, err := appender.AppendHistogram(0, lbls, ts, s.h, nil)
|
||||
// return ref, s, err
|
||||
// },
|
||||
// sampleFunc: func(ts, value int64) sample {
|
||||
// return sample{t: ts, h: tsdbutil.GenerateTestGaugeHistogram(int(value))}
|
||||
// },
|
||||
//},
|
||||
//gaugeFloatHistogram: {
|
||||
// sampleType: sampleMetricTypeHistogram,
|
||||
// appendFunc: func(appender storage.Appender, lbls labels.Labels, ts, value int64) (storage.SeriesRef, sample, error) {
|
||||
// s := sample{t: ts, fh: tsdbutil.GenerateTestGaugeFloatHistogram(int(value))}
|
||||
// ref, err := appender.AppendHistogram(0, lbls, ts, nil, s.fh)
|
||||
// return ref, s, err
|
||||
// },
|
||||
// sampleFunc: func(ts, value int64) sample {
|
||||
// return sample{t: ts, fh: tsdbutil.GenerateTestGaugeFloatHistogram(int(value))}
|
||||
// },
|
||||
//},
|
||||
} |
||||
|
||||
// requireEqualSamples checks that the actual series are equal to the expected ones. It ignores the counter reset hints for histograms.
|
||||
func requireEqualSamples(t *testing.T, expected, actual map[string][]chunks.Sample, ignoreCounterResets bool) { |
||||
for name, expectedItem := range expected { |
||||
actualItem, ok := actual[name] |
||||
require.True(t, ok, "Expected series %s not found", name) |
||||
compareSamples(t, name, expectedItem, actualItem, ignoreCounterResets) |
||||
} |
||||
for name := range actual { |
||||
_, ok := expected[name] |
||||
require.True(t, ok, "Unexpected series %s", name) |
||||
} |
||||
} |
||||
|
||||
func requireEqualOOOSamples(t *testing.T, expectedSamples int, db *DB) { |
||||
require.GreaterOrEqual(t, float64(expectedSamples), |
||||
prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamplesAppended.WithLabelValues(sampleMetricTypeFloat))+ |
||||
prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamplesAppended.WithLabelValues(sampleMetricTypeHistogram)), |
||||
"number of ooo appended samples mismatch") |
||||
} |
||||
|
||||
func compareSamples(t *testing.T, name string, expected, actual []chunks.Sample, ignoreCounterResets bool) { |
||||
require.Equal(t, len(expected), len(actual), "Length not expected for %s", name) |
||||
for i, s := range expected { |
||||
expectedSample := s |
||||
actualSample := actual[i] |
||||
require.Equal(t, expectedSample.T(), expectedSample.T(), "Different timestamps for %s[%d]", name, i) |
||||
require.Equal(t, expectedSample.Type().String(), actualSample.Type().String(), "Different types for %s[%d] at ts %d", name, i, expectedSample.T()) |
||||
switch { |
||||
case s.H() != nil: |
||||
{ |
||||
expectedHist := expectedSample.H() |
||||
actualHist := actualSample.H() |
||||
if ignoreCounterResets && expectedHist.CounterResetHint != histogram.GaugeType { |
||||
expectedHist.CounterResetHint = histogram.UnknownCounterReset |
||||
actualHist.CounterResetHint = histogram.UnknownCounterReset |
||||
} else { |
||||
require.Equal(t, expectedHist.CounterResetHint, actualHist.CounterResetHint, "Sample header doesn't match for %s[%d] at ts %d, expected: %s, actual: %s", name, i, expectedSample.T(), counterResetAsString(expectedHist.CounterResetHint), counterResetAsString(actualHist.CounterResetHint)) |
||||
} |
||||
require.Equal(t, expectedHist, actualHist, "Sample doesn't match for %s[%d] at ts %d", name, i, expectedSample.T()) |
||||
} |
||||
case s.FH() != nil: |
||||
{ |
||||
expectedHist := expectedSample.FH() |
||||
actualHist := actualSample.FH() |
||||
if ignoreCounterResets { |
||||
expectedHist.CounterResetHint = histogram.UnknownCounterReset |
||||
actualHist.CounterResetHint = histogram.UnknownCounterReset |
||||
} else { |
||||
require.Equal(t, expectedHist.CounterResetHint, actualHist.CounterResetHint, "Sample header doesn't match for %s[%d] at ts %d, expected: %s, actual: %s", name, i, expectedSample.T(), counterResetAsString(expectedHist.CounterResetHint), counterResetAsString(actualHist.CounterResetHint)) |
||||
} |
||||
require.Equal(t, expectedHist, actualHist, "Sample doesn't match for %s[%d] at ts %d", name, i, expectedSample.T()) |
||||
} |
||||
default: |
||||
require.Equal(t, expectedSample, actualSample, "Sample doesn't match for %s[%d] at ts %d", name, i, expectedSample.T()) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func counterResetAsString(h histogram.CounterResetHint) string { |
||||
switch h { |
||||
case histogram.UnknownCounterReset: |
||||
return "UnknownCounterReset" |
||||
case histogram.CounterReset: |
||||
return "CounterReset" |
||||
case histogram.NotCounterReset: |
||||
return "NotCounterReset" |
||||
case histogram.GaugeType: |
||||
return "GaugeType" |
||||
} |
||||
panic("Unexpected counter reset type") |
||||
} |
||||
|
||||
func samplesFromIterator(t testing.TB, it chunkenc.Iterator) []chunks.Sample { |
||||
var samples []chunks.Sample |
||||
for typ := it.Next(); typ != chunkenc.ValNone; typ = it.Next() { |
||||
switch typ { |
||||
case chunkenc.ValFloat: |
||||
ts, val := it.At() |
||||
samples = append(samples, sample{t: ts, f: val}) |
||||
case chunkenc.ValHistogram: |
||||
ts, val := it.AtHistogram(nil) |
||||
samples = append(samples, sample{t: ts, h: val}) |
||||
case chunkenc.ValFloatHistogram: |
||||
ts, val := it.AtFloatHistogram(nil) |
||||
samples = append(samples, sample{t: ts, fh: val}) |
||||
default: |
||||
t.Fatalf("unknown sample value type %s", typ) |
||||
} |
||||
} |
||||
return samples |
||||
} |
||||
Loading…
Reference in new issue