Expressions
Some LogScale functions and constructs allow 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 and the eval()
function and the syntactic short-hand field := expression
,
but 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
.
The 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 an statement like
result := field > 3
will not create (or overwrite) the
field.
Note
The strings "true"
and "false"
,
as well as the bare words true
and
false
, while they are technically just strings, are
interpreted as boolean values in expression contexts, for example when
using the function if()
.
Operators
Expressions can be combined using comparison, numerical and logical operators, and put into parentheses. Using operators with values of the wrong type, for example subtracting strings, does not create a compile-time error, but usually produces a null value at runtime.
The numerical comparison operators are <
,
>
, <=
and
>=
compare numerical values and produce either
true
or false
. 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 +
, -
,
/
, *
, %
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
, 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 |
There are currently no operators for logical AND
and
OR
.
Functions
Functions that calculate a single field and filter functions 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 we need to 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()
supports a typical
if...then...else
conditional
statement. However, unlike a case
or match
statement, the if()
can be embedded into other
functions and expressions.
The if()
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, and not an expression.
However, some field names cannot be written unquoted, because they are
not bare words in the CrowdStrike Query Language; for example,
host-name
or host/name
need quotes
when used in places where field names are expected: but do not:
host.name=*
, host[0]=*
, and
"host-name"=*
all work, while host-name=*
results in a syntax error.
In expressions, on the other hand, 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.