Skip to content

Conversation

@dnhatn
Copy link
Member

@dnhatn dnhatn commented Nov 16, 2025

This change adds window function support for time-series aggregation functions including rate, avg_over_time, and last_over_time. Additional time-series aggregation functions will be supported in a follow-up to keep this PR focused.

Examples:

TS k8s
| WHERE TRANGE("2024-05-10T00:05:00.000Z", "2024-05-10T00:10:00.000Z")
| STATS rate_bytes_in=avg(rate(network.total_bytes_in, 5minute)) 
              BY cluster, time_bucket = bucket(@timestamp, 1minute)

Window 5-minute over 1-minute buckets.

TS k8s 
| STATS events = sum(avg_over_time(events_received, 10minute)) 
             BY pod, time_bucket = tbucket(5minute)
| SORT time_bucket, pod
| LIMIT 10

Window 10-minute over 5-minute buckets.

Limitation:

ES|QL currently supports only windows that are multiples of the bucket size.

@dnhatn dnhatn added >enhancement :StorageEngine/ES|QL Timeseries / metrics / logsdb capabilities in ES|QL labels Nov 16, 2025
@elasticsearchmachine
Copy link
Collaborator

Hi @dnhatn, I've created a changelog YAML for you.

@github-actions
Copy link
Contributor

ℹ️ Important: Docs version tagging

👋 Thanks for updating the docs! Just a friendly reminder that our docs are now cumulative. This means all 9.x versions are documented on the same page and published off of the main branch, instead of creating separate pages for each minor version.

We use applies_to tags to mark version-specific features and changes.

Expand for a quick overview

When to use applies_to tags:

✅ At the page level to indicate which products/deployments the content applies to (mandatory)
✅ When features change state (e.g. preview, ga) in a specific version
✅ When availability differs across deployments and environments

What NOT to do:

❌ Don't remove or replace information that applies to an older version
❌ Don't add new information that applies to a specific version without an applies_to tag
❌ Don't forget that applies_to tags can be used at the page, section, and inline level

🤔 Need help?

@dnhatn dnhatn changed the title Support window function in time-series aggregations Support window functions in time-series aggregations Nov 16, 2025
Interval prev = intervals[i];
if (prev.v2 > next.v2) {
state.resets += prev.v2;
if (prev.v1 > next.v2) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Existing bug in rate that only manifests when using window functions.

@dnhatn dnhatn requested a review from kkrik-es November 17, 2025 00:16
@dnhatn dnhatn marked this pull request as ready for review November 17, 2025 00:16
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-storage-engine (Team:StorageEngine)

TimeSeriesGroupingAggregatorEvaluationContext evaluationContext
) {
if (selected.getPositionCount() > 0) {
// TODO: rewrite to NO_WINDOW in the planner if the bucket and the window are the same
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the window is smaller than the bucket, e.g.

TS metrics | STATS sum(rate(reqs, 1m) BY TBUCKET(5m)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should reject this query during translation.

examples = { @Example(file = "k8s-timeseries", tag = "avg_over_time") }
examples = {
@Example(file = "k8s-timeseries", tag = "avg_over_time"),
@Example(file = "k8s-timeseries-avg-over-time", tag = "avg_over_time_with_window") }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we skip the version with window for now? I think it's gonna show up in the documentation, which will be confusing for users in 9.2.. Let's discuss separate with Liam on how best to approach this, once we have all functions updated to support windows.

We do need to add them in the tests so that Kibana documentation is updated..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++ I removed this in 3e42bb7

int window = between(1, 20);
var query = String.format(Locale.ROOT, """
TS k8s
| STATS avg(last_over_time(network.bytes_in, %s minute)) BY bucket(@timestamp, 1 minute)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: use TBUCKET?

}
}
throw new EsqlIllegalArgumentException(
"Unsupported window [{}] of aggregate function [{}]; the window must be a positive multiple of the time bucket [{}].",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or smaller than the time bucker?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++ I pushed e0a3c5a

Copy link
Contributor

@kkrik-es kkrik-es left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, so clean! Mostly a question around the documentation, to avoid confusing users of 9.2.

@dnhatn
Copy link
Member Author

dnhatn commented Nov 17, 2025

Thanks Kostas!

@dnhatn dnhatn merged commit 59da11b into elastic:main Nov 17, 2025
36 checks passed
@dnhatn dnhatn deleted the add-window-function-rate branch November 17, 2025 19:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

>enhancement :StorageEngine/ES|QL Timeseries / metrics / logsdb capabilities in ES|QL Team:StorageEngine v9.3.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants