Expression reference
Latest Dynatrace
Dynatrace Workflows use Jinja templating engine to allow for dynamic configurations in workflows. Those expressions provide access to exeuction parameters, schedule information, event context, and much more.
They enable you to reference results from predecessors in a task configuration and define [custom conditions] (link to task conditions).
There are two kinds of delimiters.
{{ ... }}
for expressions, used to access data from other tasks, executions and functions.{% ... %}
for statements and control structures like loops and if conditions.
Expressions
The list below is a reference list of the expressions available. Beyond that you can use any templating functionality Jinja provides!
Expressions are supported in any input of any action (unless specified otherwise by the action developer) as well as the custom task conditions. A noteable exception is the Run Javascript action, which does not support expression in its input to avoid the possibility of code injection. See [Actions:run javascript] on how to access execution paramaters using the Run Javascript action
We strive for ease of use and therfore consistency between different ways to access the same information. No matter if you use the REST API or expression to access Workflows, Executions, Scheduling-Rules, Calendars there are the same arguments 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 REST API request returns JSON, an expression will return a native object, respectively its string representation.
Access to resources happens in context of the workflow actor (link to workflow settings).
calendars()
Access business calendars and their attributes. The behavior and result is similar to an API request for the /usiness_calendars
endpoint.
-
Arguments:
- identifier: Calendar id
-
Keyword arguments: identical to the REST API please see note on top.
-
Returns: 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", }
event()
- Arguments:
- event attribute (optional): Access only a specific attribute of the event object
- Keyword arguments: None
- Returns: event object which was passed via exeuction 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 }}
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" }
executions()
Access executions and their attributes. The behavior and result is similar to an API request for the /executions
endpoint.
- Arguments:
- identifier: Workflow Execution id
- Keyword arguments: identical to the REST API please see note on top.
- 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()
Current timestamp in UTC or timezone as provided as input parameter. Expression returns native Python datetime object, in order to allow formatting into any desired output. Use strftime
and format codes as described in 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
result()
Access the result of a preceeding 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 please see note on top.
-
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 1 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 provide also a formatting hint, on how to interprete 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 srings 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 }}
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 as 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 try 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 is similar to an API request for the /workflows
endpoint.
- Arguments:
- identifier: Workflow id
- Keyword arguments: identical to the REST API please see note on top.
- 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 be inside {% … %} blocks and typically span across multiple lines.
For loop
For loops iterate over each item in a list.
Basic example with static list
{% for my_item in ["item 1", "item 2", "item 3"] %}
item : {{ my_item }}
{% endfor %}
Example assuming 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.
Example generating an insert SQL statement from a list of values
INSERT into dummy_table(name, address, priority)
VALUES
{% for sub in result('get_').subscribers %}
('My Item {{ sub.name }}', 'Sample Address {{ sub.address }}', 42)
{% if not loop.last %},{% endif %}
{% endfor %}
Control strcutures can also be combined, eg to iterate of a list of lists and create a table like structure for a notifcation:
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 took place because the sequence was empty or the filtering removed all the items from the sequence, you can render a default block by 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 varaible 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 offers 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.
To apply arguments to filters, use paranthesis, just like a function call. For example: {{ my_list|join(', ') }}
will join a list with commas and whitespace inbetween.
For the full list of filters, see Jinja documentation
Common filters:
for lists
first
: Return the first item of a list.last
: Return the last item of a list.join
: Return a string which is the concatenation of the items in a list.{{ ['a', 'b', 'c']|join('=') }}
returns 'a=b=c'length
: Return the number of items in a list.unique
: Returns a list of unique items in a list.
for strings
capitalize
: The first character will be uppercase, all others lowercase.length
: Return the number of characters in a string.lower
: Convert a string to lowercase.replace
: Replace all occurrences of a substring with a new one.{{ 'Hello World'|replace('Hello', 'Greetings') }}
returns 'Greetings World'trim
truincate
upper
: Convert a string to uppercase.
default value
default
: If the value is undefined it will return provided value, otherwise the value of the variable.{{ my_variable|default('my_variable is not defined') }}