Logs Search Syntax

Every filter you build by checking a sidebar value or adding a Builder chip compiles to a FuseQL query, which you can see and edit by switching the search bar to Code. This page documents that FuseQL syntax as you type it in the Code input. This page is the full operator reference; see Explorer layout for how the search bar fits into the rest of the screen.

This syntax is the pre-pipe (filtering) half of FuseQL, Kloudfuse’s query language: it goes before the first | in a query. See Logs Analytics for the post-pipe aggregation syntax, and Comparison operators, Text search operators, and Logical operators for the full operator reference with every function’s syntax, parameters, and examples.

Operators

Labels such as level are written by their bare name; facets such as @msg and @path take an @ prefix. @msg, @path, @status, and @bytes below stand in for any facet name; substitute your own. Always quote string values: an unquoted value such as level=error is not an error, but it matches no logs.

Syntax Meaning

level="error"

Equals: exact match on a label or facet

level!="debug"

Not equals

@msg=~"timeout.*"

Regex match

@msg!~"health.*"

Regex exclude

@path*~"/api"

Starts with

@msg**"error"

Contains

@path~*".json"

Ends with

@status>499

Greater than

@status>=500

Greater than or equal

@bytes<1024

Less than

@bytes<=2048

Less than or equal

level="A" or level="B"

Union — matches either value

@status:number

Key exists

!@status:number

Key absent

'error'

Term search — matches the whole word error anywhere in the message

"error text"

Substring search (grep) — matches the exact phrase

!'error'

Exclude term

!"error text"

Exclude substring (not-grep)

The comparison operators (>, >=, <, <=) compare plain numbers. To compare a duration facet such as @duration, whose values carry a unit (95.046µs, 1.2s), convert it to milliseconds with toduration() after the filter, then compare the result:

source="grafana" and @duration:string | toduration(@duration) as duration_ms | where duration_ms > 500
fuseql

A direct comparison such as @duration>500ms is accepted, but it compares the stored text rather than the time value and returns wrong results.

Term search vs. field filters

A single-quoted word ('error') is a term search — it looks up a whole word in an index built from the message at ingest time, the same way a search engine matches words in a document. A double-quoted phrase ("connection refused") is a substring search (grep) — it scans the reconstructed message text for that exact, case-sensitive sequence of characters instead. A field="value" expression is a field filter — it matches an indexed label or facet exactly, regardless of how the message text is worded.

Field filters are cheaper to evaluate, because the Logs Store already has every label and facet indexed — see How a search reaches the data. Prefer them over a term search whenever the value you’re looking for is already available as a field (level="error" instead of the term 'error'; kube_namespace="payments" instead of the term 'payments'), and reserve term/substring/regex search for text that only exists in the free-form part of the message.

Facets vs. labels in a query

Both facets and labels are field="value" filters — the difference is in the field name, not the syntax. A facet (something Kloudfuse extracted from the message) is referenced with an @ prefix — @status=500; a label (attached at collection time — kube_namespace, level, source, and so on) is referenced by its bare name — kube_namespace="payments". A facet written without the @, such as duration>500ms, is treated as a label: it is not an error, but it matches either no logs or every log. See Facets, labels, and tags for what determines which one a given field is.

Combining filters

Join filters with and to require all of them, and with or to accept any of them. Writing filters side by side without and is a syntax error.

level="error" and kube_namespace="payments" and "connection refused"
fuseql

This matches logs where the level is error, and the namespace is payments, and the message contains the phrase "connection refused". To accept several values of one field, write each one as a full condition and group them with parentheses:

(level="error" or level="warn") and kube_namespace="payments"
fuseql

A single quoted value such as level="error OR warn" is matched literally, so it matches no logs.

Builder vs. Code

The search bar has two modes, switched by the Builder and Code buttons at its right edge:

Builder

The default. Each filter is a separate chip, and the search bar stays in sync with the sidebar’s checked values. Builder joins its chips with and when it builds the query. Each chip holds one filter: typing source=nginx level=error into one chip searches for a source named nginx level=error.

Code

A raw FuseQL query editor with a Run button. It shows the query that Builder generates, underlines syntax errors as you type, and is the place for queries more complex than the Builder is meant for — see Logs Analytics for the aggregation syntax (count by, roll up every, formulas) used in the analytics views.

How term search tokenizes a message

A term search doesn’t require an exact substring match the way a quoted phrase does — it looks up whole tokens in an index built at ingest time, rather than scanning message text. For the precise tokenization rule (what counts as a token, which characters are boundaries, case sensitivity) and worked examples, see Term search in the FuseQL reference — it covers this in more depth than duplicated here. When you need an exact, uninterrupted phrase instead of a token match, use a quoted substring search ("connection refused") or a regex (@msg=~"connection refused").