mirror of https://github.com/prometheus/prometheus
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
210 lines
7.9 KiB
210 lines
7.9 KiB
// 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 ( |
|
"testing" |
|
|
|
"github.com/prometheus/prometheus/tsdb/tsdbutil" |
|
|
|
prom_testutil "github.com/prometheus/client_golang/prometheus/testutil" |
|
|
|
"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" |
|
intHistogram = "integer histogram" |
|
floatHistogram = "float histogram" |
|
gaugeIntHistogram = "gauge int histogram" |
|
gaugeFloatHistogram = "gauge float histogram" |
|
) |
|
|
|
type testValue 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))} |
|
}, |
|
}, |
|
} |
|
|
|
// requireEqualSeries checks that the actual series are equal to the expected ones. It ignores the counter reset hints for histograms. |
|
func requireEqualSeries(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) |
|
requireEqualSamples(t, name, expectedItem, actualItem, requireEqualSamplesIgnoreCounterResets) |
|
} |
|
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.Equal(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") |
|
} |
|
|
|
type requireEqualSamplesOption int |
|
|
|
const ( |
|
requireEqualSamplesNoOption requireEqualSamplesOption = iota |
|
requireEqualSamplesIgnoreCounterResets |
|
requireEqualSamplesInUseBucketCompare |
|
) |
|
|
|
func requireEqualSamples(t *testing.T, name string, expected, actual []chunks.Sample, options ...requireEqualSamplesOption) { |
|
var ( |
|
ignoreCounterResets bool |
|
inUseBucketCompare bool |
|
) |
|
for _, option := range options { |
|
switch option { |
|
case requireEqualSamplesIgnoreCounterResets: |
|
ignoreCounterResets = true |
|
case requireEqualSamplesInUseBucketCompare: |
|
inUseBucketCompare = true |
|
} |
|
} |
|
|
|
require.Equal(t, len(expected), len(actual), "Length not equal to expected for %s", name) |
|
for i, s := range expected { |
|
expectedSample := s |
|
actualSample := actual[i] |
|
require.Equal(t, expectedSample.T(), actualSample.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)) |
|
} |
|
if inUseBucketCompare { |
|
expectedSample.H().Compact(0) |
|
actualSample.H().Compact(0) |
|
} |
|
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)) |
|
} |
|
if inUseBucketCompare { |
|
expectedSample.FH().Compact(0) |
|
actualSample.FH().Compact(0) |
|
} |
|
require.Equal(t, expectedHist, actualHist, "Sample doesn't match for %s[%d] at ts %d", name, i, expectedSample.T()) |
|
} |
|
default: |
|
expectedFloat := expectedSample.F() |
|
actualFloat := actualSample.F() |
|
require.Equal(t, expectedFloat, actualFloat, "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") |
|
}
|
|
|