diff --git a/promql/functions.go b/promql/functions.go index f1b9c0fd7..6103dbd38 100644 --- a/promql/functions.go +++ b/promql/functions.go @@ -505,6 +505,33 @@ func funcHistogramQuantile(ev *evaluator, args Expressions) Value { return outVec } +// === resets(matrix ExprMatrix) Vector === +func funcResets(ev *evaluator, args Expressions) Value { + in := ev.evalMatrix(args[0]) + out := make(Vector, 0, len(in)) + + for _, samples := range in { + resets := 0 + prev := clientmodel.SampleValue(samples.Values[0].Value) + for _, sample := range samples.Values[1:] { + current := sample.Value + if current < prev { + resets++ + } + prev = current + } + + rs := &Sample{ + Metric: samples.Metric, + Value: clientmodel.SampleValue(resets), + Timestamp: ev.Timestamp, + } + rs.Metric.Delete(clientmodel.MetricNameLabel) + out = append(out, rs) + } + return out +} + var functions = map[string]*Function{ "abs": { Name: "abs", @@ -621,6 +648,12 @@ var functions = map[string]*Function{ ReturnType: ExprVector, Call: funcRate, }, + "resets": { + Name: "resets", + ArgTypes: []ExprType{ExprMatrix}, + ReturnType: ExprVector, + Call: funcResets, + }, "round": { Name: "round", ArgTypes: []ExprType{ExprVector, ExprScalar}, diff --git a/promql/testdata/functions.test b/promql/testdata/functions.test new file mode 100644 index 000000000..e3c5687f9 --- /dev/null +++ b/promql/testdata/functions.test @@ -0,0 +1,21 @@ +load 5m + http_requests{path="/foo"} 1 2 3 0 1 0 0 1 2 0 + http_requests{path="/bar"} 1 2 3 4 5 1 2 3 4 5 + +eval instant at 50m resets(http_requests[5m]) + {path="/foo"} 0 + {path="/bar"} 0 + +eval instant at 50m resets(http_requests[20m]) + {path="/foo"} 1 + {path="/bar"} 0 + +eval instant at 50m resets(http_requests[30m]) + {path="/foo"} 2 + {path="/bar"} 1 + +eval instant at 50m resets(http_requests[50m]) + {path="/foo"} 3 + {path="/bar"} 1 + +eval instant at 50m resets(nonexistent_metric[50m])