mirror of
https://github.com/prometheus/prometheus.git
synced 2024-11-09 23:24:05 -08:00
promql: adelta/aincrease/arate functions
This are the same functions as delta/increase/rate without extrapolation of values at boundaries. Signed-off-by: Jérôme LOYET <822436+fatpat@users.noreply.github.com>
This commit is contained in:
parent
d23d196db5
commit
6038f723b8
|
@ -5,6 +5,7 @@
|
|||
* [FEATURE] OTLP receiver: Add new option `otlp.promote_resource_attributes`, for any OTel resource attributes that should be promoted to metric labels. #14200
|
||||
* [ENHANCEMENT] OTLP receiver: Warn when encountering exponential histograms with zero count and non-zero sum. #14706
|
||||
* [BUGFIX] tsdb/wlog.Watcher.readSegmentForGC: Only count unknown record types against record_decode_failures_total metric. #14042
|
||||
* [FEATURE] PromQL: Add `adelta`/`aincrease`/`arate` functions: the version without extrapolation of `delta`/`increase`/`rate` functions. #13436
|
||||
|
||||
## 2.54.1 / 2024-08-27
|
||||
|
||||
|
|
|
@ -76,6 +76,43 @@ absent_over_time(sum(nonexistent{job="myjob"})[1h:])
|
|||
In the first two examples, `absent_over_time()` tries to be smart about deriving
|
||||
labels of the 1-element output vector from the input vector.
|
||||
|
||||
## `adelta()`
|
||||
|
||||
**This function has to be enabled via the [feature flag](../feature_flags/) `--enable-feature=promql-experimental-functions`.**
|
||||
|
||||
`adelta(v range-vector)` calculates the difference between the last and the first samples
|
||||
in the range vector `v`, returning an instant vector with the given deltas and
|
||||
equivalent labels. It does not extrapolate values at boundaries as `delta()` does.
|
||||
|
||||
`adelta` should only be used with gauges.
|
||||
|
||||
See `delta()` for more details.
|
||||
|
||||
## `aincrease()`
|
||||
|
||||
**This function has to be enabled via the [feature flag](../feature_flags/) `--enable-feature=promql-experimental-functions`.**
|
||||
|
||||
`aincrease(v range-vector)` calculates the increase in the time series in the range vector.
|
||||
It does not extrapolate values at boundaries as `increase()` does.
|
||||
|
||||
`aincrease` should only be used with counters and native histograms where the
|
||||
components behave like counters.
|
||||
|
||||
See `increase()` for more details.
|
||||
|
||||
## `arate()`
|
||||
|
||||
**This function has to be enabled via the [feature flag](../feature_flags/) `--enable-feature=promql-experimental-functions`.**
|
||||
|
||||
`arate(v range-vector)` calculates the per-second average rate of increase of the
|
||||
time series in the range vector. It does not extrapolate at boundaries values
|
||||
as `rate()` does.
|
||||
|
||||
`arate` should only be used with counters and native histograms where the
|
||||
components behave like counters.
|
||||
|
||||
See `rate()` for more details.
|
||||
|
||||
## `ceil()`
|
||||
|
||||
`ceil(v instant-vector)` rounds the sample values of all elements in `v` up to
|
||||
|
@ -679,7 +716,7 @@ over time and return an instant vector with per-series aggregation results:
|
|||
If the [feature flag](../feature_flags.md#experimental-promql-functions)
|
||||
`--enable-feature=promql-experimental-functions` is set, the following
|
||||
additional functions are available:
|
||||
|
||||
* `adelta`, `aincrease` and `arate`: the acurate version of `delta`, `increase` and `rate` functions without extrapolation of data at boundaries.
|
||||
* `mad_over_time(range-vector)`: the median absolute deviation of all points in the specified interval.
|
||||
|
||||
Note that all values in the specified interval have the same weight in the
|
||||
|
|
|
@ -66,9 +66,9 @@ func funcTime(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper)
|
|||
|
||||
// extrapolatedRate is a utility function for rate/increase/delta.
|
||||
// It calculates the rate (allowing for counter resets if isCounter is true),
|
||||
// extrapolates if the first/last sample is close to the boundary, and returns
|
||||
// extrapolates if extrapolate is true and the first/last sample is close to the boundary, and returns
|
||||
// the result as either per-second (if isRate is true) or overall.
|
||||
func extrapolatedRate(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper, isCounter, isRate bool) (Vector, annotations.Annotations) {
|
||||
func extrapolatedRate(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper, isCounter, isRate, extrapolate bool) (Vector, annotations.Annotations) {
|
||||
ms := args[0].(*parser.MatrixSelector)
|
||||
vs := ms.VectorSelector.(*parser.VectorSelector)
|
||||
var (
|
||||
|
@ -123,6 +123,13 @@ func extrapolatedRate(vals []parser.Value, args parser.Expressions, enh *EvalNod
|
|||
return enh.Out, annos
|
||||
}
|
||||
|
||||
if !extrapolate {
|
||||
if isRate {
|
||||
resultFloat /= ms.Range.Seconds()
|
||||
}
|
||||
return append(enh.Out, Sample{F: resultFloat, H: resultHistogram}), annos
|
||||
}
|
||||
|
||||
// Duration between first/last samples and boundary of range.
|
||||
durationToStart := float64(firstT-rangeStart) / 1000
|
||||
durationToEnd := float64(rangeEnd-lastT) / 1000
|
||||
|
@ -262,17 +269,17 @@ func histogramRate(points []HPoint, isCounter bool, metricName string, pos posra
|
|||
|
||||
// === delta(Matrix parser.ValueTypeMatrix) (Vector, Annotations) ===
|
||||
func funcDelta(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||
return extrapolatedRate(vals, args, enh, false, false)
|
||||
return extrapolatedRate(vals, args, enh, false, false, true)
|
||||
}
|
||||
|
||||
// === rate(node parser.ValueTypeMatrix) (Vector, Annotations) ===
|
||||
func funcRate(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||
return extrapolatedRate(vals, args, enh, true, true)
|
||||
return extrapolatedRate(vals, args, enh, true, true, true)
|
||||
}
|
||||
|
||||
// === increase(node parser.ValueTypeMatrix) (Vector, Annotations) ===
|
||||
func funcIncrease(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||
return extrapolatedRate(vals, args, enh, true, false)
|
||||
return extrapolatedRate(vals, args, enh, true, false, true)
|
||||
}
|
||||
|
||||
// === irate(node parser.ValueTypeMatrix) (Vector, Annotations) ===
|
||||
|
@ -285,6 +292,21 @@ func funcIdelta(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelpe
|
|||
return instantValue(vals, enh.Out, false)
|
||||
}
|
||||
|
||||
// === adelta(Matrix parser.ValueTypeMatrix) (Vector, Annotations) ===
|
||||
func funcAdelta(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||
return extrapolatedRate(vals, args, enh, false, false, false)
|
||||
}
|
||||
|
||||
// === arate(node parser.ValueTypeMatrix) (Vector, Annotations) ===
|
||||
func funcArate(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||
return extrapolatedRate(vals, args, enh, true, true, false)
|
||||
}
|
||||
|
||||
// === aincrease(node parser.ValueTypeMatrix) (Vector, Annotations) ===
|
||||
func funcAincrease(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||
return extrapolatedRate(vals, args, enh, true, false, false)
|
||||
}
|
||||
|
||||
func instantValue(vals []parser.Value, out Vector, isRate bool) (Vector, annotations.Annotations) {
|
||||
samples := vals[0].(Matrix)[0]
|
||||
// No sense in trying to compute a rate without at least two points. Drop
|
||||
|
@ -1653,6 +1675,9 @@ var FunctionCalls = map[string]FunctionCall{
|
|||
"absent_over_time": funcAbsentOverTime,
|
||||
"acos": funcAcos,
|
||||
"acosh": funcAcosh,
|
||||
"adelta": funcAdelta,
|
||||
"aincrease": funcAincrease,
|
||||
"arate": funcArate,
|
||||
"asin": funcAsin,
|
||||
"asinh": funcAsinh,
|
||||
"atan": funcAtan,
|
||||
|
|
|
@ -53,6 +53,24 @@ var Functions = map[string]*Function{
|
|||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
ReturnType: ValueTypeVector,
|
||||
},
|
||||
"adelta": {
|
||||
Name: "adelta",
|
||||
ArgTypes: []ValueType{ValueTypeMatrix},
|
||||
ReturnType: ValueTypeVector,
|
||||
Experimental: true,
|
||||
},
|
||||
"aincrease": {
|
||||
Name: "aincrease",
|
||||
ArgTypes: []ValueType{ValueTypeMatrix},
|
||||
ReturnType: ValueTypeVector,
|
||||
Experimental: true,
|
||||
},
|
||||
"arate": {
|
||||
Name: "arate",
|
||||
ArgTypes: []ValueType{ValueTypeMatrix},
|
||||
ReturnType: ValueTypeVector,
|
||||
Experimental: true,
|
||||
},
|
||||
"asin": {
|
||||
Name: "asin",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
|
|
23
promql/promqltest/testdata/functions.test
vendored
23
promql/promqltest/testdata/functions.test
vendored
|
@ -101,6 +101,29 @@ eval instant at 50m increase(http_requests[100m])
|
|||
|
||||
clear
|
||||
|
||||
# Tests for increase()/aincrease().
|
||||
load 15s
|
||||
http_requests{path="/foo"} 0x40 0+1x20 20x40
|
||||
http_requests{path="/bar"} 0x40 0+1x10 0+1x10 10x40
|
||||
|
||||
eval instant at 21m5s increase(http_requests[15m])
|
||||
{path="/foo"} 20.112994350282488
|
||||
{path="/bar"} 20.112994350282488
|
||||
|
||||
eval instant at 21m5s increase(http_requests[100m])
|
||||
{path="/foo"} 20.07936507936508
|
||||
{path="/bar"} 20.07936507936508
|
||||
|
||||
eval instant at 21m5s aincrease(http_requests[15m])
|
||||
{path="/foo"} 20
|
||||
{path="/bar"} 20
|
||||
|
||||
eval instant at 21m5s aincrease(http_requests[100m])
|
||||
{path="/foo"} 20
|
||||
{path="/bar"} 20
|
||||
|
||||
clear
|
||||
|
||||
# Test for increase() with counter reset.
|
||||
# When the counter is reset, it always starts at 0.
|
||||
# So the sequence 3 2 (decreasing counter = reset) is interpreted the same as 3 0 1 2.
|
||||
|
|
|
@ -77,6 +77,24 @@ export const functionIdentifierTerms = [
|
|||
info: 'Calculate the inverse hyperbolic cosine, in radians, for input series',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
label: 'adelta',
|
||||
detail: 'function',
|
||||
info: 'Calculate the non extrapolated difference between beginning and end of a range vector (for gauges)',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
label: 'aincrease',
|
||||
detail: 'function',
|
||||
info: 'Calculate the non extrapolated increase in value over a range of time (for counters)',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
label: 'arate',
|
||||
detail: 'function',
|
||||
info: 'Calculate the non extrapolated per-second increase over a range vector (for counters)',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
label: 'asin',
|
||||
detail: 'function',
|
||||
|
|
|
@ -17,6 +17,9 @@ import {
|
|||
AbsentOverTime,
|
||||
Acos,
|
||||
Acosh,
|
||||
Adelta,
|
||||
Aincrease,
|
||||
Arate,
|
||||
Asin,
|
||||
Asinh,
|
||||
Atan,
|
||||
|
@ -138,6 +141,24 @@ const promqlFunctions: { [key: number]: PromQLFunction } = {
|
|||
variadic: 0,
|
||||
returnType: ValueType.vector,
|
||||
},
|
||||
[Adelta]: {
|
||||
name: 'adelta',
|
||||
argTypes: [ValueType.matrix],
|
||||
variadic: 0,
|
||||
returnType: ValueType.vector,
|
||||
},
|
||||
[Aincrease]: {
|
||||
name: 'aincrease',
|
||||
argTypes: [ValueType.matrix],
|
||||
variadic: 0,
|
||||
returnType: ValueType.vector,
|
||||
},
|
||||
[Arate]: {
|
||||
name: 'arate',
|
||||
argTypes: [ValueType.matrix],
|
||||
variadic: 0,
|
||||
returnType: ValueType.vector,
|
||||
},
|
||||
[Asin]: {
|
||||
name: 'asin',
|
||||
argTypes: [ValueType.vector],
|
||||
|
|
|
@ -20,7 +20,7 @@ export const promQLHighLight = styleTags({
|
|||
NumberDurationLiteral: tags.number,
|
||||
NumberDurationLiteralInDurationContext: tags.number,
|
||||
Identifier: tags.variableName,
|
||||
'Abs Absent AbsentOverTime Acos Acosh Asin Asinh Atan Atanh AvgOverTime Ceil Changes Clamp ClampMax ClampMin Cos Cosh CountOverTime DaysInMonth DayOfMonth DayOfWeek DayOfYear Deg Delta Deriv Exp Floor HistogramAvg HistogramCount HistogramFraction HistogramQuantile HistogramSum HoltWinters Hour Idelta Increase Irate LabelReplace LabelJoin LastOverTime Ln Log10 Log2 MaxOverTime MinOverTime Minute Month Pi PredictLinear PresentOverTime QuantileOverTime Rad Rate Resets Round Scalar Sgn Sin Sinh Sort SortDesc SortByLabel SortByLabelDesc Sqrt StddevOverTime StdvarOverTime SumOverTime Tan Tanh Time Timestamp Vector Year':
|
||||
'Abs Absent AbsentOverTime Acos Acosh Adelta Aincrease Arate AAsin Asinh Atan Atanh AvgOverTime Ceil Changes Clamp ClampMax ClampMin Cos Cosh CountOverTime DaysInMonth DayOfMonth DayOfWeek DayOfYear Deg Delta Deriv Exp Floor HistogramAvg HistogramCount HistogramFraction HistogramQuantile HistogramSum HoltWinters Hour Idelta Increase Irate LabelReplace LabelJoin LastOverTime Ln Log10 Log2 MaxOverTime MinOverTime Minute Month Pi PredictLinear PresentOverTime QuantileOverTime Rad Rate Resets Round Scalar Sgn Sin Sinh Sort SortDesc SortByLabel SortByLabelDesc Sqrt StddevOverTime StdvarOverTime SumOverTime Tan Tanh Time Timestamp Vector Year':
|
||||
tags.function(tags.variableName),
|
||||
'Avg Bottomk Count Count_values Group LimitK LimitRatio Max Min Quantile Stddev Stdvar Sum Topk': tags.operatorKeyword,
|
||||
'By Without Bool On Ignoring GroupLeft GroupRight Offset Start End': tags.modifier,
|
||||
|
|
|
@ -112,6 +112,9 @@ FunctionIdentifier {
|
|||
Abs |
|
||||
Acos |
|
||||
Acosh |
|
||||
Adelta |
|
||||
Aincrease |
|
||||
Arate |
|
||||
Asin |
|
||||
Asinh |
|
||||
Atan |
|
||||
|
@ -359,6 +362,9 @@ NumberDurationLiteralInDurationContext {
|
|||
AbsentOverTime { condFn<"absent_over_time"> }
|
||||
Acos { condFn<"acos"> }
|
||||
Acosh { condFn<"acosh"> }
|
||||
Adelta { condFn<"adelta"> }
|
||||
Aincrease { condFn<"aincrease"> }
|
||||
Arate { condFn<"arate"> }
|
||||
Asin { condFn<"asin"> }
|
||||
Asinh { condFn<"asinh">}
|
||||
Atan { condFn<"atan"> }
|
||||
|
|
Loading…
Reference in a new issue