Skip to main content

Fleak Eval Expression Language (FEEL) Reference

Introduction

Fleak Eval Expression Language is a flexible expression language designed for data transformation and evaluation. It provides various operations for manipulating dictionaries, arrays, strings, and timestamps, with a focus on data processing efficiency.

Basic Syntax and Types

Data Types

Numbers

  • Integers: 0 or any sequence of digits not starting with 0 (e.g., 42, 123)
  • Floating-point numbers: Numbers with decimal points (e.g., -1.5, .5, 10.0)
  • Negative numbers are supported for both integer and floating-point values

Strings

  • Can be enclosed in either single quotes ('hello') or double quotes ("world")
  • Support escape sequences:
    • \' - Single quote in single-quoted strings
    • \" - Double quote in double-quoted strings
    • \\ - Backslash
  • Examples:
    "This is a 'string'"
    'This is a "string"'
    "String with \"quotes\""
    'String with \'quotes\''
    "Path with \\backslashes\\"

Booleans

  • Two possible values: true or false
  • Used in conditional expressions and comparisons

Null

  • Represented by the keyword: null
  • Used to represent missing or undefined values

Path Selection

The language provides flexible path selection syntax for accessing nested data structures:

  • $: References the root event/document
  • .fieldName: Accesses a field in a dictionary using dot notation (field name must be a valid identifier)
  • [index]: Accesses an array element by numeric index (zero-based)
  • ["fieldName"]: Alternative syntax for accessing dictionary fields, required when:
    • Field names contain special characters or spaces
    • Field names are reserved words
    • Field names need to be computed dynamically

Examples:

// Basic field access
$.user.name // Access 'name' field in user object
$["user"]["name"] // Same access using bracket notation

// Array access
$.items[0] // Access first element of items array
$.users[1].address // Combine array and field access

// Special character handling
$["special.field"] // Access field containing a dot
$["user name"] // Access field containing a space

// Nested combinations
$.users[0]["address.line1"] // Mix of array access and special fields

Operators and Precedence

Operators

Listed in order of precedence (highest to lowest):

  1. Unary Operations (highest)

    • Unary minus (-)
    • Logical NOT (not)
  2. Multiplicative Operations

    • Multiplication (*)
    • Division (/)
    • Modulo (%)
  3. Additive Operations

    • Addition (+)
    • Subtraction (-)
  4. Relational Operations

    • Less than (<)
    • Greater than (>)
    • Less than or equal (<=)
    • Greater than or equal (>=)
  5. Equality Operations

    • Equal (==)
    • Not equal (!=)
  6. Logical AND (and)

  7. Logical OR (or) (lowest)

Examples:

// Unary has highest precedence
-3 * 4 // Evaluates as (-3) * 4 = -12
not true and false // Evaluates as (not true) and false = false

// Multiplication before addition
2 + 3 * 4 // Evaluates as 2 + (3 * 4) = 14

// Comparison before logical operations
x > 5 and y < 10 // Evaluates as (x > 5) and (y < 10)

// AND before OR
a or b and c // Evaluates as a or (b and c)

Use parentheses to override default precedence:

(2 + 3) * 4  // Evaluates as 5 * 4 = 20
a and (b or c) // Evaluates AND after OR

Control Flow

Case Expressions

Provides conditional logic with pattern matching syntax. The first matching condition's expression is evaluated and returned.

case(
condition_1 => expression_1,
condition_2 => expression_2,
...
_ => default_expression
)

Examples:

// Simple status mapping
case(
$.status == "active" => "Current",
$.status == "pending" => "In Progress",
_ => "Unknown"
)

// Data transformation
case(
size_of($.items) == 0 => dict(status="empty", count=0),
size_of($.items) > 10 => dict(
status="full",
count=size_of($.items),
firstItem=$.items[0]
),
_ => dict(status="partial", items=$.items)
)

// Type-based handling
case(
$.value == null => "missing",
str_contains(to_str($.value), "error") => "error",
$.value > 100 => "high",
_ => "normal"
)

Built-in Functions

Utility Functions

size_of()

Returns the size of the argument based on its type.

Syntax: size_of(expression)

Input Types:

  • Array: Returns number of elements
  • Dictionary/Object: Returns number of key-value pairs
  • String: Returns string length

Returns: Integer

Examples:

// Array size
size_of($.items) // Returns number of elements
size_of(array(1, 2, 3)) // Returns 3

// Dictionary size
size_of(dict(a=1, b=2)) // Returns 2
size_of($.user.properties) // Returns number of properties

// String size
size_of("hello") // Returns 5
size_of($.message) // Returns string length

Dictionary Operations

dict()

Creates a dictionary with specified key-value pairs.

Syntax: dict(key1=expression1, key2=expression2, ...)

Keys must be valid identifiers:

  • Start with letter or underscore
  • Contain only letters, numbers, and underscores
  • Case-sensitive

Returns: Dictionary

Examples:

dict(
city=$.address.city,
state=$.address.state,
details=dict(
zip=$.address.zip,
country=$.address.country
)
)

dict_merge()

Merges multiple dictionaries into one. Later dictionaries override earlier ones for duplicate keys.

Syntax: dict_merge(dict1, dict2, ...)

Input: Two or more dictionaries Returns: Dictionary

Example:

dict_merge(
$,
dict(newField="value"),
grok($.__raw__, "%{PATTERN}")
)

Array Operations

array()

Creates an array from the provided arguments. Arguments can be of any type and can be mixed.

Syntax: array([expression1, expression2, ...])

Returns: Array

Example:

array($.field1, $.field2, "constant", 42)

arr_foreach()

Applies an expression to each element of an array.

Syntax: arr_foreach(arrayExpression, elementVariable, transformExpression)

Parameters:

  • arrayExpression: Expression that evaluates to an array. If it points to an object, treat that object as a single element array.
  • elementVariable: Variable name to represent each array element
  • transformExpression: Expression to apply to each element

Returns: Array of transformed elements

Example:

arr_foreach(
$.users,
user,
dict(
name=user.name,
age=user.age,
type=$.userType
)
)

arr_flatten()

Flattens an array of arrays by one level.

Syntax: arr_flatten(arrayOfArrays)

Input: An array containing other arrays Returns: A flattened array with one level of nesting removed

Example:

// Given:
// $.nested = [[1, 2], [3, 4], [5, [6, 7]]]

arr_flatten($.nested)
// Results: [1, 2, 3, 4, 5, [6, 7]]

Note: This performs a shallow flatten operation, not a deep recursive flatten. Deeper nested arrays remain intact.

String Operations

str_split()

Splits a string into an array of substrings based on a delimiter.

Syntax: str_split(string, delimiter)

Input:

  • String to split
  • Delimiter string

Returns: Array of strings

Example:

str_split("a,b,c", ",")  // Returns ["a", "b", "c"]

to_str()

Converts a value to string.

Syntax: to_str(expression)

Input: Any value Returns: String, or null if input is null

Example:

to_str($.numericField)  // Converts number to string
to_str(null) // Returns null

upper()

Converts a string to uppercase.

Syntax: upper(expression)

Input: String Returns: String Throws: Error if input is not a string

Example:

upper($.name)  // "john" -> "JOHN"

lower()

Converts a string to lowercase.

Syntax: lower(expression)

Input: String Returns: String Throws: Error if input is not a string

Example:

lower($.name)  // "JOHN" -> "john"

str_contains()

Tests if a string contains a substring.

Syntax: str_contains(string, substring)

Input: Two strings (string to search, substring to find) Returns: Boolean Throws: Error if either input is not a string

Examples:

// Basic usage
str_contains($.message, "error") // Returns true if found

// In case expressions
case(
str_contains($.level, "ERROR") => "critical",
str_contains($.level, "WARN") => "warning",
_ => "info"
)

// With other functions
str_contains(lower($.text), $.searchTerm)

grok()

Applies a Grok pattern to extract structured data from a string.

Syntax: grok(string, pattern)

Input:

  • String to parse
  • Grok pattern string

Returns: Dictionary of extracted fields Throws: Error if pattern is invalid

Example:

grok($.rawLog, "%{TIMESTAMP:timestamp} %{WORD:level}: %{GREEDYDATA:message}")

Time and Date Operations

ts_str_to_epoch()

Converts a timestamp string to epoch milliseconds.

Syntax: ts_str_to_epoch(timestampString, formatPattern)

Input:

Returns: Integer (epoch milliseconds) Throws: Error if timestamp doesn't match pattern

Example:

ts_str_to_epoch($.timestamp, "yyyy-MM-dd HH:mm:ss")

epoch_to_ts_str()

Converts epoch milliseconds to formatted timestamp string.

Syntax: epoch_to_ts_str(epochMillis, formatPattern)

Input:

Returns: String Throws: Error if timestamp is invalid

Example:

epoch_to_ts_str($.epochTime, "yyyy-MM-dd HH:mm:ss")

duration_str_to_mills()

Converts a duration string to milliseconds.

Syntax: duration_str_to_mills(durationString)

Input: Duration string in "HH:mm:ss" format Returns: Integer (milliseconds) Throws: Error if duration format is invalid

Example:

duration_str_to_mills("01:30:00")  // Returns 5400000 (1.5 hours in milliseconds)

Number Operations

parse_int()

Parses a string into a long integer (equivalent to Java's Long.parseLong()).

Syntax: parse_int(string)

Input: String containing an integer Returns: Long integer Throws: Error if string is not a valid integer

Example:

parse_int("42")  // Returns 42

parse_float()

Parses a string into a floating-point number (equivalent to Java's Double.parseDouble()).

Syntax: parse_float(string)

Input: String that represents a number Returns: Double Throws: Error if string is not a valid number

Example:

parse_float("3.14")  // Returns 3.14
parse_float("-1.5") // Returns -1.5
parse_float("42") // Returns 42.0

Error Handling

Null Safety

  • Operations on null values generally propagate null
  • Function-specific null handling is documented in each function
  • Use case expressions for explicit null handling:
    case(
    $.field == null => "missing",
    _ => to_str($.field)
    )

Type Safety

  • Type mismatches in operations throw errors
  • Explicit type conversion functions available:
    • to_str() for string conversion
    • parse_int() for integer conversion
    • parse_float() for floating-point conversion

Common Error Conditions

  1. Type Mismatches

    // These will throw errors:
    "string" * 5 // Can't multiply string
    upper(42) // upper() requires string
    size_of(true) // size_of() not valid for boolean
  2. Field Access

    // These return null:
    $.nonexistent.field // Missing field
    $.array[999] // Index out of bounds

    // These throw errors:
    $.string[0] // Array access on non-array
    $[true] // Invalid field access
  3. Function Arguments

    // These throw errors:
    size_of() // Missing argument
    str_contains("a") // Missing second argument
    upper(42) // Wrong argument type

Best Practices

  1. Check for null values:

    case(
    $.amount != null => $.amount * 100,
    _ => 0
    )
  2. Provide default values:

    dict(
    name=case($.name != null => $.name, _ => "unknown"),
    value=case($.value != null => $.value, _ => 0)
    )
  3. Validate data structure:

    case(
    not array($.data) => dict(error="data must be array"),
    _ => arr_foreach($.data, item, process(item))
    )