Skip to content
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
6463013
Add documentation for TS source
kkrik-es Sep 9, 2025
8677ce0
add toc ref
kkrik-es Sep 9, 2025
49630b7
update nav
kkrik-es Sep 9, 2025
3beebc4
update
kkrik-es Sep 9, 2025
4104e1a
Merge branch 'main' into tsdb/ts-doc
marciw Sep 10, 2025
c860567
Apply suggestions from code review
kkrik-es Sep 11, 2025
5d23ffe
Update ts.md
kkrik-es Sep 11, 2025
4ec4daf
Merge branch 'main' into tsdb/ts-doc
kkrik-es Sep 11, 2025
2feaffc
Apply suggestions from code review
kkrik-es Sep 12, 2025
d9e9451
update
kkrik-es Sep 12, 2025
fd54d14
add links to time-series functions
kkrik-es Sep 12, 2025
7dbd092
restore brief description
kkrik-es Sep 12, 2025
54f994b
fix formatting
kkrik-es Sep 12, 2025
b299ec4
remove links
kkrik-es Sep 12, 2025
0e56b47
Apply suggestions from code review
kkrik-es Sep 15, 2025
9b3bb28
Update ts.md
kkrik-es Sep 15, 2025
e452620
Update ts.md
kkrik-es Sep 16, 2025
bf342c2
Update ts.md
kkrik-es Sep 16, 2025
9b557ce
Merge branch 'main' into tsdb/ts-doc
kkrik-es Sep 19, 2025
647534c
Merge branch 'refs/heads/main' into tsdb/ts-doc
kkrik-es Sep 19, 2025
8afa050
update
kkrik-es Sep 19, 2025
a83f082
Merge remote-tracking branch 'origin/tsdb/ts-doc' into tsdb/ts-doc
kkrik-es Sep 19, 2025
5cb5f45
Merge branch 'main' into tsdb/ts-doc
kkrik-es Sep 23, 2025
086fece
mark over time functions as preview
kkrik-es Sep 24, 2025
a376340
Merge branch 'main' into tsdb/ts-doc
kkrik-es Sep 24, 2025
020d26b
add time-series aggs
kkrik-es Sep 24, 2025
ef0611f
Merge remote-tracking branch 'origin/tsdb/ts-doc' into tsdb/ts-doc
kkrik-es Sep 24, 2025
cd670c1
list time-series aggs
kkrik-es Sep 24, 2025
51b2170
add missing
kkrik-es Sep 24, 2025
e499726
add toc
kkrik-es Sep 24, 2025
bd2f557
remove snapshot notes
kkrik-es Sep 24, 2025
a9cc818
add title
kkrik-es Sep 24, 2025
cd4ed00
sum_over_time example
kkrik-es Sep 24, 2025
8954b44
fix ts agg refs
kkrik-es Sep 24, 2025
1d25d54
add links to TS doc
kkrik-es Sep 24, 2025
8545d17
fix links to TS doc
kkrik-es Sep 24, 2025
c9a21d4
fix links to TS doc
kkrik-es Sep 24, 2025
9e192d9
Merge branch 'main' into tsdb/ts-doc
kkrik-es Sep 24, 2025
4d7e593
remove note
kkrik-es Sep 24, 2025
f32b1ff
Merge branch 'main' into tsdb/ts-doc
kkrik-es Sep 25, 2025
ee1df8b
Apply suggestions from code review
kkrik-es Sep 25, 2025
9276b86
Update ts.md
kkrik-es Sep 25, 2025
b0600a9
Apply suggestions from code review
kkrik-es Sep 25, 2025
aa587e8
Apply suggestions from code review
kkrik-es Sep 25, 2025
1f17af3
update function description
kkrik-es Sep 25, 2025
71fa400
Update docs/reference/query-languages/esql/_snippets/commands/layout/…
kkrik-es Sep 25, 2025
013a5e0
Merge branch 'main' into tsdb/ts-doc
kkrik-es Sep 25, 2025
2b1832c
Apply suggestions from code review
kkrik-es Sep 26, 2025
59541ae
Merge branch 'main' into tsdb/ts-doc
kkrik-es Sep 26, 2025
a2706ea
fix from review
kkrik-es Sep 26, 2025
2921961
Update ts.md
kkrik-es Sep 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 96 additions & 7 deletions docs/reference/query-languages/esql/_snippets/commands/layout/ts.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
```yaml {applies_to}
serverless: ga
stack: ga
serverless: preview
stack: preview 9.2.0
```

The `TS` command is similar to the `FROM` source command,
but with two key differences: it targets only [time-series indices](docs-content://manage-data/data-store/data-streams/time-series-data-stream-tsds.md)
and enables the use of time-series aggregation functions
with the [STATS](/reference/query-languages/esql/commands/stats-by.md) command.
**Brief description**

The `TS` source command is similar to the [`FROM`](/reference/query-languages/esql/commands/from.md)
source command, with the following key differences:

- Targets only [time-series indices](docs-content://manage-data/data-store/data-streams/time-series-data-stream-tsds.md)
- Enables the use of time-series aggregation functions inside the
[STATS](/reference/query-languages/esql/commands/stats-by.md) command

**Syntax**

Expand All @@ -22,10 +26,95 @@ TS index_pattern [METADATA fields]
`fields`
: A comma-separated list of [metadata fields](/reference/query-languages/esql/esql-metadata-fields.md) to retrieve.

**Description**

The `TS` source command enables time series semantics and enables the usage of
time series aggregation functions in the `STATS` command, such as
[`AVG_OVER_TIME()`](/reference/query-languages/esql/functions-operators/time-series-aggregation-functions.md#esql-avg_over_time),
or [`RATE`](/reference/query-languages/esql/functions-operators/time-series-aggregation-functions.md#esql-rate).
These functions are implicitly evaluated per per time-series, with their results
then aggregated per grouping bucket using a secondary aggregation
function. More concretely, consider the following query:
Copy link
Contributor

Choose a reason for hiding this comment

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

@leemthompo going for conciseness, but possibly too far?


```esql
TS metrics
| WHERE @timestamp >= now() - 1 hour
| STATS SUM(RATE(search_requests)) BY TBUCKET(1 hour), host
```

This query calculates the total rate of search requests (tracked through
counter `search`) per host and hour. Here, the `rate()` function is first
applied per time-series and hourly time bucket, with the results then summed per
host and hourly bucket, as each host value may map to many time-series.

This paradigm with a pair of aggregation functions is standard for time-series
querying. Supported inner (time-series) functions per
[metric type](docs-content://manage-data/data-store/data-streams/time-series-data-stream-tsds.md#time-series-metric)
are listed [here](/reference/query-languages/esql/functions-operators/time-series-aggregation-functions.md)
and apply to downsampled data too, with the same semantics as for raw data.

::::{note}
If a query is missing an inner (time-series) aggregation function,
[`LAST_OVER_TIME()`](/reference/query-languages/esql/functions-operators/time-series-aggregation-functions.md#esql-last_over_time)
is assumed and used implicitly. For instance, the following two queries are
equivalent, returning the average of the last memory usage values per time-series:

```esql
TS metrics | STATS AVG(memory_usage)

TS metrics | STATS AVG(LAST_OVER_TIME(memory_usage))
```

Calculating the average memory usage across per-time-series averages requires
the following query:

```esql
TS metrics | STATS AVG(AVG_OVER_TIME(memory_usage))
```
::::

Use regular (non-time-series) [aggregation functions](/reference/query-languages/esql/functions-operators/aggregation-functions.md),
such as `SUM()` as outer aggregation functions. Using a time-series aggregation,
in combination with an inner function, leads to an error. For instance, the
following query is invalid:

```esql
TS metrics | STATS AVG_OVER_TIME(RATE(memory_usage))
```

::::{note}
It's currently required to wrap a time-series aggregation function inside a
regular aggregation function. For instance, the following query is invalid:

```esql
TS metrics | STATS RATE(search_requests)
```
::::

**Best practices**

- Avoid mixing aggregation functions on different metrics in the same query, to
avoid interference between different time-series. For instance, if one metric
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is very poorly phrased.. Effectively, if we have

STATS max(rate(foo) + rate(bar))

foo and bar need to have the same dimension values, otherwise for some dimension combinations the rate for either one will be null. The + operator doesn't like that, so it returns null too.

Copy link
Contributor

Choose a reason for hiding this comment

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

Claude's attempt to rewrite this 🤖 + some edits by me -- @kkrik-es WDYT? please check for accuracy!


Avoid aggregating multiple metrics in the same query when those metrics have different dimensional cardinalities. For example, in STATS max(rate(foo)) + rate(bar)), if foo and bar don't share the same dimension values, the rate for one metric will be null for some dimension combinations. Because the + operator returns null when either input is null, the entire result becomes null for those dimensions. Additionally, queries that aggregate a single metric can filter out null values more efficiently.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Applied, thanks!

Copy link
Contributor

@marciw marciw Sep 25, 2025

Choose a reason for hiding this comment

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

unresolving this in reference to #134373 (comment)

(the code font didn't get applied as shown in this claude+me suggestion -- you can "edit" the comment to copy the markdown instead of plain text)

is missing values for a given time-series, the aggregation function
may return null for a given combination of dimensions, which may lead to a
null result for that group if the secondary function returns null on a null
arg. More so, null metric filtering is more efficient when a query includes
a single metric.
- Prefer the `TS` command for aggregations on time-series data. `FROM` is still
applicable, e.g. to list document contents, but it's not optimized to process
time-series data efficiently. More so, the `TS` command can't be combined
with certain operation such as [`FORK`](/reference/query-languages/esql/commands/fork.md),
before the `STATS` command is applied. That said, once `STATS` is applied, its
tabular output can be further processed as applicable, in line with regular
ES|QL processing.
- Include a time range filter on `@timestamp`, to prevent scanning
unnecessarily large data volumes.

**Examples**

```esql
TS metrics
| STATS sum(last_over_time(memory_usage))
| WHERE @timestamp >= now() - 1 day
| STATS SUM(AVG_OVER_TIME(memory_usage)) BY host, TBUCKET(1 hour)
```

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
* [`ABSENT`](../../functions-operators/aggregation-functions.md#esql-absent)
* [`AVG`](../../functions-operators/aggregation-functions.md#esql-avg)
* [`COUNT`](../../functions-operators/aggregation-functions.md#esql-count)
* [`COUNT_DISTINCT`](../../functions-operators/aggregation-functions.md#esql-count_distinct)
* [`FIRST`](../../functions-operators/aggregation-functions.md#esql-first)
* [`LAST`](../../functions-operators/aggregation-functions.md#esql-last)
* [`MAX`](../../functions-operators/aggregation-functions.md#esql-max)
* [`MEDIAN`](../../functions-operators/aggregation-functions.md#esql-median)
* [`MEDIAN_ABSOLUTE_DEVIATION`](../../functions-operators/aggregation-functions.md#esql-median_absolute_deviation)
* [`MIN`](../../functions-operators/aggregation-functions.md#esql-min)
* [`PERCENTILE`](../../functions-operators/aggregation-functions.md#esql-percentile)
* [`PRESENT`](../../functions-operators/aggregation-functions.md#esql-present)
* [`SAMPLE`](../../functions-operators/aggregation-functions.md#esql-sample)
* [preview] [`ST_CENTROID_AGG`](../../functions-operators/aggregation-functions.md#esql-st_centroid_agg)
* [preview] [`ST_EXTENT_AGG`](../../functions-operators/aggregation-functions.md#esql-st_extent_agg)
Expand All @@ -14,4 +18,3 @@
* [`TOP`](../../functions-operators/aggregation-functions.md#esql-top)
* [preview] [`VALUES`](../../functions-operators/aggregation-functions.md#esql-values)
* [`WEIGHTED_AVG`](../../functions-operators/aggregation-functions.md#esql-weighted_avg)
* [`PRESENT`](../../functions-operators/aggregation-functions.md#esql-present)
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
- [`FROM`](/reference/query-languages/esql/commands/from.md)
- [`ROW`](/reference/query-languages/esql/commands/row.md)
- [`SHOW`](/reference/query-languages/esql/commands/show.md)
- [`SHOW`](/reference/query-languages/esql/commands/show.md)
- [`TS`](/reference/query-languages/esql/commands/ts.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
* [preview] [`ABSENT_OVER_TIME`](../../functions-operators/time-series-aggregation-functions.md#esql-absent_over_time)
* [preview] [`AVG_OVER_TIME`](../../functions-operators/time-series-aggregation-functions.md#esql-avg_over_time)
* [preview] [`COUNT_OVER_TIME`](../../functions-operators/time-series-aggregation-functions.md#esql-count_over_time)
* [preview] [`COUNT_DISTINCT_OVER_TIME`](../../functions-operators/time-series-aggregation-functions.md#esql-count_distinct_over_time)
* [preview] [`FIRST_OVER_TIME`](../../functions-operators/time-series-aggregation-functions.md#esql-first_over_time)
* [preview] [`LAST_OVER_TIME`](../../functions-operators/time-series-aggregation-functions.md#esql-last_over_time)
* [preview] [`MAX_OVER_TIME`](../../functions-operators/time-series-aggregation-functions.md#esql-max_over_time)
* [preview] [`MIN_OVER_TIME`](../../functions-operators/time-series-aggregation-functions.md#esql-min_over_time)
* [preview] [`PRESENT_OVER_TIME`](../../functions-operators/time-series-aggregation-functions.md#esql-present_over_time)
* [preview] [`RATE`](../../functions-operators/time-series-aggregation-functions.md#esql-rate)
* [preview] [`SUM_OVER_TIME`](../../functions-operators/time-series-aggregation-functions.md#esql-sum_over_time)
10 changes: 10 additions & 0 deletions docs/reference/query-languages/esql/commands/ts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
navigation_title: "TS"
mapped_pages:
- https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-commands.html#esql-ts
---

# `TS` [esql-ts]

:::{include} ../_snippets/commands/layout/ts.md
:::
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ mapped_pages:
:::
::::

::::{dropdown} Time-series aggregate functions
:open:
:::{include} _snippets/lists/time-series-aggregation-functions.md
:::
::::

::::{dropdown} Grouping functions
:open:
:::{include} _snippets/lists/grouping-functions.md
Expand Down
Loading