Miscellaneous operators :: Kloudfuse Docs
Miscellaneous operators
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>
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
| _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 |
Expected output (illustrative)
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]
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
| _filter |
|---|
| level="error" and org_id="pisco-shared") or (level="info" and org_id="pisco-shared" |
Expected output (the compose operator produces a filter string)
compose is most powerful inside a subquery block:```none [subquery: source="query-service" |
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>
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
source="nginx"
| timeslice 60s
| count_unique(@error) by (_timeslice)
| predict (_count_unique) by 60s, model=linear, forecast=3600s
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>
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
source="nginx"
| timeslice 60s
| count_unique(@error) by (_timeslice)
| predict (_count_unique) by 60s, model=seasonal, seasonality=hourly, forecast=3600s
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]]
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>
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>, ...
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
byclause): descending by<ranking_field>.Per group (
byclause): groups appear in input order; within each group, rows are descending by<ranking_field>.
Behavior
topkmust appear after an aggregation operator such ascount,sum,avg, orpercentiles. Usingtopkbefore an aggregation returns an error.Comparison is numeric when both values being compared are numeric (including mixed
intandfloatvalues); otherwise the values are compared as strings.Missing or
nullranking values sort to the end, so rows with no value never appear in the top results unlesskexceeds the number of non-null rows.A
topkwith a value of<k>that is larger than the input set is not an error —topkreturns all input rows.
Example: Top N across all results
Return the 5 sources producing the most logs:
* | count by source | topk(5, _count)
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
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)
``` \n
This returns the 10 slowest endpoints by average duration.