Expressions
The documentation explains LogScale's expression language capabilities, including basic values, operators, and functions that allow users to perform computations and comparisons with strings, numeric values, and boolean data. The content covers essential expression components like literal values, field references, comparison operators, numerical operations, and specialized functions such as if(), coalesce(), and text:contains(), while emphasizing that LogScale treats all values as strings that are interpreted based on their context.
Some LogScale functions and constructs allow for writing expressions
instead of simple values or field names, for example, to perform
computations. The most common places where expressions are used are the
test() function, the eval()
function, and the syntactic short-hand field :=
expression. However there are other functions that take expressions
as arguments, like coalesce(),
if(), getField(), and
text:contains(). For more information about syntax
rules of expressions, see also
Grammar Subset.
Basic Expressions and Values
LogScale's expression language can be used to compute and compare
strings that represent text, numeric, and boolean values. Values can be
stored in fields on the current event or used as arguments to functions
that support expressions, like text:contains() or
if().
It is important to keep in mind that in LogScale there are no
types associated with values at runtime, values are basically strings that
are interpreted in the context they are used. For example, the query
fragment a := "2" | b := 4 / lower(a)
results in b having the value
2, and a := "2" | b :=
format("%s%s", field=[a, a]) + 1 results in
b having the value
23.
Basic expressions are literal strings, like "some
test", literal booleans like false, and
literal numbers, like 1, 0.5, which
evaluate to that value.
The values of fields in the event can be referred to by the field name,
for example field. If the event does not
contain a field of that name, the expression produces the special value
null. This null value is handled
specially; for example, the expression field >
3, where the field does not exist, produces a
null value, and assigning the null
value to a new field in a statement like result
:= field > 3 will not create (or overwrite) the field.
Note
The strings "true" and "false" and
the bare words true and false are
interpreted as boolean values in expression contexts even though they
are technically just strings. An example of this is when using the
function if().
Operators
Expressions can be combined using comparison, numerical, and logical operators, then put into parentheses. Using operators with incorrect type values does not create a compile-time error, but does usually produce a null value at run time. An example of this includes substracting strings.
Hint
Single Equals Comparison
The expression a = b does not perform a
comparison. Instead, it is used for filtering on explicit fields. For
more information on this form, see
Field Filters.
The numerical comparison operators are <,
>, <= and
>=. They compare numerical values and produce either
true or false values - if the
operands are not numbers, no value is produced:
"a" > 3
|
Comparing a string to a number, result is null.
|
1 > 3
|
Comparing two numbers, result is false.
|
field > 3
|
Comparing the value in a field to a number, result is
true/false if the field
exists and has a numeric value, null otherwise.
|
The numerical operators +, -,
/, *, and % take
one or two values and compute the corresponding numerical operation if
both operands are numbers; otherwise, a null value is produced:
"a" / 2
|
Dividing a string and a number, result is null.
|
4 / 2
| Dividing two numbers, result is is a number. |
field / 2
|
Dividing the value of the field to a number, result is a number if
the field exists and has a numeric value, null
otherwise.
|
The general comparison operators == and
!= compare two values and produce
true or false values accordingly, if
both values are non-null:
"a" == 2
|
Comparing two values of different types, result is
false.
|
1 != 2
|
Comparing two numbers, result is true.
|
field == 2
|
Comparing the value of the field to a number, result is a
true/false if the field exists, null otherwise.
|
Logical negation !, computes the logical negation of a
boolean value, or whether a numerical value is equal to
0. If the value is neither a boolean nor a numeric
value, the result is null:
!false, !true
|
Negation of literal boolean value, result is
true and false,
respectively.
|
!field
|
Negation of value in field field,
result is true if the field contains a numeric value or
true/false,
otherwise it is null.
|
!0, !1
|
Negation of numeric values, result is true and
false, respectively
|
Note
There are currently no operators for logical AND and
OR.
Functions
Functions that calculate a single field or filter function can also be
used in expressions, where they evaluate to the value of that field, or
true or false for filter functions. However,
function arguments are not automatically accepting expressions, even in
the context of an expression.
For example, to calculate the cosine of a number, write
n := 1 | c := math:cos(n). Because the
cosine function expects a field name; the expression
c := math:cos(1) computes the cosine of
the value in the field named 1.
Some CQL functions, like coalesce(),
if(), getField(), and
text:contains() support expressions as arguments, but
most functions take field or array names; the type of the parameter in the
documentation will be "expression", if expressions are supported.
The function if() is particularly useful in
expressions, as it can be used to conditionally compute other expressions
inside an expression.
if() Function
The if() function supports a typical
if...then...else conditional statement.
However, unlike a case or
match statement, the
if() function can be embedded into other functions
and expressions.
The if() function supports statements like the one
below, where a comparison is being made between timestamps to determine
the time of an error:
errortime := if((@ingesttimestamp > @timestamp), then=@timestamp, else=@ingesttimestamp) / 1000
For more information and examples, see if().
For information about other usage of statements, see Conditional Evaluation.
Field Names in Expressions
In most places in a query, it is clear from the context whether a value or
the name of a field is expected. In these cases, the name of a field can
be written with or without quotation marks, meaning the same. For example,
math:cos("fieldName") means the same as
math:cos(fieldName), because the argument to the
function is defined as a string denoting a field name, not an expression.
However, some field names cannot be written unquoted, because they are not
bare words in the LogScale language; for example
host-name or host/name need quotes
when used in places where field names are expected. These two formats
work:
host.name=*, host[0]=*
"host-name"=*But the following will result in a syntax error:
host-name=*
In more complex naming and quoting where the double quote is required in
the context of the function parameter, use the backtick
(`) to quote the name. For example:
array:contains(array="`filters.not-values`[]", value="9847598475")Note
The exact details of which names need quoting are complicated. The following table contains the allowed symbols marked with UnquotedFieldName: Character Table.
In expressions quotation marks always mean a string value, while unquoted
field names always mean the value of that field. To use the value of a
field with such a name in an expression, the function
getField() can be used with the quoted name, like
coalesce([host, getField("host-name")]). This works
because getField() takes an expression and reads the
value of the field with that name. Alternatively, if not using
getField(), you can copy or rename the field before
using it in an expression.