Conditional Statements

There is no if-then-else syntax in Humio, since the streaming style is not well-suited for procedural-style conditions. However, there are a few ways to do conditional evaluation:

Case Statements

Using case statements, you can describe alternative flows in your queries. It is similar to case or cond you might know from many other functional programming languages. It essentially allows you to write if-then-else constructs that work on events streams.

The syntax looks like this:

humio
case {
  expression | expression | ...;
  expression | expression | ...;
  expression | expression | ...;
  * | expression | ...
}

You write a sequence of pipeline clauses separated by a semi-colon (i.e., ;). Humio will apply each clause from top to bottom until one returns a value (matches the input).

You can add wildcard clause case { ... ; * } which matches all events as the “default case”, essentially the else part of an if-statement. If you don’t add a wildcard clause, any events that don’t match any of the explicit clauses will be dropped.

Example

Let’s say we have logs from multiple sources that all have a field named time, and we want to get percentiles of the time fields, but one for each kind of source.

First we try to match some text that distinguishes the different types of line. Then we can create a new field type and assign a value that we can use to group by

humio
time=*
| case { "client-side"     | type := "client";
         "frontend-server" | ip != 192.168.1.1 | type := "frontend";
         Database          | type := "db" }
| groupBy(type, function=percentile(time)))

Catch-All Clause

Note that the * clause captures any output that has not matched a previous clause, and can be used either to ignore that information (resulting in no action or output) or to apply a default operation or value. For example, in the sample below the client field is being used to determine whether the IP address is localhost and setting the local field accordingly:

humio
case { client = "::1" | local := "true";
       client = "127.0.0.1" | local := "true";
       * | local := "false"}

The * clause in this instance sets local to false for any non-matching value.

However, the following is also valid:

humio
case { client = "::1" | local := "true";
       client = "127.0.0.1" | local := "true";
       * }

The above ensures that the non-matching clauses are not processed, but does not create the field unless we’ve identified a local value.

Match Statements

Using match statements, you can describe alternative flows in your queries where the conditions all check the same field. It is similar to match` ` or ``switch which you might recognize from many other programming languages. It essentially allows you to write if-then-else constructs that work on events streams. The matches on the field support the filters listed in Field Filters.

The syntax looks like this:

humio
 field match {
   value => expression | expression... ;
   /regex/ => expression | ...;
   * => expression | ...
}

You write a sequence of filter and pipeline clauses to run when the filter matches, separated by a semicolon (;). Humio will apply each clause from top to bottom until one returns a value (matches the input).

You can add a wildcard clause match { ... ; * } which matches all events as the “default case”, essentially the else part of an if-statement. If you don’t add a wildcard clause any events that don’t match any of the explicit clauses will be dropped. You cannot use the empty clause — you must explicitly write * to match all.

Example

Let’s say we have logs from multiple sources that all have a field that holds the time spent on some operation, but in different fields and units. We want to get percentiles of the time fields all in the same unit and in one field.

humio
logtype match {
    "accesslog" => time:=response_time ;     // Access log is in seconds.
    /server_\d+/ => time:=server_time*1000 ; // These servers log in millis
  }
| groupBy(logtype, function=percentile(time)))

Setting a Field’s Default Value

You can use the function default() to set the value of a missing or empty field.