Expressions and transformations#

Expressions and transformations are the tools with which message data (payload, properties, or topics), received from mqtt can be processed. The difference between the two is:

  • Expressions are used to extract or calculate a value from a payload
  • Transformations are used to transform a payload into a different format, e.g. from text to json.

Parameters supporting expressions or transformation can be identified by the tag expressions or transformations.

In fields that supports text input, there is a special syntax for embedding expressions inside a text field. The expression must then be wrapped inside a $(expression). So for example to include the payload inside a text, you can use This is the payload: $(Payload()).. Parameters supporting embedded expressions can be identified by the tag: embedded expressions.

All parameters that support embedded expressions support variables as well.

Expressions#

The basics#

Expressions are mainly used at the Value parameter inside a Processors.Otel.Metrics.Metric.Value are build on top of the NCalc library where you can find additional information on capabilities not covered in this document.

A simple expression returning the constant value 42 would be:

1
Value: "42"

Functions#

Most of the time you want to process a payload as delivered by a mqtt subscription. Lets take the following example json payload:

1
2
3
4
5
6
7
{
    "Processor": 
    {
        "Temperature": 42.5
    },
    "TempUnit": "C"
}

To access the temperature we use the JSONPATH syntax: $.Processor.Temperature that gets the Temperature parameter inside the Processor parameter. To do this we have to use a function called JSONPATH:

1
Value: "JsonPath('$.Processor.Temperature')"

That will return the value 42.5. The data type returned will be the data type defined in Processors.Otel.Metrics.Metric.SignalDataType. If you want to change the data type to e.g. int you can add another parameter to the function stating the data type:

1
Value: "ToInt(JsonPath('$.Processor.Temperature'))"

This will return the value 42.

Important

The name of functions is case-insensitive.

Available Functions#

Mqtt message parsing

FunctionExampleDescription
JsonPathJsonPath('$.Root')Extracts data using JSONPATH syntax from a json payload.
XPathXPath('/root/child[1]')Extracts data using XPath syntax from a xml payload
TopicPathTopicPath('[1]')Extracts data using TopicPath syntax from the message topic.
UserPropertyUserProperty('Name')Accesses an mqtt user property via its name. If the name exists multiple times, the first match is used. If the name does not exist, the function returns an empty string.
RegExRegEx('[0-9]+')Extracts data from payload using a regular expression. If the regular expression returns more than one match, then the first match is used.
VarVar('MyVariable')Returns the variable with the given name. No $ is needed before the variable name.
PayloadPayload()Returns the raw payload

String functions

FunctionExampleDescription
ToLowerToLower('My Signal') => my signalReturns lower case value
ToUpperToUpper('My Signal') => MY SIGNALReturns upper case value
ToPascalCaseToPascalCase('My Signal') => MySignalReturns pascal case value
ToCamelCaseToCamelCase('My Signal') => mySignalReturns camel case value
ToSnakeCaseToSnakeCase('My Signal') => my_signalReturns snake case value
ToKebabCaseToKebabCase('My Signal') => my-signalReturns kebab or hyphen case value
ToTrainCaseToTrainCase('My Signal') => My-SignalReturns train case value
TrimTrim(' Test ') => “Test”Removes leading and trailing whitespace
TrimStartTrimStart(' Test ') => “Test "Removes leading whitespace
TrimEndTrimEnd(' Test ') => " Test”Remove trailing whitespace
StartsWithStartsWith('MyValue', 'My') => trueTests, whether a string starts with the provided pattern.
EndsWithStartsWith('MyValue', 'Value') => trueTests, whether a string ends with the provided pattern.
ContainsContains('MyValue', 'Val') => trueTests, whether a string contains the provided pattern.
ReplaceReplace('Test', 'e', 'ee') => TeestReplaces strings inside a string.
MatchesWildcardMatchesWildcard('My Signal', '*Signal') => trueTests, whether a string matches a wildcard pattern.
MatchesRegExMatchesRegEx('My Signal', '.*') => trueTests, whether a string matches a regular expression.
MapMap('value', 'lookupTable') => translated valueMaps the provided value to another value, as defined in the lookup table. For details, see Mappings.

Type conversion

FunctionExampleDescription
ToIntToInt(42.1) => 42Converts a value to integer
ToLongToLong(42.1) => 42LConverts a value to a long integer
ToFloatToInt(42) => 42.0Converts a value to float
ToDoubleToInt(42) => 42.00Converts a value to double
ToStringToInt(42) => “42”Converts a value to string

Constants#

Some constants are always available when evaluating an expression. They are enclosed in [], e.g. [Pi].

Important

The name of constants is case-insensitive.

The following constants are allways available:

ConstantExampleDescription
Pi[Pi] => 3.14…The mathematical constant pi
e[e] => 2.718…the euler number

In some contexts additional constants may be available, e.g. in a NameFormatter or in a ValueConverter.

Calculations#

We’ve already used an expression to parse the payload with JsonPath('$.Processor.Temperature'). However, you can also perform mathematical calculations. For example, to convert the temperature from Celsius to Fahrenheit, you can use this expression:

1
Value: "(JSONPATH('$.Processor.Temperature') * 1.8) + 32.0"

Standard mathematical operations like +, -, *, /, and functions such as Sqrt, Sin, Cos, Tan, and constants like [PI] and [E] are also supported. Further details can be found at the NCalc library.

Transformations#

The basics#

Transformations work similar than expressions, but instead of extracting the needed value they transform a payload in another form for further processing.

Let’s say you receive a log message payload in the following format from MQTT:

2026-02-26T10:28:34Z [Info] [ServerA] Temperature value read successfully.

Rather than sending the raw message to Otel, we can transform it into a structured log format using an extended DISSECT expression:

%{otel_timestamp:DateTime} [%{otel_loglevel}] [{server_name}] %{otel_message}

This can be read as:

  • Parse date and time and name it otel_timestamp
  • Read a space and a [ and discard the information
  • Read everything up until ] and name it otel_loglevel
  • Read ] [ and discard the information
  • Read everything up until ] and name it server_name
  • Read ] [ and discard the information
  • Read the remaining part of the message and name it otel_message

With that the payload will be transformed in a log message that looks like this:

1
2
3
4
5
6
{
  "otel_timestamp": "2026-02-26T10:28:34Z",
  "otel_loglevel": "Info",
  "server_name": "ServerA",
  "otel_message": "Temperature value read successfully."
}

This message can than be passed to the log processor. Be careful to set PayloadType: Json for getting the expected results. The usage is similar to expressions:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11

Processors:
  - Name: "Server logs"
    Description: "Collect all log messages from the server."
    Mqtt:
      Subscriptions:
        - Topic: "sensor/+/log"
    Otel:
       Logs:
         - PayloadType: Json
           Transform: "DISSECT('%{otel_timestamp} [%{otel_loglevel}] [%{server_name}] %{otel_message}')"

Available Functions#

FunctionExampleDescription
DISSECTDISSECT('%{otel_message}')Converts a payload to json using Extended dissect syntax
GROKGROK('%{GREEDYDATA:otel_message}')Converts a payload to json using GROK syntax