Add regression tests for metrics mutations in AST.
It turned out in the end, that only drop_common_metrics() produced any erroneous output in the old system. The second expression in the test ("sum(testmetric) keeping_extra") already worked in the old code, but why not keep it in... The way to test ranged evaluations is a bit clumsy so far, so I want to build a nicer test framework in the end, where all the test cases can be specified as text files which specify desired inputs, outputs, query step widths, etc. Change-Id: I821859789e69b8232bededf670a1b76e9e8c8ca4
This commit is contained in:
parent
c9618d11e8
commit
00a2a93a05
|
@ -40,6 +40,7 @@ type SampleStream struct {
|
||||||
Values metric.Values
|
Values metric.Values
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sample is a single sample belonging to a COWMetric.
|
||||||
type Sample struct {
|
type Sample struct {
|
||||||
Metric clientmodel.COWMetric
|
Metric clientmodel.COWMetric
|
||||||
Value clientmodel.SampleValue
|
Value clientmodel.SampleValue
|
||||||
|
@ -413,7 +414,7 @@ func EvalVectorRange(node VectorNode, start clientmodel.Timestamp, end clientmod
|
||||||
// TODO implement watchdog timer for long-running queries.
|
// TODO implement watchdog timer for long-running queries.
|
||||||
evalTimer := queryStats.GetTimer(stats.InnerEvalTime).Start()
|
evalTimer := queryStats.GetTimer(stats.InnerEvalTime).Start()
|
||||||
sampleStreams := map[uint64]*SampleStream{}
|
sampleStreams := map[uint64]*SampleStream{}
|
||||||
for t := start; t.Before(end); t = t.Add(interval) {
|
for t := start; !t.After(end); t = t.Add(interval) {
|
||||||
vector := node.Eval(t)
|
vector := node.Eval(t)
|
||||||
for _, sample := range vector {
|
for _, sample := range vector {
|
||||||
samplePair := metric.SamplePair{
|
samplePair := metric.SamplePair{
|
||||||
|
|
|
@ -91,11 +91,12 @@ func (vector Vector) String() string {
|
||||||
func (matrix Matrix) String() string {
|
func (matrix Matrix) String() string {
|
||||||
metricStrings := make([]string, 0, len(matrix))
|
metricStrings := make([]string, 0, len(matrix))
|
||||||
for _, sampleStream := range matrix {
|
for _, sampleStream := range matrix {
|
||||||
metricName, ok := sampleStream.Metric.Metric[clientmodel.MetricNameLabel]
|
metricName, hasName := sampleStream.Metric.Metric[clientmodel.MetricNameLabel]
|
||||||
if !ok {
|
numLabels := len(sampleStream.Metric.Metric)
|
||||||
panic("Tried to print matrix without metric name")
|
if hasName {
|
||||||
|
numLabels--
|
||||||
}
|
}
|
||||||
labelStrings := make([]string, 0, len(sampleStream.Metric.Metric)-1)
|
labelStrings := make([]string, 0, numLabels)
|
||||||
for label, value := range sampleStream.Metric.Metric {
|
for label, value := range sampleStream.Metric.Metric {
|
||||||
if label != clientmodel.MetricNameLabel {
|
if label != clientmodel.MetricNameLabel {
|
||||||
labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value))
|
labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value))
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"github.com/prometheus/prometheus/rules/ast"
|
"github.com/prometheus/prometheus/rules/ast"
|
||||||
"github.com/prometheus/prometheus/stats"
|
"github.com/prometheus/prometheus/stats"
|
||||||
"github.com/prometheus/prometheus/storage/local"
|
"github.com/prometheus/prometheus/storage/local"
|
||||||
|
"github.com/prometheus/prometheus/storage/metric"
|
||||||
"github.com/prometheus/prometheus/utility/test"
|
"github.com/prometheus/prometheus/utility/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -60,7 +61,7 @@ func newTestStorage(t testing.TB) (storage local.Storage, closer test.Closer) {
|
||||||
|
|
||||||
func TestExpressions(t *testing.T) {
|
func TestExpressions(t *testing.T) {
|
||||||
// Labels in expected output need to be alphabetically sorted.
|
// Labels in expected output need to be alphabetically sorted.
|
||||||
var expressionTests = []struct {
|
expressionTests := []struct {
|
||||||
expr string
|
expr string
|
||||||
output []string
|
output []string
|
||||||
shouldFail bool
|
shouldFail bool
|
||||||
|
@ -705,6 +706,188 @@ func TestExpressions(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRangedEvaluationRegressions(t *testing.T) {
|
||||||
|
scenarios := []struct {
|
||||||
|
in ast.Matrix
|
||||||
|
out ast.Matrix
|
||||||
|
expr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
// Testing COWMetric behavior in drop_common_labels.
|
||||||
|
in: ast.Matrix{
|
||||||
|
{
|
||||||
|
Metric: clientmodel.COWMetric{
|
||||||
|
Metric: clientmodel.Metric{
|
||||||
|
clientmodel.MetricNameLabel: "testmetric",
|
||||||
|
"testlabel": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Values: metric.Values{
|
||||||
|
{
|
||||||
|
Timestamp: testStartTime,
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Timestamp: testStartTime.Add(time.Hour),
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Metric: clientmodel.COWMetric{
|
||||||
|
Metric: clientmodel.Metric{
|
||||||
|
clientmodel.MetricNameLabel: "testmetric",
|
||||||
|
"testlabel": "2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Values: metric.Values{
|
||||||
|
{
|
||||||
|
Timestamp: testStartTime.Add(time.Hour),
|
||||||
|
Value: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
out: ast.Matrix{
|
||||||
|
{
|
||||||
|
Metric: clientmodel.COWMetric{
|
||||||
|
Metric: clientmodel.Metric{
|
||||||
|
clientmodel.MetricNameLabel: "testmetric",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Values: metric.Values{
|
||||||
|
{
|
||||||
|
Timestamp: testStartTime,
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Metric: clientmodel.COWMetric{
|
||||||
|
Metric: clientmodel.Metric{
|
||||||
|
clientmodel.MetricNameLabel: "testmetric",
|
||||||
|
"testlabel": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Values: metric.Values{
|
||||||
|
{
|
||||||
|
Timestamp: testStartTime.Add(time.Hour),
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Metric: clientmodel.COWMetric{
|
||||||
|
Metric: clientmodel.Metric{
|
||||||
|
clientmodel.MetricNameLabel: "testmetric",
|
||||||
|
"testlabel": "2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Values: metric.Values{
|
||||||
|
{
|
||||||
|
Timestamp: testStartTime.Add(time.Hour),
|
||||||
|
Value: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expr: "drop_common_labels(testmetric)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Testing COWMetric behavior in vector aggregation.
|
||||||
|
in: ast.Matrix{
|
||||||
|
{
|
||||||
|
Metric: clientmodel.COWMetric{
|
||||||
|
Metric: clientmodel.Metric{
|
||||||
|
clientmodel.MetricNameLabel: "testmetric",
|
||||||
|
"testlabel": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Values: metric.Values{
|
||||||
|
{
|
||||||
|
Timestamp: testStartTime,
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Timestamp: testStartTime.Add(time.Hour),
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Metric: clientmodel.COWMetric{
|
||||||
|
Metric: clientmodel.Metric{
|
||||||
|
clientmodel.MetricNameLabel: "testmetric",
|
||||||
|
"testlabel": "2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Values: metric.Values{
|
||||||
|
{
|
||||||
|
Timestamp: testStartTime,
|
||||||
|
Value: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
out: ast.Matrix{
|
||||||
|
{
|
||||||
|
Metric: clientmodel.COWMetric{
|
||||||
|
Metric: clientmodel.Metric{},
|
||||||
|
},
|
||||||
|
Values: metric.Values{
|
||||||
|
{
|
||||||
|
Timestamp: testStartTime,
|
||||||
|
Value: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Metric: clientmodel.COWMetric{
|
||||||
|
Metric: clientmodel.Metric{
|
||||||
|
"testlabel": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Values: metric.Values{
|
||||||
|
{
|
||||||
|
Timestamp: testStartTime.Add(time.Hour),
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expr: "sum(testmetric) keeping_extra",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, s := range scenarios {
|
||||||
|
storage, closer := local.NewTestStorage(t)
|
||||||
|
storeMatrix(storage, s.in)
|
||||||
|
|
||||||
|
expr, err := LoadExprFromString(s.expr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%d. Error parsing expression: %v", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := ast.EvalVectorRange(
|
||||||
|
expr.(ast.VectorNode),
|
||||||
|
testStartTime,
|
||||||
|
testStartTime.Add(time.Hour),
|
||||||
|
time.Hour,
|
||||||
|
storage,
|
||||||
|
stats.NewTimerGroup(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%d. Error evaluating expression: %v", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got.String() != s.out.String() {
|
||||||
|
t.Fatalf("%d. Expression: %s\n\ngot:\n=====\n%v\n====\n\nwant:\n=====\n%v\n=====\n", i, s.expr, got.String(), s.out.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
closer.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var ruleTests = []struct {
|
var ruleTests = []struct {
|
||||||
inputFile string
|
inputFile string
|
||||||
shouldFail bool
|
shouldFail bool
|
||||||
|
|
Loading…
Reference in New Issue