Miscellaneous operators

This page covers FuseQL operators and reference material that do not fit a larger category: time-shifted comparison, forecasting, and reserved field names.

compare timeshift

Adds one or more columns containing time-shifted historical values alongside the current aggregated data. Use compare timeshift to perform day-over-day, week-over-week, or custom-period comparisons in a single query — each shifted column contains the metric value from the specified duration ago.

compare timeshift can only be used after an aggregation operator such as count, sum, or avg. It requires aggregated data to perform time-based comparisons.

Syntax

| compare timeshift <duration>
| compare timeshift <duration> <count>
| compare timeshift <duration> as <alias>
| compare timeshift <duration> as <alias>, timeshift <duration2> as <alias2>
none

Parameters

Parameter Required Description

<duration>

Required

How far back to shift. Supported units: m (minutes), h (hours), d (days), w (weeks).

<count>

Optional

Number of shifted periods to generate. Creates <count> columns, one for each successive period. Default is 1.

as <alias>

Optional

Custom name for the comparison column. Without an alias, columns are named <metric>_<duration>_<index> (e.g., count_1d_1).

Multiple timeshifts

Optional

Specify additional timeshift <duration> as <alias> clauses separated by commas to compare against multiple reference periods simultaneously.

Example

Compare hourly nginx request counts with both yesterday and last week.

source="nginx"
| timeslice 1h
| count by (_timeslice)
| compare timeshift 1d as yesterday, timeshift 1w as last_week
Expected output (illustrative)
_timeslice _count count_yesterday count_last_week

2026-06-27 18:00:00 UTC

650,712

598,240

612,450

2026-06-27 19:00:00 UTC

474,040

441,800

488,920

Rows return NULL for the shifted columns when no matching historical data exists for that time period. When timeslice is present, the operator normalizes time values to align with the baseline period. Column naming rules: with alias → <metric><alias>; without alias → <metric>_<duration>_<index>; duplicate aliases → <metric>_<alias>_<index>.

compose

Converts query results into a FuseQL filter expression (a boolean OR of field=value conditions). compose is primarily used as the final stage of a subquery, but can also be run standalone to preview the generated filter. Use it to dynamically build filters from aggregated data — for example, generating a filter from the top error-producing hosts discovered in one query and applying it to another.

Syntax

| compose <field1>[, <field2>, ...] [maxresults=<N>] [keywords]
none

Parameters

Parameter Required Description

<field1>, …​

Required

One or more field names. Multiple fields create AND conditions within each row; rows are combined with OR.

maxresults=<N>

Optional

Limits the number of result rows used in filter generation. Default: 2500. Maximum: 10000.

keywords

Optional

Generates keyword grep searches ("value") instead of field equality filters (field="value").

Example

Generate a filter from the level and org_id combinations found in query-service logs, then use it to filter another source.

source="query-service"
| count by level, org_id
| compose level, org_id
Expected output (the compose operator produces a filter string)
_filter

level="error" and org_id="pisco-shared") or (level="info" and org_id="pisco-shared"

compose is most powerful inside a subquery block:

[subquery: source="query-service" | count by host | compose host] | timeslice 20s | count by _timeslice
none

Run compose standalone first to verify the generated filter size before embedding it in a production subquery. The keywords flag is not supported inside where or if clauses.

Linear Forecast

Forecasts future metric values by fitting a linear regression model to historical time-series data. Use Linear Forecast when your data shows a consistent upward or downward trend without strong seasonal patterns — for example, predicting steady traffic growth or a declining error rate.

Linear forecasting is built on the Linear Regression. It extrapolates the trend line forward for a specified duration.

Syntax

| predict (<field>) by <bucket_size>, model=linear, forecast=<duration>
none

Parameters

Parameter Required Description

(<field>)

Required

The aggregated numeric field to forecast.

by <bucket_size>

Required

The time bucket size matching the upstream timeslice duration (e.g., 60s, 5m).

model=linear

Required

Selects the linear regression model.

forecast=<duration>

Required

How far forward to project. Expressed in seconds (e.g., 3600s for 1 hour).

Example

show count unique of @*:error by Everything roll up every 1m forecast linear

Linear Forecast

Linear forecasting works best for data with a clear monotonic trend. For data with hourly or daily cyclical patterns, use Seasonal Forecast instead. The forecast duration determines how many additional projected data points appear after the last historical data point.

Reserved fields

FuseQL provides a set of reserved field names that map to the core columns shown in the Log Search results view. Use these fields to filter, extract, or alias the primary log attributes without parsing them from the raw log line.

Field reference

Field Maps to Description

__kf_msg

Message column

The full raw log line text. Regex matching against __kf_msg is optimized — the engine performs automatic substring extraction for improved query performance.

__kf_level

Level column

The log severity level (e.g., ERROR, WARN, INFO, DEBUG).

__kf_source

Source column

The log source identifier (equivalent to the source facet).

Example

Filter logs by message pattern, level, and source simultaneously using reserved fields.

__kf_msg =~ "ERROR.*connection.*timeout"
__kf_level = "ERROR"
__kf_source = "nginx"

Alias example

Reorder the default log columns by aliasing reserved fields. Using aliases disables the default column display and shows only the aliased versions in the result.

* | __kf_msg as LogMessage | __kf_level as LogLevel | __kf_source as LogSource

Reserved fields are available in all FuseQL contexts — filter expressions, where clauses, and pipe stages. __kf_msg regex matching (=~) is particularly efficient because the engine can use index-based substring extraction rather than scanning the full raw text for every row.

Seasonal Forecast

Forecasts future metric values from time-series data that contains recurring seasonal patterns — hourly, daily, or weekly cycles — in addition to overall trends. Use Seasonal Forecast when your data shows predictable periodic behavior, such as traffic spikes every morning or error rate increases every evening.

Seasonal forecasting is built on Prophet, which handles seasonality, trend, and holiday effects simultaneously.

Syntax

| predict (<field>) by <bucket_size>, model=seasonal, seasonality=<period>, forecast=<duration>
none

Parameters

Parameter Required Description

(<field>)

Required

The aggregated numeric field to forecast.

by <bucket_size>

Required

The time bucket size matching the upstream timeslice duration (e.g., 60s, 5m).

model=seasonal

Required

Selects the seasonal (Prophet) model.

seasonality=<period>

Required

The dominant seasonal period. Supported values: hourly (24-hour cycle) or daily (7-day cycle).

forecast=<duration>

Required

How far forward to project. Expressed in seconds (e.g., 3600s for 1 hour).

Example

show count unique of @*:error by Everything roll up every 1m forecast seasonal

Seasonal Forecast

Use seasonality=hourly for data with intra-day cycles (for example, a traffic spike at the top of each hour). Use seasonality=daily for data with day-of-week patterns (for example, higher traffic on weekdays). For data without seasonal patterns, use Linear Forecast instead.

subquery

Executes a nested inner query, converts its results into a filter expression using compose, and applies that filter to the outer query. Use subquery to correlate data across sources without manual copy-paste — for example, finding all logs from hosts that also appear in a separate error log source.

The subquery operator must always include a compose operator as its final stage.

Syntax

[subquery: <inner_query> | compose <fields> [maxresults=<N>] [keywords]]
none

The subquery block can appear in three positions:

[subquery: <inner_query> | compose <fields>] | <outer_query>

<outer_query> | where [subquery: <inner_query> | compose <fields>]

<outer_query> | if([subquery: <inner_query> | compose <fields>], <true_value>, <false_value>) as <field>
none

Parameters

Parameter Required Description

<inner_query>

Required

Any valid FuseQL query. Its results are passed to compose.

compose <fields>

Required

Converts the inner query’s result rows into a boolean filter expression.

maxresults=<N>

Optional

Limits how many result rows compose uses. Default: 2500. Maximum: 10000.

keywords

Optional

Generates keyword grep searches instead of field equality filters. Not supported with where or if.

Example

Filter logs from org_id="pisco-shared" to only those originating from hosts that also appear in query-service logs.

org_id="pisco-shared"
and [subquery: source="query-service" | count by host | compose host]
| timeslice 20s
| count by _timeslice

The inner query produces:

host _count

server-1

250

server-2

180

compose host converts this to host="server-1") or (host="server-2", making the full query equivalent to:

org_id="pisco-shared"
and ((host="server-1") or (host="server-2"))
| timeslice 20s | count by _timeslice

Always test the outer query independently before adding the inner subquery. Subqueries within if or where are typically more expensive than subqueries placed at the start of the search expression. Subqueries are not supported in Scheduled Views.

topk

The topk operator keeps the highest-ranked rows of an aggregation result. Use it to answer questions like "the top 5 hosts by error count" or "the top 3 endpoints by latency per service".

topk runs after an aggregation. It sorts the aggregated rows in descending order by a ranking field, keeps at most k rows, and adds a rank column starting at 1. With a by clause, topk ranks within each group independently and returns the top _k rows for every group.

Syntax

| topk(<k>, <ranking_field>)
| topk(<k>, <ranking_field>) by <field1>, <field2>, ...
none
<k>

Positive integer. The maximum number of rows to keep. Must be >= 1. If fewer rows exist than k, all rows are returned.

<ranking_field>

The field used to rank rows in descending order. This is typically an aggregation output column such as _count, or an aliased aggregation like errors from count as errors.

by <field1>, <field2>, …​

Optional grouping fields. When present, topk partitions input rows by the listed fields and returns the top k rows within each group. Group order in the output follows the order in which each group is first seen in the input.

Output

topk appends a _rank column to the schema. _rank is 1 for the highest-ranked row in each result set (or per group), 2 for the next, and so on. Within a by group, _rank restarts at 1.

Rows are ordered:

  • Globally (no by clause): descending by <ranking_field>.

  • Per group (by clause): groups appear in input order; within each group, rows are descending by <ranking_field>.

Behavior

  • topk must appear after an aggregation operator such as count, sum, avg, or percentiles. Using topk before an aggregation returns an error.

  • Comparison is numeric when both values being compared are numeric (including mixed int and float values); otherwise the values are compared as strings.

  • Missing or null ranking values sort to the end, so rows with no value never appear in the top results unless k exceeds the number of non-null rows.

  • A topk with a value of <k> that is larger than the input set is not an error — topk returns all input rows.

Example: Top N across all results

Return the 5 sources producing the most logs:

* | count by source | topk(5, _count)
none

The result has at most 5 rows ranked by _count descending, with _rank values 1 through 5.

Example: Top N per group

Return the 3 most frequent error sources in each 5-minute window:

level="error"
| timeslice 5m
| count by (_timeslice, source)
| topk(3, _count) by _timeslice
none

Each _timeslice bucket has up to 3 rows, each carrying a _rank of 1, 2, or 3 for that bucket.

Example: Ranking by an aliased aggregation

topk can rank by any output column, including an aliased aggregation:

* | avg(durationMs) as p_avg by endpoint | topk(10, p_avg)
none

This returns the 10 slowest endpoints by average duration.