Skip to content

Dynamic templating

Dynamic templating lets you customize notification content and routing using Tera expressions. Use it to make messages, routing rules, and connector configurations respond to alert or case data in real time.

Where to use dynamic templating

Tera expressions work in:

  • Connectors: dynamically set URLs, headers, channels, or service keys
  • Presets: customize message content for alerts and cases
  • Routing rules: create conditions that determine where notifications are sent

What dynamic templating does

Dynamic templating supports:

  • Inserting alert or case values directly into message templates
  • Applying conditional logic (if, elif, else)
  • Formatting timestamps, numbers, and text
  • Routing notifications based on metadata such as priority, team, or service

Global context available

All templates have access to a built-in _context variable containing metadata about the notification source.
VariableDescription
_contextContains metadata about the context of the notification source type.
_context.entityTypeThe notification source type (alerts, cases).
_context.entitySubTypeThe entity subtype (for example, metricThresholdTriggered).
_context.entityLabelsNotification source type labels associated with the context (e.g., host, region).
_context.systemInformation about the system, including its ID and name.
_context.system.idThe system's unique identifier.
_context.system.nameYour Coralogix team or system name (e.g., acme-prod).
_context.triggerThe trigger that initiated the notification source type.
_context.trigger.typeTrigger type (manual, automatic).
_context.trigger.automaticTriggerAutomatic trigger details (if applicable).
_context.trigger.manualTriggerManual trigger details (e.g., user email).
_context.trigger.manualTrigger.userEmailThe email address of the user who manually triggered the notification source type.

Label data shapes: alerts vs. Cases

Label data has different shapes depending on its source. The same key can be a single value or an array of values, so use the right read form for each. If you read an array-shaped label without indexing into it, the template renders the array literal, including the surrounding square brackets. The bracketed output then propagates into whatever the template feeds, for example Slack channel names, HTTPS payload fields, ServiceNow ticket fields, or email subject lines.
VariableSourceShapeHow to read
alertDef.entityLabelsAlert definition{ key: value }{{ alertDef.entityLabels["Service"] }}
alert.groups[N].keyValuesAlert group{ key: value }{{ alert.groups[0].keyValues["Service"] }}
_context.entityLabelsNotification context{ key: value[] }{{ _context.entityLabels["Service"][0] }}
case.labelsCase{ key: value[] }{{ case.labels["Service"][0] }}

For alerts, _context.entityLabels arrays always contain a single value. For Cases, the array can contain multiple values; use [0] to read the first one. For case.labels and _context.entityLabels, always index into the array. For alertDef.entityLabels and alert.groups, read the value directly.

To confirm the shape for a specific notification before writing a template, see Inspect context.

Common use cases

Insert dynamic values

{{ alert.highestPriority }} - {{ alertDef.name }}
````
### Conditional output
```tera
{% if alert.highestPriority == "P1" %}
#critical-alerts
{% elif alert.highestPriority == "P3" %}
#warn-alerts
{% else %}
#general
{% endif %}

Format dates

{{ alert.timestamp | date(format="%Y-%m-%d %H:%M") }}

Use default values

{{ alertDef.entityLabels.team | default(value="no team assigned") }}

Inspect context

To view the entire context object during configuration, use:

{{ get_context() | json_encode(pretty = true) }}

Note

  • Wrap dynamic expressions in {{ }} or {% %}.
  • Use the default filter to handle missing values.
  • Keep templates simple; avoid unnecessary complexity.
  • Test templates with example data before saving.

Example: conditional alert handling based on name

{% if alertDef.name == "RDS Instance Low CPU" %}
affected db: {{ alert.groups[0].keyValues.DBInstanceIdentifier }}
credit balance is below: {{ i.condition.threshold }}
owning team: {{ alert.groups[0].keyValues.Team }}

{% elif alertDef.name == "OOM killed pod" %}
pod: {{ alert.groups[0].keyValues.k8s_pod_name }}
container: {{ alert.groups[0].keyValues.k8s_container_name }}

{% else %}
{{ alertDef.name }} is triggering
{% endif %}

Example: logs threshold alert description

{{ alert.timestamp | date(format="%Y-%m-%d %H:%M") }}

We've detected that the query result has dropped below the threshold for the following values of {{ alertDef.groupByKeys }}:

Priority / Values / Threshold / Start Time / End Time
{% for i in alert.groups %}
{{ i.priority }} / {{ i.keyValues | json_escape }} / {{ i.details.logsThreshold.fromTimestamp | date(format="%Y-%m-%d %H:%M") }} / {{ i.details.logsThreshold.toTimestamp }}
{% endfor %}

Alert Query:
{{ alertDef.typeDefinition.logsThreshold.luceneQuery }}

Alert Condition Rules:
Condition type - {{ alertDef.typeDefinition.logsThreshold.rules[0].condition.conditionType }}
Condition rules -
{% for i in alertDef.typeDefinition.logsThreshold.rules %}
Threshold: {{ i.condition.threshold }}, timeframe: {{ i.condition.timeWindow.logsTimeWindowSpecificValue }}.
{% endfor %}

@jane.doe  
@here

Example: grouping by service

{
  "alert_url": "https://teamname-prod.app.eu2.coralogix.com/#/alerts/{{ alert.id }}",
  "service": "{{ alert.groups[0].keyValues.service_name }}",
  "priority": "{{ alert.highestPriority }}",
  "timestamp": "{{ alert.timestamp | date(format=\"%Y-%m-%d %H:%M\") }}",
  "status": "{{ alert.status }}"
}

Next steps

Explore operators, filters, and tests for building Tera expressions in Tera syntax quick reference.