Query using conditional logic

Flux provides if, then, and else conditional expressions that allow for powerful and flexible Flux queries.

Conditional expression syntax
  1. // Pattern
  2. if <condition> then <action> else <alternative-action>
  3. // Example
  4. if color == "green" then "008000" else "ffffff"

Conditional expressions are most useful in the following contexts:

  • When defining variables.
  • When using functions that operate on a single row at a time ( filter(), map(), reduce() ).

Evaluating conditional expressions

Flux evaluates statements in order and stops evaluating once a condition matches.

For example, given the following statement:

  1. if r._value > 95.0000001 and r._value <= 100.0 then "critical"
  2. else if r._value > 85.0000001 and r._value <= 95.0 then "warning"
  3. else if r._value > 70.0000001 and r._value <= 85.0 then "high"
  4. else "normal"

When r._value is 96, the output is “critical” and the remaining conditions are not evaluated.

Examples

Conditionally set the value of a variable

The following example sets the overdue variable based on the dueDate variable’s relation to now().

  1. dueDate = 2019-05-01
  2. overdue = if dueDate < now() then true else false

Create conditional filters

The following example uses an example metric variable to change how the query filters data. metric has three possible values:

  • Memory
  • CPU
  • Disk

    1. metric = "Memory"
    2. from(bucket: "telegraf/autogen")
    3. |> range(start: -1h)
    4. |> filter(fn: (r) =>
    5. if v.metric == "Memory"
    6. then r._measurement == "mem" and r._field == "used_percent"
    7. else if v.metric == "CPU"
    8. then r._measurement == "cpu" and r._field == "usage_user"
    9. else if v.metric == "Disk"
    10. then r._measurement == "disk" and r._field == "used_percent"
    11. else r._measurement != ""
    12. )

Conditionally transform column values with map()

The following example uses the map() function to conditionally transform column values. It sets the level column to a specific string based on _value column.

No Comments Comments

  1. from(bucket: "telegraf/autogen")
  2. |> range(start: -5m)
  3. |> filter(fn: (r) => r._measurement == "mem" and r._field == "used_percent" )
  4. |> map(fn: (r) => ({
  5. r with
  6. level:
  7. if r._value >= 95.0000001 and r._value <= 100.0 then "critical"
  8. else if r._value >= 85.0000001 and r._value <= 95.0 then "warning"
  9. else if r._value >= 70.0000001 and r._value <= 85.0 then "high"
  10. else "normal"
  11. })
  12. )
  1. from(bucket: "telegraf/autogen")
  2. |> range(start: -5m)
  3. |> filter(fn: (r) => r._measurement == "mem" and r._field == "used_percent" )
  4. |> map(fn: (r) => ({
  5. // Retain all existing columns in the mapped row
  6. r with
  7. // Set the level column value based on the _value column
  8. level:
  9. if r._value >= 95.0000001 and r._value <= 100.0 then "critical"
  10. else if r._value >= 85.0000001 and r._value <= 95.0 then "warning"
  11. else if r._value >= 70.0000001 and r._value <= 85.0 then "high"
  12. else "normal"
  13. })
  14. )

Conditionally increment a count with reduce()

The following example uses the aggregateWindow() and reduce() functions to count the number of records in every five minute window that exceed a defined threshold.

No Comments Comments

  1. threshold = 65.0
  2. from(bucket: "telegraf/autogen")
  3. |> range(start: -1h)
  4. |> filter(fn: (r) => r._measurement == "mem" and r._field == "used_percent" )
  5. |> aggregateWindow(
  6. every: 5m,
  7. fn: (column, tables=<-) => tables |> reduce(
  8. identity: {above_threshold_count: 0.0},
  9. fn: (r, accumulator) => ({
  10. above_threshold_count:
  11. if r._value >= threshold then accumulator.above_threshold_count + 1.0
  12. else accumulator.above_threshold_count + 0.0
  13. })
  14. )
  15. )
  1. threshold = 65.0
  2. from(bucket: "telegraf/autogen")
  3. |> range(start: -1h)
  4. |> filter(fn: (r) => r._measurement == "mem" and r._field == "used_percent" )
  5. // Aggregate data into 5 minute windows using a custom reduce() function
  6. |> aggregateWindow(
  7. every: 5m,
  8. // Use a custom function in the fn parameter.
  9. // The aggregateWindow fn parameter requires 'column' and 'tables' parameters.
  10. fn: (column, tables=<-) => tables |> reduce(
  11. identity: {above_threshold_count: 0.0},
  12. fn: (r, accumulator) => ({
  13. // Conditionally increment above_threshold_count if
  14. // r.value exceeds the threshold
  15. above_threshold_count:
  16. if r._value >= threshold then accumulator.above_threshold_count + 1.0
  17. else accumulator.above_threshold_count + 0.0
  18. })
  19. )
  20. )