Summary from
- Understanding Prometheus Range Vectors
- The Anatomy of a PromQL Query
- What’s a Vector?
- Since Prometheus is a timeseries database, all data is in the context of some timestamp. The series that maps a timestamp to recorded data is called a timeseries
- a set of related timeseries is called a vector
- Ex.
http_requests_totalis a vector representing the total number of http requests received by a servicehttp_requests_total{code="200"}http_requests_total refers to the entire set of timeseries that are named that. And by appending a{code="200"}, we’re selecting a subset.
- Types of Vectors
- Instant vector - a set of timeseries where every timestamp maps to a single data point at that “instant”
- Imagine evaluating the expression
http_requests_totalat a given timestamp. http_requests_total is an instant vector selector that selects the latest sample for any time series with the metric namehttp_requests_total. More specifically, "latest" means "at most 5 minutes old and not stale", relative to the evaluation timestamp. So this selector will only yield a result for series that have a sample at most 5 minutes prior to the evaluation timestamp, and where the last sample before the evaluation timestamp is not a stale marker (an explicit way of marking a series as terminating at a certain time in the Prometheus TSDB).
- Imagine evaluating the expression
- Range vector - a set of timeseries where every timestamp maps to a “range” of data points, recorded some duration into the past.
- Range vector is mostly used for graphs, where you want to show a PromQL expression over a given time range. A range query works exactly like many completely independent instant queries that are evaluated at subsequent time steps over a given range of time. Of course, this is highly optimized under the hood and Prometheus doesn't actually run many independent instant queries in this case.
- Instant vector - a set of timeseries where every timestamp maps to a single data point at that “instant”
- Differences
- Instant vectors can be charted; Range vectors cannot. This is because charting something involves displaying a data point on the y-axis for every timestamp on the x-axis. Instant vectors have a single value for every timestamp, while range vectors have many of them. For the purpose of charting a metric, it is undefined1 how to show multiple data points for a single timestamp in a timeseries.
- Instant vectors can be compared and have arithmetic performed on them; Range vectors cannot. This is also due to the way comparison and arithmetic operators are defined. For every timestamp, if we have multiple values, we don’t know how to add1 or compare them to another timeseries of a similar nature.
- Range Vectors for counters. We take the instant vector and append our duration
[15m]. This part is called the range selector and it transforms the instant vector into a range vector. We then use a function like increase which effectively subtracts the data point at the start of the range from the one at the end.increase(http_requests_total{code="200",handler="/api/v1/query"}[15m])representit is the increase in the total number of requests over the past fifteen minutes
Summary from
- Understanding Prometheus Range Vectors
- The Anatomy of a PromQL Query
- What’s a Vector?
- Since Prometheus is a timeseries database, all data is in the context of some timestamp. The series that maps a timestamp to recorded data is called a timeseries
- a set of related timeseries is called a vector
- Ex.
http_requests_totalis a vector representing the total number of http requests received by a servicehttp_requests_total{code="200"}http_requests_total refers to the entire set of timeseries that are named that. And by appending a{code="200"}, we’re selecting a subset.
- Types of Vectors
- Instant vector - a set of timeseries where every timestamp maps to a single data point at that “instant”
- Imagine evaluating the expression
http_requests_totalat a given timestamp. http_requests_total is an instant vector selector that selects the latest sample for any time series with the metric namehttp_requests_total. More specifically, "latest" means "at most 5 minutes old and not stale", relative to the evaluation timestamp. So this selector will only yield a result for series that have a sample at most 5 minutes prior to the evaluation timestamp, and where the last sample before the evaluation timestamp is not a stale marker (an explicit way of marking a series as terminating at a certain time in the Prometheus TSDB).
- Imagine evaluating the expression
- Range vector - a set of timeseries where every timestamp maps to a “range” of data points, recorded some duration into the past.
- Range vector is mostly used for graphs, where you want to show a PromQL expression over a given time range. A range query works exactly like many completely independent instant queries that are evaluated at subsequent time steps over a given range of time. Of course, this is highly optimized under the hood and Prometheus doesn't actually run many independent instant queries in this case.
- Instant vector - a set of timeseries where every timestamp maps to a single data point at that “instant”
- Differences
- Instant vectors can be charted; Range vectors cannot. This is because charting something involves displaying a data point on the y-axis for every timestamp on the x-axis. Instant vectors have a single value for every timestamp, while range vectors have many of them. For the purpose of charting a metric, it is undefined1 how to show multiple data points for a single timestamp in a timeseries.
- Instant vectors can be compared and have arithmetic performed on them; Range vectors cannot. This is also due to the way comparison and arithmetic operators are defined. For every timestamp, if we have multiple values, we don’t know how to add1 or compare them to another timeseries of a similar nature.
- Range Vectors for counters. We take the instant vector and append our duration
[15m]. This part is called the range selector and it transforms the instant vector into a range vector. We then use a function like increase which effectively subtracts the data point at the start of the range from the one at the end.increase(http_requests_total{code="200",handler="/api/v1/query"}[15m])representit is the increase in the total number of requests over the past fifteen minutes
VictoriaMetrics author here. This is Prometheus-like monitoring system, which supports PromQL-like query language - MetricsQL.
The instant vector and range vector are indeed confusing terms in Prometheus. That's why these terms are avoided in VictoriaMetrics docs. Prometheus query language - PromQL - provides various functions, which can be divided into two groups:
- Functions, which accept only
instant vector. Such functions can be split into the following subgroups:- transform functions, which apply various transformations individually per each input time series. For example, abs()
- label manipulation functions, which modify labels and metric names for the input time series. For example, label_replace()
- aggregate functions, which aggregate multiple input time series into specified groups of output time series. For example, sum(). Fun fact is that aggregate functions are named
aggregation operatorsin Prometheus - see these docs.
- Functions, which accept only
range vector. VictoriaMetrics names such functions as rollup functions, since they calculate the result based on input time series samples over the given lookbehind window specified in square brackets (aka sliding window). For example,rate(http_requests_total[5m])calculates the average per-second increase rate forhttp_requests_totaltime series over the last 5 minutes.
From user's perspective the only difference between instant vector and range vector is that range vector is constructed from the instant vector by adding a lookbehind window in square brackets. For example, http_requests_total is an instant vector, while http_requests_total[5m] is a range vector. I'd say that the range vector syntax is just a syntactic sugar for rollup functions in PromQL. E.g. rate(m[d]) could be written as rate(m, d), e.g. the lookbehind window d could be passed as a separate argument to rollup functions.
Generating range vectors from return values in Prometheus queries - Stack Overflow
prometheus - Understanding range vector selectors - Stack Overflow
Instant vectors to ranged vectors
promql - Instant vector operations on prometheus range vectors - Stack Overflow
Solution
It's possible with the subquery-syntax (introduced in Prometheus version 2.7):
deriv(rate(varnish_main_client_req[2m])[5m:10s])
Warning: These subqueries are expensive, i.e. create very high load on Prometheus. Use recording-rules when you use these queries regularly (in alerts, etc.).
Subquery syntax
<instant_query>[<range>:<resolution>]
instant_query: a PromQL-function which returns an instant-vector)range: offset (back in time) to start the first subqueryresolution: the size of each of the subqueries.
It returns a range-vector.
In the example above, Prometheus runs rate() (= instant_query) 30 times (the first from 5 minutes ago to -4:50, ..., the last -0:10 to now).
The resulting range-vector is input to the deriv()-function.
Another example (mostly available on all Prometheus instances):
deriv(rate(prometheus_http_request_duration_seconds_sum{job="prometheus"}[1m])[5m:10s])
Without the subquery-range ([5m:10s]), you'll get this error-message:
parse error at char 80: expected type range vector in call to function "deriv", got instant vector
Yes, you need to use a recording rule for this.
Prometheus calculates the rate of client requests over the last 2 mins and returns a derivative of the resulting values over the last 5 mins.
Herein lies the problem - at what interval should Prometheus synthesise this data?
Why doesn’t ”(some_metric*10)[1h]” work? When i try it i get error: ”ranges only allowed for vector selectors”.
Wouldnt a instant vector and a scalar together return another instant vector that can be turned into a ranged vector?
Im very very stuck pls help
Is there any way to perform an instant vector operation on a range vector?
No. Prometheus doesn't allow anything like this.
But you can apply range selector over something other than vector selector using subquery syntax. So in your example it would be something like.
avg(avg_over_time((count_containers > 0)[1h:15s]))
Notice that in this case you must place : in the range selector to indicate usage of subquery.
And for this example I used resolution 15s, to indicate that result of the query should be calculated for each 15 seconds window. But you might want to adjust this to your needs, depending on needed precision, scrape interval, etc. Also, resolution can be omitted (while preserving :, like [1h:]): in that case value of evaluation_interval will be used.
we want to count the fraction of the time where we have at least one, we might try to do:
Your attempt of the query, even if it were supported, would not produced what you wanted. Rather it would calculate average number of containers when number of containers was positive.
To calculate percentage of the time when number of containers was positive use following
avg(avg_over_time( (count_containers > bool 0)[1h:15s] ))
Expression count_containers > bool 0 will return 1 if number of containers is positive, and 0 otherwise.
If you want calculating the share of time when count_containers was positive during the last hour, it is better to use the following PromQL query:
sum(sum_over_time((count_containers >bool 0)[1h:15s]))
/
sum(count_over_time(count_containers[1h:15s]))
This query uses the following PromQL features:
- subquery
>operator withboolmodifier- sum_over_time and count_over_time rollup functions
- sum aggregate function
/binary operator.
Note that the avg(avg_over_time(...)) query may return unexpected results, since average of averages may not equal to the average.
P.S. the query above assumes that the interval between raw samples of a single time series equals to 15 seconds - see 15s in square brackets after the colon in the query above. This interval is also known as scrape_interval in Prometheus ecosystem. If your data has different scrape interval, then the value in square brackets should be adjusted in the query above. Otherwise query results will be incorrect.
P.P.S. The query can be simplified to the following one with share_gt_over_time function in MetricsQL - PromQL-like query language I work on:
share_gt_over_time(count_containers[1h], 0)