Expression reference

Latest Dynatrace

Dynatrace Workflows Workflows use the Jinja templating engine to allow for dynamic configuration in Workflows. Those expressions provide, for example, access to execution parameters, schedule information, event context.

Expressions are supported in any input of any action (unless specified otherwise by the action developer) and the custom task conditions and options. A notable exception is the Run Javascript action, which does not support expression in its input to avoid the possibility of code injection. Instead, SDKs are provided to access the same information directly in JavaScript. For more information, see Run JavaScript action for Workflows.

Expressions

Expressions enable you to reference results from predecessors in a task configuration and define custom conditions.

There are two kinds of delimiters.

  • {{ ... }} for expressions, it's used to access data from other tasks, executions, and functions.
  • {% ... %} for statements and control structures like loops and if conditions.

The list below is a reference list of the expressions available.

Beyond that, you can use any templating functionality Jinja provides.

Whether you use the REST API or expressions to access workflows, executions, scheduling rules, or calendars, the same arguments are available to control paging, filtering, ordering, search, and expansion.

/executions?name=foo&limit=50&offset=0 behaves the same as {{ executions(name='foo', limit=50, offset=0) in the same user context. Mind that while the REST API request returns JSON, an expression will return a native object, which is its string representation.

Access to resources happens in the context of the workflow actor (link to workflow settings).

calendars()

Access business calendars and their attributes. The behavior and result are similar to an API request for the /business_calendars endpoint.

  • Arguments:

    • identifier: Calendar ID
  • Keyword arguments: identical to the REST API. For more information, see the note above.

  • Returns: a list of calendar objects or a single calendar object if id was specified

  • Examples:

    # access to calendar '854a3452-a6d3-45bd-83e1-e8afa56eabcd'
    {{ calendars('854a3452-a6d3-45bd-83e1-e8afa56eabcd') }}
    {
    "id": "854a3452-a6d3-45bd-83e1-e8afa56eabcd",
    "created_at": "2022-12-07T12:42:45.732902Z",
    "updated_at": "2022-12-20T09:36:40.303952Z",
    "title": "Sample Calendar",
    "weekstart": 1,
    "weekdays": [
    1,
    2,
    3,
    4,
    5
    ],
    "holidays": [
    {
    "date": "2020-01-01",
    "title": "New Year"
    },
    {
    "date": "2020-01-07",
    "title": "International Programmers Day"
    }
    ],
    "valid_from": "2020-01-01",
    "valid_to": "2029-12-31",
    }

connection()

Get a single connection by schema ID and connection name.

  • Arguments:
    • schema: the settings schema ID
    • name: the connection name
  • Returns: string
  • Examples:
    # get the settings object ID by schema ID and name
    {{ connection('app:dynatrace.slack:connection', 'My Slack Connection') }}
    # get the settings object ID by schema ID and name from a previous task result
    {{ connection('app:dynatrace.slack:connection', result('get_my_config')['slack']['connection']) }}

environment()

Information about the environment, for example, id or url.

  • Arguments: None
  • Keyword arguments: None
  • Returns: environment id and environment url.
  • Examples:
    {
    "id": "xyz12345",
    "url": "https://xyz12345.dynatrace.com"
    }
    # get the full environment object
    {{ environment() }}
    # access current environment id
    {{ environment().id }} # -> "xyz12345"
    # access current environment url
    {{ environment().url }} # -> "https://xyz12345.dynatrace.com"

event()

  • Arguments:
    • event attribute (optional): Access only a specific attribute of the event object
  • Keyword arguments: None
  • Returns: event object which was passed via execution params or None if no event was given.
  • Examples:
    # Assuming the following sample event as a trigger for a Workflow Execution
    {
    "type": "security-problem-event",
    "version": "0.0.2",
    "event.id": "20d01063-14d7-4b99-aef1-77e92962fb7f"
    "event.id": "20d01063-14d7-4b99-aef1-77e92962fb7f",
    "event.kind": "SECURITY_PROBLEM_EVENT",
    "event.name": "Vulnerability resolved",
    "event.type": "THIRD_PARTY",
    "event.status": "Resolved",
    "event.category": "Vulnerability",
    "security-problem.display-id": "S-3750",
    "security-problem.technology": "go",
    "security-problem.vulnerability-type": "third-party"
    }
    # get the full event object
    {{ event() }}
    # access only the type attribute
    {{ event('type') }} # -> "security-problem-event"
    # access the full event object and then select the type attribute
    {{ event().type }} # -> "security-problem-event"
    # trying to access the 'technology' attribute of the 'security-problem' object
    # this will FAIL, as there is actually no 'security-problem' object in the example above
    {{ event().security-problem.technology }} # -> ERROR
    # NOTE: events often do not contain structured objects but flattened objects
    # the 'security-problem.technology' for example is a single attribute, that happens to have a "." in its name
    # in order to access attributes with "." in its name, use square brackets instead []
    {{ event()['security-problem.technology'] }} # -> "go"
    # as an alternative, use the get() function
    {{ event().get('security-problem.technology') }}
    # the get function also allows for default values, if the attribute is not defined
    {{ event().get('does.not.exist', 'my default value') }}

execution()

Access the current execution context.

  • Arguments: None

  • Keyword arguments: None

  • Returns: execution object

  • Examples:

    # access the current execution object
    {{ execution() }}
    # access ID of current execution
    Execution ID {{ execution().id }}
    # access input of current execution
    Execution input {{ execution().input | default('no input defined') }}

    Sample result

    {
    "id": "b126f1cc-fce1-4d28-adcf-0805b98961b9",
    "state": "RUNNING",
    "started_at": "2022-12-21T18:33:11.084818Z",
    "ended_at": null,
    "runtime": 12,
    "user": "716535cb-b992-47e4-90be-7d4b9785a501",
    "title": "Get Security Problem events count",
    "link": "https://xyz12345.apps.dynatrace.com/ui/apps/dynatrace.automations/executions/b126f1cc-fce1-4d28-adcf-0805b98961b9",
    "workflow": {
    "id": "ef1f1ca4-1d6b-4c7d-b964-5f09096d77cd",
    "title": "Get Security Problem events count",
    "actor": "716535cb-b992-47e4-90be-7d4b9785a501",
    "link": "https://xyz12345.apps.dynatrace.com/ui/apps/dynatrace.automations/workflows/ef1f1ca4-1d6b-4c7d-b964-5f09096d77cd"
    }
    }

executions()

Access executions and their attributes. The behavior and result are similar to an API request for the /executions endpoint.

  • Arguments:
    • identifier: workflow execution ID
  • Keyword arguments: identical to the REST API. For more information, see the note above.
  • Returns: list of execution objects or a single execution object if id was specified
  • Examples:
    #execution with ID 00c27c88-d066-4424-bc44-f49a75536e37 {{ executions('00c27c88-d066-4424-bc44-f49a75536e37') }}
    #executions of the workflow with ID '81a7fbb5-7f69-4005-81ec-26a39272bf09' (default limit applies for resultsize)
    {{ executions(workflow='81a7fbb5-7f69-4005-81ec-26a39272bf09') }}
    #returns up to 5 executions ordered by created_at in descending order
    {{ executions(limit=5, order='-created_at') }}
    # returns the most recent execution of workflow '81a7fbb5-7f69-4005-81ec-26a39272bf09'
    {{ executions(workflow='81a7fbb5-7f69-4005-81ec-26a39272bf09', limit=1, order='-created_at') }}

now()

The current timestamp in UTC or time zone is provided as the input parameter. The expression returns a native Python datetime object to allow formatting into any desired output. Use strftime and format codes as described in datetime Python documentation.

  • Arguments:

    • timezone (optional): Timezones as available in pytz. If no timezone is provided, UTC is used.
  • Returns: datetime object

  • Examples:

    # current time in UTC
    {{ now().strftime("%b %d %Y") }}
    # current time in Europe/Vienna
    {{ now('Europe/Vienna').strftime("%b %d %Y") }}

    Sample result

    2022-12-21 18:30:26.518253+00:00

timedelta()

Difference between two datetime values. Expression returns native Python timedelta object to allow time calculations when working with now(). The JSON representation of this expression is the number of total seconds.

  • Arguments:

    • days: Difference in days
    • hours: Difference in hours
    • minutes: Difference in minutes
    • seconds: Difference in seconds
    • weeks: Difference in weeks
    • milliseconds: Difference in milliseconds
    • microseconds: Difference in microseconds
  • Returns: timedelta object

  • Examples:

    # calculate yesterday by substracting one day
    {{ now() - timedelta(days=1) }}
    # offset current date and time by one week
    {{ now() + timedelta(weeks=1) }}
    # offset current date and time by one hour, thirty minutes, and fifteen seconds
    {{ now() - timedelta(hours=1, minutes=30, seconds=15) }}
    # double the timedelta value and increase it by five minutes
    {{ timedelta(hours=1)*2 + timedelta(minutes=5) }}

result()

Access the result of a preceding task within the workflow.

  • Arguments:
    • task name: Name to identify the task you try to access the result from
  • Returns: Task result object
  • Examples:
    # result of 'task_1' in the workflow
    {{ result('task_1') }}
    # result attribute 'foo' of 'task_1'
    # the result function allows to only return part of the object
    # if the result object does not have an attribute "foo", the function will fail with an "Undefined variables" message
    {{ result('task_1.foo') }}
    # alternatively, the whole result object can be returned and afterwards access the attributes of the object
    # if the result object does not have an attribute "foo", the expression will fail with an "Undefined variables" message
    {{ result('task_1').foo }}
    # both options can be combined, for example, with a default filter (see filters)
    {{ result('task_1').foo | default('foo is not defined') }}`
    # however for the following, at least the "foo" attribute needs to exist otherwise the same error will occour
    {{ result('task_1').foo.bar | default('foo is not defined') }}`
    # the get function can also be used to access object attributes
    {{ result('task_1').get('foo', 'foo is not defined') }}

scheduling_rules()

Access Scheduling rules and their attributes. The behavior and result is similar to an API request for the scheduling_rules endpoint.

  • Arguments:

    • identifier: scheduling rule ID
  • Keyword arguments: identical to the REST API. For more information, see the note above.

  • Returns: list of scheduling rule objects or a single scheduling rule object if id was specified

  • Examples:

    # access scheduling rule 'a941f679-a6ee-4f33-9914-b15ea32eb326'
    {{ scheduling_rules('a941f679-a6ee-4f33-9914-b15ea32eb326') }}

    Sample result

    {
    "id": "a941f679-a6ee-4f33-9914-b15ea32eb326",
    "created_at": "2022-12-07T12:42:45.806740Z",
    "updated_at": "2022-12-07T12:42:45.806755Z",
    "title": "First working day of the week",
    "rule_type": "rrule",
    "rrule": {
    "freq": "WEEKLY",
    "bysetpos": [
    1
    ],
    "interval": 1,
    "datestart": "2020-10-01",
    "byworkday": "WORKING"
    },
    "business_calendar": "8b31fda3-3227-431c-aafe-aa849894010b"
    }

scheduling_rules_includes()

Verify if a date is part of the selected dates of a scheduling rule.

You provide a scheduling rule identifier and a date as input, and the expression will evaluate to a Boolean (True or False). This can be used to implement logic in a task condition to control the workflow. The verification is done for a one year outlook maximum.

  • Arguments:
    • identifier: Scheduling rule ID
    • date: date to verify
  • Keyword Arguments:
    • format (optional): format of start date using strptime format codes
    • count (optional): number of preview dates to retrieve
  • Returns: Boolean
  • Examples:
    # verify if scheduling rule 'd6882cd1-9af4-41f4-801a-f2999a54aded' includes '2021-06-04'
    {{ scheduling_rules_includes('d6882cd1-9af4-41f4-801a-f2999a54aded', '2021-06-04') }}
    # verify if scheduling rule 'd6882cd1-9af4-41f4-801a-f2999a54aded' includes '04.06.2021'
    {{ scheduling_rules_includes('d6882cd1-9af4-41f4-801a-f2999a54aded', '04.06.2021', format='%d.%m.%Y') }}

scheduling_rules_preview()

Preview the next n dates for a scheduling rule. You can configure a start timestamp and count of dates you would like to retrieve. Optionally, you can also provide a formatting hint on how to interpret the provided start date.

  • Arguments:

    • Identifier: scheduling rule ID
  • Keyword Arguments:

    • start (optional): start date as string
    • format (optional): format of start date using strptime format codes
    • count (optional): number of preview dates to retrieve
  • Returns: preview object with the list of date objects in the "next_executions" attribute

  • Examples:

    # next dates for scheduling rule 'd6882cd1-9af4-41f4-801a-f2999a54aded'
    {{ scheduling_rules_preview('d6882cd1-9af4-41f4-801a-f2999a54aded') }}
    # next 10 dates for Schedule 'd6882cd1-9af4-41f4-801a-f2999a54aded' starting from '04.06.2021'
    {{ scheduling_rules_preview('d6882cd1-9af4-41f4-801a-f2999a54aded', start='04.06.2021', count=10) }}
    # next 10 dates for Schedule 'd6882cd1-9af4-41f4-801a-f2999a54aded' starting from '04.06.2023' with explicit format hint
    {{ scheduling_rules_preview('d6882cd1-9af4-41f4-801a-f2999a54aded', start='04.06.2023', format="%d.%m.%Y", count=5) }}
    # format the first returned date object following pattern %d.%m.%Y
    {{ scheduling_rules_preview('d6882cd1-9af4-41f4-801a-f2999a54aded', start='04.06.2023')["next_executions"][0].strftime("%d.%m.%Y") }}

    Sample result

    {
    "valid": true,
    "next_executions": [
    "2023-06-05",
    "2023-06-12",
    "2023-06-19",
    "2023-06-26",
    "2023-07-03"
    ]
    }

seconds_before()

Returns the number of seconds until clock_time in timezone_name. If the time in timezone_name is < clock_time, and 0 otherwise.

  • Arguments: None
  • Keyword Arguments:
    • clock_time: The time of day to compare to a string in the format of 'hh:mm:ss'
    • timezone_name: Timezones as available in pytz
  • Returns: integer
  • Examples:
    # get the number of seconds between now and 2 pm in New York
    # this returns 0 if it's already past 2 pm in New York
    # if it's currently 1 pm, returns 3600
    {{ seconds_before('14:00:00', 'America/New_York') }}

task()

Access to a task and its attributes within an execution. This allows you to access information about any other task within the same workflow.

  • Arguments:

    • task name: Name to identify the task you're trying to access. If no task name is given, the current task will be returned.
  • Returns: task object

  • Examples:

    # details of 'task_2' in the workflow
    {{ task('http_request_1') }}

    Example task object

    {
    "id": "http_request_1",
    "name": "http_request_1",
    "input": {
    "url": "http://www.google.com",
    "method": "GET",
    "headers": "",
    "payload": ""
    },
    "state": "SUCCESS",
    "action": "dynatrace.automations:http-function",
    "active": true,
    "result": {
    "body": "... ",
    "headers": {
    "date": "Wed, 21 Dec 2022 17:06:57 GMT",
    "server": "gws",
    "domain=.google.com; HttpOnly",
    "content-type": "text/html; charset=ISO-8859-1",
    "cache-control": "private, max-age=0",
    "x-frame-options": "SAMEORIGIN",
    "x-xss-protection": "0",
    "cross-origin-opener-policy-report-only": "same-origin-allow-popups; report-to=\"gws\""
    },
    "status_code": 200
    },
    "runtime": 1,
    "ended_at": "2022-12-21T17:06:58.155478Z",
    "position": {
    "x": 1,
    "y": 1
    },
    "execution": 'c4ff0688-0100-4618-93bd-e157b9a9280e',
    "conditions": {},
    "started_at": "2022-12-21T17:06:56.390869Z",
    "state_info": "",
    "predecessors": [],
    "triggered_by": [],
    "condition_results": {}
    }

workflows()

Access workflows and their attributes. The behavior and result are similar to an API request for the /workflows endpoint.

  • Arguments:
    • identifier: workflow ID
  • Keyword arguments: identical to the REST API. For more information, see the note above.
  • Returns: list of workflow objects or a single workflow object if id was specified
  • Examples:
    # return workflow with ID '39e054c0-cfa1-4c67-bdda-497ed20f08f3'
    {{ workflows('39e054c0-cfa1-4c67-bdda-497ed20f08f3') }}
    # 5 most recently updated workflows
    {{ workflows(limit=5, order='-updated_at') }}

workflow_execution()

Alias for execution()

Control structures

A control structure is anything that influences the flow of a template. We use it for conditions and loops. Control structures need to be inside {% … %} blocks and typically span multiple lines.

For loop

For loops iterate over each item in a list.

Basic example with static listExample assume you have a previous task called 'get_error_logs' which has a list of logs in its 'records', and each item is an object with multiple attributes, among which 'status' and 'content':

We found the following logs:
{% for log in result('get_error_logs').records %}
- {{ log.status }}: {{ log.content }}
{% endfor %}

Inside a loop block, there are additional variables available. For a full list, see Jinja documentation.

  • loop.index: The current iteration of the loop (1 indexed)
  • loop.first: True if first iteration
  • loop.last: True if last iteration
  • loop.length: The number of items in the sequence

The example generating an insert SQL statement from a list of valuesControl structures can also be combined, for example, to iterate a list of lists and create a table-like structure for a notification.

The DB query returned:
{% for row in result('get_entries_in_db').rows %}
Row {{loop.index}}:
{% for element in row %}
Value: {{element}}
{% endfor %}
{% endfor %}

If no iteration occurred because the sequence was empty or the filtering removed all the items from the sequence, you can render a default block using else.

{% for log in result('get_error_logs').records %}
- {{ log.status }}: {{ log.content }}
{% else %}
no logs found
{% endfor %}

If statement

The if statement can be used to test if a variable is defined, not empty, or a comparison is true.

Example to check if there is an event object provided:

{% if 'event' in execution().params %}
this execution was triggered by event
{% endif %}

or even simpler by using the event() shortcut

{% if event() %}
this was triggered by event
{% endif %}

The if statements also offer an optional else if elif and else block:

{% if result('get_ssl_certificate').expires_in_days <= 14 %}
We need to renew our certificate
{% elif esult('get_ssl_certificate').expires_in_days <= 30 %}
Let's think about renewing our certificate
{% else %}
All good
{% endif %}

Filters

Variables can be modified by filters using a pipe symbol (|) and may have optional arguments.

For example, {{ my_name|capitalize }} the first character will be uppercase, all others lowercase.

Use parentheses to apply arguments to filters, just like a function call. For example, {{ my_list|join(', ') }} will join a list with commas and whitespace in between.

For the complete list of filters, see Jinja List of Builtin Filters documentation.

Lists

  • first: Returns the first item of a list.
  • last: Returns the last item of a list.
  • join: Returns a string that contains the concatenation of the items in a list. {{ ['a', 'b', 'c']|join('=') }} returns 'a=b=c'
  • length: Returns the number of items in a list.
  • unique: Returns a list of unique items in a list.

Strings

  • capitalize: The first character will be uppercase, and all others lowercase.
  • length: Returns the number of characters in a string.
  • lower: Converts a string to lowercase.
  • replace: Replaces all occurrences of a substring with a new one. {{ 'Hello World'|replace('Hello', 'Greetings') }} returns 'Greetings World'
  • trim: Strips leading and trailing characters by default whitespace.
  • truncate: Returns a truncated copy of the string. The first parameter specifies the length, which defaults to 255.
  • upper: Converts a string to uppercase.
  • to_datetime: Converts an ISO8601-conform string to a datetime-object. An alternative format can be specified with the first parameter. Example: {{ "2019_08_01" | to_datetime('%Y_%m_%d') }}

Advanced searching, filtering, and replacing are supported using regex (regular expressions). Standard keyword parameters existing on any regex filter:

  • ignorecase: Performs case insensitive search. Defaults to False.
  • multiline: Performs replacement across multiple lines. Defaults to False.

The following regex-specific filters are supported:

  • regex_search: Performs a search on the string and extracts the string(or list of strings) that matches the regular expression

    Examples: {{ 'a12b34'|regex_search('b\\d\\d') }}
    Searches for a regex and extracts a specific group either specified by the name with \\g{groupName} or specified by the index with \\{groupIndex} (0 is always the whole match). The result will be a list of matches according to the passed groups {{ 'a12b34'|regex_search('b(?P<firstDigit>\\d)\\d', '\\gfirstDigit') | first }} {{ 'Hello World'|regex_search('^(?P<FirstWord>\\w+) (?P<SecondWord>\\w+)$', '\\gSecondWord', '\\1') }}

  • regex_findall: Gets all matches in a string.

    Example: 'DynaTrace'|regex_findall('[A-Z]') returns ['D', 'T']

  • regex_replace: Replaces a part of a string with another part.

    Examples: '1a3'|regex_replace('\d', 'X') 'Hello World'|regex_replace(' \w+$', ' Moon')

    • Additional keyword parameters for regex_replace:

      • count: Maximum number of pattern occurrences to replace. The default value is zero, which replaces all occurrences.
      • mandatory_count: Aborts the evaluation if fewer occurrences have been replaced.

Numbers

  • format_number: Formats a number in the format "1,234,567.89". You can change the thousand separator and the amount of trailing digits. {{ 3.14159|format_number(trailing_digits=0) }} results in 3. {{ 3.1415|format_number(trailing_digits=3, decimal_separator=',') }} results in 3,142. {{ 1234|format_number(thousand_separator='_') }} results in 1_234.00.

Any object

  • base64encode: Encodes a string or bytes object to a base64 string.
  • base64decode: Decodes a valid string or bytes object containing a base64 string to a string.
  • to_yaml: Converts an object to its yaml representation.
  • from_yaml: Converts a yaml string back to a Python object.
  • to_json: Converts an object to its JSON representation.
  • from_json: Converts a json string back to a Python object
  • dict2items: Converts a dict to a list of key-value pairs in the form of { 'key': 'keyValue', 'value': 'valueOfPair' }. {{ {'a': 1, 'b': 2}|dict2items }} returns [{ 'key': 'a', 'value': 1 }, { 'key': 'b', 'value': 2 }]. With the key_name and value_name arguments, you can change the key-value key of the return value.
  • items2dict: Converts a list of key-value pairs to a dict. {{ [{ 'key': 'a', 'valueA': 1, 'valueB': 7 }, { 'key': 'b', 'valueA': 2, 'valueB': 8 }]|items2dict(value_name='valueA') }} returns {'a': 1, 'b': 2}. The arguments key_name and value_name can modify which keys are used to construct the dict.
  • validate_regex: Validate if variable value matches regex. This filter also allows the overriding of the expression value validation definitions defined for the input by the app author. {{ 'example_string' | validate_regex('[a-z_]+') }}
  • bool: Returns true if the expression is truthy {{ 'truthy' | bool }}.
  • json_query: To select a single value or structure from JSON data. {{ { 'key': 'a', 'value': { 'nestedValue': 'b' }}|json_query('value.nestedValue') }} returns b. The filter builds on top of the JMESPATH library. For examples and interactive tryout, see the JMESPATH documentation.
  • ternary: Returns the first argument value if it is truthy; otherwise the second argument value is returned. The third argument none_val is optional; if provided, it is returned when the first argument value is None. {{ True | ternary("foo", "bar") }} returns foo. {{ False | ternary("foo", "bar") }} returns bar. {{ None | ternary("foo", "bar", none_val="fizz") }} returns fizz.

default value

  • default: If the value is undefined it will return the provided value, otherwise the value of the variable. {{ my_variable|default('my_variable is not defined') }}