mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
[FEATURE] PromQL: Implements idelta
and irate
with histograms (#15853)
Some checks are pending
buf.build / lint and publish (push) Waiting to run
CI / Go tests (push) Waiting to run
CI / More Go tests (push) Waiting to run
CI / Go tests with previous Go version (push) Waiting to run
CI / UI tests (push) Waiting to run
CI / Go tests on Windows (push) Waiting to run
CI / Mixins tests (push) Waiting to run
CI / Build Prometheus for common architectures (0) (push) Waiting to run
CI / Build Prometheus for common architectures (1) (push) Waiting to run
CI / Build Prometheus for common architectures (2) (push) Waiting to run
CI / Build Prometheus for all architectures (0) (push) Waiting to run
CI / Build Prometheus for all architectures (1) (push) Waiting to run
CI / Build Prometheus for all architectures (10) (push) Waiting to run
CI / Build Prometheus for all architectures (11) (push) Waiting to run
CI / Build Prometheus for all architectures (2) (push) Waiting to run
CI / Build Prometheus for all architectures (3) (push) Waiting to run
CI / Build Prometheus for all architectures (4) (push) Waiting to run
CI / Build Prometheus for all architectures (5) (push) Waiting to run
CI / Build Prometheus for all architectures (6) (push) Waiting to run
CI / Build Prometheus for all architectures (7) (push) Waiting to run
CI / Build Prometheus for all architectures (8) (push) Waiting to run
CI / Build Prometheus for all architectures (9) (push) Waiting to run
CI / Report status of build Prometheus for all architectures (push) Blocked by required conditions
CI / Check generated parser (push) Waiting to run
CI / golangci-lint (push) Waiting to run
CI / fuzzing (push) Waiting to run
CI / codeql (push) Waiting to run
CI / Publish main branch artifacts (push) Blocked by required conditions
CI / Publish release artefacts (push) Blocked by required conditions
CI / Publish UI on npm Registry (push) Blocked by required conditions
Scorecards supply-chain security / Scorecards analysis (push) Waiting to run
Some checks are pending
buf.build / lint and publish (push) Waiting to run
CI / Go tests (push) Waiting to run
CI / More Go tests (push) Waiting to run
CI / Go tests with previous Go version (push) Waiting to run
CI / UI tests (push) Waiting to run
CI / Go tests on Windows (push) Waiting to run
CI / Mixins tests (push) Waiting to run
CI / Build Prometheus for common architectures (0) (push) Waiting to run
CI / Build Prometheus for common architectures (1) (push) Waiting to run
CI / Build Prometheus for common architectures (2) (push) Waiting to run
CI / Build Prometheus for all architectures (0) (push) Waiting to run
CI / Build Prometheus for all architectures (1) (push) Waiting to run
CI / Build Prometheus for all architectures (10) (push) Waiting to run
CI / Build Prometheus for all architectures (11) (push) Waiting to run
CI / Build Prometheus for all architectures (2) (push) Waiting to run
CI / Build Prometheus for all architectures (3) (push) Waiting to run
CI / Build Prometheus for all architectures (4) (push) Waiting to run
CI / Build Prometheus for all architectures (5) (push) Waiting to run
CI / Build Prometheus for all architectures (6) (push) Waiting to run
CI / Build Prometheus for all architectures (7) (push) Waiting to run
CI / Build Prometheus for all architectures (8) (push) Waiting to run
CI / Build Prometheus for all architectures (9) (push) Waiting to run
CI / Report status of build Prometheus for all architectures (push) Blocked by required conditions
CI / Check generated parser (push) Waiting to run
CI / golangci-lint (push) Waiting to run
CI / fuzzing (push) Waiting to run
CI / codeql (push) Waiting to run
CI / Publish main branch artifacts (push) Blocked by required conditions
CI / Publish release artefacts (push) Blocked by required conditions
CI / Publish UI on npm Registry (push) Blocked by required conditions
Scorecards supply-chain security / Scorecards analysis (push) Waiting to run
Add native histogram support to idelta and irate functions --------- Signed-off-by: Neeraj Gartia <neerajgartia211002@gmail.com>
This commit is contained in:
parent
cb3b17a14c
commit
130cd024e0
|
@ -286,46 +286,115 @@ func funcIncrease(vals []parser.Value, args parser.Expressions, enh *EvalNodeHel
|
|||
|
||||
// === irate(node parser.ValueTypeMatrix) (Vector, Annotations) ===
|
||||
func funcIrate(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||
return instantValue(vals, enh.Out, true)
|
||||
return instantValue(vals, args, enh.Out, true)
|
||||
}
|
||||
|
||||
// === idelta(node model.ValMatrix) (Vector, Annotations) ===
|
||||
func funcIdelta(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||
return instantValue(vals, enh.Out, false)
|
||||
return instantValue(vals, args, enh.Out, false)
|
||||
}
|
||||
|
||||
func instantValue(vals []parser.Value, out Vector, isRate bool) (Vector, annotations.Annotations) {
|
||||
samples := vals[0].(Matrix)[0]
|
||||
func instantValue(vals []parser.Value, args parser.Expressions, out Vector, isRate bool) (Vector, annotations.Annotations) {
|
||||
var (
|
||||
samples = vals[0].(Matrix)[0]
|
||||
metricName = samples.Metric.Get(labels.MetricName)
|
||||
ss = make([]Sample, 0, 2)
|
||||
annos annotations.Annotations
|
||||
)
|
||||
|
||||
// No sense in trying to compute a rate without at least two points. Drop
|
||||
// this Vector element.
|
||||
// TODO: add RangeTooShortWarning
|
||||
if len(samples.Floats) < 2 {
|
||||
if len(samples.Floats)+len(samples.Histograms) < 2 {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
lastSample := samples.Floats[len(samples.Floats)-1]
|
||||
previousSample := samples.Floats[len(samples.Floats)-2]
|
||||
|
||||
var resultValue float64
|
||||
if isRate && lastSample.F < previousSample.F {
|
||||
// Counter reset.
|
||||
resultValue = lastSample.F
|
||||
} else {
|
||||
resultValue = lastSample.F - previousSample.F
|
||||
// Add the last 2 float samples if they exist.
|
||||
for i := max(0, len(samples.Floats)-2); i < len(samples.Floats); i++ {
|
||||
ss = append(ss, Sample{
|
||||
F: samples.Floats[i].F,
|
||||
T: samples.Floats[i].T,
|
||||
})
|
||||
}
|
||||
|
||||
sampledInterval := lastSample.T - previousSample.T
|
||||
// Add the last 2 histogram samples into their correct position if they exist.
|
||||
for i := max(0, len(samples.Histograms)-2); i < len(samples.Histograms); i++ {
|
||||
s := Sample{
|
||||
H: samples.Histograms[i].H,
|
||||
T: samples.Histograms[i].T,
|
||||
}
|
||||
switch {
|
||||
case len(ss) == 0:
|
||||
ss = append(ss, s)
|
||||
case len(ss) == 1:
|
||||
if s.T < ss[0].T {
|
||||
ss = append([]Sample{s}, ss...)
|
||||
} else {
|
||||
ss = append(ss, s)
|
||||
}
|
||||
case s.T < ss[0].T:
|
||||
// s is older than 1st, so discard it.
|
||||
case s.T > ss[1].T:
|
||||
// s is newest, so add it as 2nd and make the old 2nd the new 1st.
|
||||
ss[0] = ss[1]
|
||||
ss[1] = s
|
||||
default:
|
||||
// In all other cases, we just make s the new 1st.
|
||||
// This establishes a correct order, even in the (irregular)
|
||||
// case of equal timestamps.
|
||||
ss[0] = s
|
||||
}
|
||||
}
|
||||
|
||||
resultSample := ss[1]
|
||||
sampledInterval := ss[1].T - ss[0].T
|
||||
if sampledInterval == 0 {
|
||||
// Avoid dividing by 0.
|
||||
return out, nil
|
||||
}
|
||||
switch {
|
||||
case ss[1].H == nil && ss[0].H == nil:
|
||||
if !isRate || ss[1].F >= ss[0].F {
|
||||
// Gauge or counter without reset.
|
||||
resultSample.F = ss[1].F - ss[0].F
|
||||
}
|
||||
// In case of a counter reset, we leave resultSample at
|
||||
// its current value, which is already ss[1].
|
||||
case ss[1].H != nil && ss[0].H != nil:
|
||||
resultSample.H = ss[1].H.Copy()
|
||||
// irate should only be applied to counters.
|
||||
if isRate && (ss[1].H.CounterResetHint == histogram.GaugeType || ss[0].H.CounterResetHint == histogram.GaugeType) {
|
||||
annos.Add(annotations.NewNativeHistogramNotCounterWarning(metricName, args.PositionRange()))
|
||||
}
|
||||
// idelta should only be applied to gauges.
|
||||
if !isRate && (ss[1].H.CounterResetHint != histogram.GaugeType || ss[0].H.CounterResetHint != histogram.GaugeType) {
|
||||
annos.Add(annotations.NewNativeHistogramNotGaugeWarning(metricName, args.PositionRange()))
|
||||
}
|
||||
if !isRate || !ss[1].H.DetectReset(ss[0].H) {
|
||||
_, err := resultSample.H.Sub(ss[0].H)
|
||||
if errors.Is(err, histogram.ErrHistogramsIncompatibleSchema) {
|
||||
return out, annos.Add(annotations.NewMixedExponentialCustomHistogramsWarning(metricName, args.PositionRange()))
|
||||
} else if errors.Is(err, histogram.ErrHistogramsIncompatibleBounds) {
|
||||
return out, annos.Add(annotations.NewIncompatibleCustomBucketsHistogramsWarning(metricName, args.PositionRange()))
|
||||
}
|
||||
}
|
||||
resultSample.H.CounterResetHint = histogram.GaugeType
|
||||
resultSample.H.Compact(0)
|
||||
default:
|
||||
// Mix of a float and a histogram.
|
||||
return out, annos.Add(annotations.NewMixedFloatsHistogramsWarning(metricName, args.PositionRange()))
|
||||
}
|
||||
|
||||
if isRate {
|
||||
// Convert to per-second.
|
||||
resultValue /= float64(sampledInterval) / 1000
|
||||
if resultSample.H == nil {
|
||||
resultSample.F /= float64(sampledInterval) / 1000
|
||||
} else {
|
||||
resultSample.H.Div(float64(sampledInterval) / 1000)
|
||||
}
|
||||
}
|
||||
|
||||
return append(out, Sample{F: resultValue}), nil
|
||||
return append(out, resultSample), annos
|
||||
}
|
||||
|
||||
// Calculate the trend value at the given index i in raw data d.
|
||||
|
|
56
promql/promqltest/testdata/functions.test
vendored
56
promql/promqltest/testdata/functions.test
vendored
|
@ -218,6 +218,13 @@ clear
|
|||
load 5m
|
||||
http_requests_total{path="/foo"} 0+10x10
|
||||
http_requests_total{path="/bar"} 0+10x5 0+10x5
|
||||
http_requests_histogram{path="/a"} {{sum:2 count:2}}+{{sum:3 count:3}}x5
|
||||
http_requests_histogram{path="/b"} 0 0 {{sum:1 count:1}} {{sum:4 count:4}}
|
||||
http_requests_histogram{path="/c"} 0 0 {{sum:1 count:1}} {{sum:4 count:4 counter_reset_hint:gauge}}
|
||||
http_requests_histogram{path="/d"} 0 0 {{sum:1 count:1 counter_reset_hint:gauge}} {{sum:4 count:4}}
|
||||
http_requests_histogram{path="/e"} 0 1 2 {{sum:4 count:4}}
|
||||
http_requests_histogram{path="/f"} 0 0 {{sum:1 count:1}} {{schema:-53 sum:3 count:3 custom_values:[5 10] buckets:[3]}}
|
||||
http_requests_histogram{path="/g"} 0 0 {{schema:-53 sum:3 count:3 custom_values:[1] buckets:[3]}} {{schema:-53 sum:3 count:3 custom_values:[5 10] buckets:[3]}}
|
||||
|
||||
eval instant at 50m irate(http_requests_total[50m])
|
||||
{path="/foo"} .03333333333333333333
|
||||
|
@ -228,6 +235,28 @@ eval instant at 30m irate(http_requests_total[50m])
|
|||
{path="/foo"} .03333333333333333333
|
||||
{path="/bar"} 0
|
||||
|
||||
eval instant at 20m irate(http_requests_histogram{path="/a"}[20m])
|
||||
{path="/a"} {{sum:0.01 count:0.01 counter_reset_hint:gauge}}
|
||||
|
||||
eval instant at 20m irate(http_requests_histogram{path="/b"}[20m])
|
||||
{path="/b"} {{sum:0.01 count:0.01 counter_reset_hint:gauge}}
|
||||
|
||||
eval instant at 20m irate(http_requests_histogram{path="/b"}[6m])
|
||||
|
||||
eval_warn instant at 20m irate(http_requests_histogram{path="/c"}[20m])
|
||||
{path="/c"} {{sum:0.01 count:0.01 counter_reset_hint:gauge}}
|
||||
|
||||
eval_warn instant at 20m irate(http_requests_histogram{path="/d"}[20m])
|
||||
{path="/d"} {{sum:0.01 count:0.01 counter_reset_hint:gauge}}
|
||||
|
||||
eval_warn instant at 20m irate(http_requests_histogram{path="/e"}[20m])
|
||||
|
||||
eval instant at 20m irate(http_requests_histogram{path="/f"}[20m])
|
||||
{path="/f"} {{schema:-53 sum:0.01 count:0.01 custom_values:[5 10] buckets:[0.01]}}
|
||||
|
||||
eval instant at 20m irate(http_requests_histogram{path="/g"}[20m])
|
||||
{path="/g"} {{schema:-53 sum:0.01 count:0.01 custom_values:[5 10] buckets:[0.01]}}
|
||||
|
||||
clear
|
||||
|
||||
# Tests for delta().
|
||||
|
@ -259,11 +288,38 @@ clear
|
|||
load 5m
|
||||
http_requests{path="/foo"} 0 50 100 150
|
||||
http_requests{path="/bar"} 0 50 100 50
|
||||
http_requests_histogram{path="/a"} {{sum:2 count:2 counter_reset_hint:gauge}}+{{sum:1 count:3 counter_reset_hint:gauge}}x5
|
||||
http_requests_histogram{path="/b"} 0 0 {{sum:1 count:1 counter_reset_hint:gauge}} {{sum:2 count:2 counter_reset_hint:gauge}}
|
||||
http_requests_histogram{path="/c"} 0 0 {{sum:1 count:1}} {{sum:2 count:2 counter_reset_hint:gauge}}
|
||||
http_requests_histogram{path="/d"} 0 0 {{sum:1 count:1 counter_reset_hint:gauge}} {{sum:2 count:2}}
|
||||
http_requests_histogram{path="/e"} 0 1 2 {{sum:1 count:2 counter_reset_hint:gauge}}
|
||||
http_requests_histogram{path="/f"} 0 0 {{sum:1 count:1 counter_reset_hint:gauge}} {{schema:-53 sum:1 count:1 custom_values:[5 10] buckets:[1] counter_reset_hint:gauge}}
|
||||
http_requests_histogram{path="/g"} 0 0 {{schema:-53 sum:1 count:1 custom_values:[1] buckets:[2] counter_reset_hint:gauge}} {{schema:-53 sum:1 count:1 custom_values:[5 10] buckets:[1] counter_reset_hint:gauge}}
|
||||
|
||||
eval instant at 20m idelta(http_requests[20m])
|
||||
{path="/foo"} 50
|
||||
{path="/bar"} -50
|
||||
|
||||
eval instant at 20m idelta(http_requests_histogram{path="/a"}[20m])
|
||||
{path="/a"} {{sum:1 count:3 counter_reset_hint:gauge}}
|
||||
|
||||
eval instant at 20m idelta(http_requests_histogram{path="/b"}[20m])
|
||||
{path="/b"} {{sum:1 count:1 counter_reset_hint:gauge}}
|
||||
|
||||
eval instant at 20m idelta(http_requests_histogram{path="/b"}[6m])
|
||||
|
||||
eval_warn instant at 20m idelta(http_requests_histogram{path="/c"}[20m])
|
||||
{path="/c"} {{sum:1 count:1 counter_reset_hint:gauge}}
|
||||
|
||||
eval_warn instant at 20m idelta(http_requests_histogram{path="/d"}[20m])
|
||||
{path="/d"} {{sum:1 count:1 counter_reset_hint:gauge}}
|
||||
|
||||
eval_warn instant at 20m idelta(http_requests_histogram{path="/e"}[20m])
|
||||
|
||||
eval_warn instant at 20m idelta(http_requests_histogram{path="/f"}[20m])
|
||||
|
||||
eval_warn instant at 20m idelta(http_requests_histogram{path="/g"}[20m])
|
||||
|
||||
clear
|
||||
|
||||
# Tests for deriv() and predict_linear().
|
||||
|
|
Loading…
Reference in a new issue