promql: Add support for predict_linear(my_timeseries[1h], 7200)
This will give a prediction for the value of my_timeseries in 2 hours, based on the last hour of data.
This commit is contained in:
parent
beae7b6afb
commit
d6a80c2b76
|
@ -474,6 +474,43 @@ func funcDeriv(ev *evaluator, args Expressions) Value {
|
|||
return resultVector
|
||||
}
|
||||
|
||||
// === predict_linear(node ExprMatrix, k ExprScalar) Vector ===
|
||||
func funcPredictLinear(ev *evaluator, args Expressions) Value {
|
||||
vector := funcDeriv(ev, args[0:1]).(Vector)
|
||||
duration := clientmodel.SampleValue(clientmodel.SampleValue(ev.evalFloat(args[1])))
|
||||
|
||||
excludedLabels := map[clientmodel.LabelName]struct{}{
|
||||
clientmodel.MetricNameLabel: {},
|
||||
}
|
||||
|
||||
// Calculate predicted delta over the duration.
|
||||
signatureToDelta := map[uint64]clientmodel.SampleValue{}
|
||||
for _, el := range vector {
|
||||
signature := clientmodel.SignatureWithoutLabels(el.Metric.Metric, excludedLabels)
|
||||
signatureToDelta[signature] = el.Value * duration
|
||||
}
|
||||
|
||||
// add predicted delta to last value.
|
||||
matrixBounds := ev.evalMatrixBounds(args[0])
|
||||
outVec := make(Vector, 0, len(signatureToDelta))
|
||||
for _, samples := range matrixBounds {
|
||||
if len(samples.Values) < 2 {
|
||||
continue
|
||||
}
|
||||
signature := clientmodel.SignatureWithoutLabels(samples.Metric.Metric, excludedLabels)
|
||||
delta, ok := signatureToDelta[signature]
|
||||
if ok {
|
||||
samples.Metric.Delete(clientmodel.MetricNameLabel)
|
||||
outVec = append(outVec, &Sample{
|
||||
Metric: samples.Metric,
|
||||
Value: delta + samples.Values[1].Value,
|
||||
Timestamp: ev.Timestamp,
|
||||
})
|
||||
}
|
||||
}
|
||||
return outVec
|
||||
}
|
||||
|
||||
// === histogram_quantile(k ExprScalar, vector ExprVector) Vector ===
|
||||
func funcHistogramQuantile(ev *evaluator, args Expressions) Value {
|
||||
q := clientmodel.SampleValue(ev.evalFloat(args[0]))
|
||||
|
@ -688,6 +725,12 @@ var functions = map[string]*Function{
|
|||
ReturnType: ExprVector,
|
||||
Call: funcMinOverTime,
|
||||
},
|
||||
"predict_linear": {
|
||||
Name: "predict_linear",
|
||||
ArgTypes: []ExprType{ExprMatrix, ExprScalar},
|
||||
ReturnType: ExprVector,
|
||||
Call: funcPredictLinear,
|
||||
},
|
||||
"rate": {
|
||||
Name: "rate",
|
||||
ArgTypes: []ExprType{ExprMatrix},
|
||||
|
|
|
@ -62,3 +62,33 @@ load 5m
|
|||
eval instant at 50m increase(http_requests[50m])
|
||||
{path="/foo"} 100
|
||||
{path="/bar"} 90
|
||||
|
||||
|
||||
clear
|
||||
|
||||
# Tests for deriv() and predict_linear().
|
||||
load 5m
|
||||
testcounter_reset_middle 0+10x4 0+10x5
|
||||
http_requests{job="app-server", instance="1", group="canary"} 0+80x10
|
||||
|
||||
# Deriv should return the same as rate in simple cases.
|
||||
eval instant at 50m rate(http_requests{group="canary", instance="1", job="app-server"}[60m])
|
||||
{group="canary", instance="1", job="app-server"} 0.26666666666666666
|
||||
|
||||
eval instant at 50m deriv(http_requests{group="canary", instance="1", job="app-server"}[60m])
|
||||
{group="canary", instance="1", job="app-server"} 0.26666666666666666
|
||||
|
||||
# Deriv should return correct result.
|
||||
eval instant at 50m deriv(testcounter_reset_middle[100m])
|
||||
{} 0.010606060606060607
|
||||
|
||||
# Predict_linear should return correct result.
|
||||
eval instant at 50m predict_linear(testcounter_reset_middle[100m], 3600)
|
||||
{} 88.181818181818185200
|
||||
|
||||
# Predict_linear is syntactic sugar around deriv.
|
||||
eval instant at 50m predict_linear(http_requests[50m], 3600) - (http_requests + deriv(http_requests[50m]) * 3600)
|
||||
{group="canary", instance="1", job="app-server"} 0
|
||||
|
||||
eval instant at 50m predict_linear(testcounter_reset_middle[100m], 3600) - (testcounter_reset_middle + deriv(testcounter_reset_middle[100m]) * 3600)
|
||||
{} 0
|
||||
|
|
|
@ -238,10 +238,6 @@ eval instant at 50m delta(http_requests{group="canary", instance="1", job="app-s
|
|||
eval instant at 50m rate(http_requests{group="canary", instance="1", job="app-server"}[60m])
|
||||
{group="canary", instance="1", job="app-server"} 0.26666666666666666
|
||||
|
||||
# Deriv should return the same as rate in simple cases.
|
||||
eval instant at 50m deriv(http_requests{group="canary", instance="1", job="app-server"}[60m])
|
||||
{group="canary", instance="1", job="app-server"} 0.26666666666666666
|
||||
|
||||
# Counter resets at in the middle of range are handled correctly by rate().
|
||||
eval instant at 50m rate(testcounter_reset_middle[60m])
|
||||
{} 0.03
|
||||
|
@ -251,10 +247,6 @@ eval instant at 50m rate(testcounter_reset_middle[60m])
|
|||
eval instant at 50m rate(testcounter_reset_end[5m])
|
||||
{} 0
|
||||
|
||||
# Deriv should return correct result.
|
||||
eval instant at 50m deriv(testcounter_reset_middle[100m])
|
||||
{} 0.010606060606060607
|
||||
|
||||
# count_scalar for a non-empty vector should return scalar element count.
|
||||
eval instant at 50m count_scalar(http_requests)
|
||||
8
|
||||
|
|
Loading…
Reference in New Issue