Notification template reference
By default, Grafana provides predefined templates to format notification messages.
You can also customize your notifications with custom templates, which are based on the Go template language.
This documentation lists the data available for use in notification templates.
Notification Data
In notification templates, dot (.
) is initialized with the following data:
It’s important to remember that a single notification can group multiple alerts to reduce the number of alerts you receive. Alerts
is an array that includes all the alerts in the notification.
Here’s an example that prints all available notification data from dot (.
):
{{ define "custom_template" }}
{{ .Receiver }}
{{ .Status }}
There are {{ len .Alerts }} alerts
There are {{ len .Alerts.Firing }} firing alerts
There are {{ len .Alerts.Resolved }} resolved alerts
{{ .GroupLabels }}
{{ .CommonLabels }}
{{ .CommonAnnotations }}
{{ .ExternalURL }}
{{ end }}
You can execute this template by passing the dot (.
):
{{ template "custom_template" . }}
Alert
Alert
contains data for an individual alert:
Grafana-managed alerts include these additional properties:
This example iterates over the list of firing and resolved alerts (.Alerts
) in the notification and prints the data for each alert:
{{ define "custom_template" }}
{{ range .Alerts }}
{{ .Status }}
{{ .Labels }}
{{ .Annotations }}
{{ .StartsAt }}
{{ .EndsAt }}
{{ .GeneratorURL }}
{{ .Fingerprint }}
{{/* Only available for Grafana-managed alerts */}}
{{ .DashboardURL }}
{{ .PanelURL }}
{{ .SilenceURL }}
{{ .Values }}
{{ .ValueString }}
{{ end }}
{{ end }}
You can run this template by passing the dot (.
):
{{ template "custom_template" . }}
KV
KV
is a set of key value pairs, where each key and value is a string.
Similarly to accessing variable properties, you can use .
to retrieve the value of a value. For example:
{{ define "custom_template" }}
{{ .CommonLabels.grafana_folder }}
{{ end }}
If a KV happens to contain numbers or bools then these are string representations of the numeric or boolean value.
Additionally, KV provides methods to sort the pairs, remove keys, and iterate over just the keys or values:
Here’s an example of using these methods:
{{ define "custom_template" }}
{{ .CommonLabels.SortedPairs }}
{{ .CommonLabels.Names }}
{{ .CommonLabels.Values }}
{{ .CommonLabels.Remove (stringSlice "grafana_folder") }}
{{ end }}
Time
Some template functions and properties return a Time
object, which refers to the type Time
in Go’s time package.
When accessing a Time
object, you can use various Time
functions in your templates as follows.
{{ define "custom_template" }}
{{ range .Alerts }}
{{ .StartsAt }}
{{ .StartsAt.Add 6000000000000 }}
{{ .StartsAt.Add -6000000000000 }}
{{ .StartsAt.AddDate 1 0 0 }}
{{ .StartsAt.Year }}/{{ .StartsAt.Month }}/{{ .StartsAt.Day }}
{{ .StartsAt.Hour }}:{{ .StartsAt.Minute }}:{{ .StartsAt.Second }}
{{ .StartsAt.YearDay }}-{{ .StartsAt.Weekday }}
{{ .StartsAt.Unix }} {{ .StartsAt.UnixMilli }}
{{ end}}
{{ end }}
Functions
Functions can perform actions in templates such as transforming or formatting data.
Note that the functions provided by Go’s template language, such as index
, and
, printf
, and len
, are available, along with many others.
In addition, the following functions are also available for templating notifications:
Here’s an example using some functions to format text:
{{ define "custom_template" }}
{{ title "hello, world!" }}
{{ toUpper "Hello, world!" }}
{{ toLower "Hello, world!" }}
{{ trimSpace "Hello, world!" }}
{{ match "a.*" "abc" }}
{{ reReplaceAll "localhost:(.*)" "example.com:$1" "localhost:8080" }}
{{ join "-" (stringSlice "a" "b" "c") }}
{{ safeHtml "<b>Text</b>"}}
{{ stringSlice "a" "b" "c" }}
{{ end }}
date
and tz
can format times. For example, to print the time an alert fired in the format 15:04:05 MST
:
{{ define "custom_template" }}
{{ range .Alerts }}
{{ .StartsAt | date "15:04:05 MST" }}
{{ end}}
{{ end }}
You can then use tz
to change the timezone from UTC to local time, such as Europe/Paris
.
{{ define "custom_template" }}
{{ range .Alerts }}
{{ .StartsAt | tz "Europe/Paris" }}
{{ .StartsAt | tz "Europe/Paris" | date "15:04:05 MST" }}
{{ end}}
{{ end }}
2024-10-30 21:01:45.227 +0100 CET
21:01:45 CET
Namespaced Functions
In addition to the top-level functions, the following namespaced functions are also available:
Collection Functions
Example using collection functions:
{{ define "collection.example" }}
{{- /* Create a dictionary of alert metadata */ -}}
{{- $metadata := coll.Dict
"severity" "critical"
"team" "infrastructure"
"environment" "production"
-}}
{{- /* Create a slice of affected services */ -}}
{{- $services := coll.Slice "database" "cache" "api" -}}
{{- /* Append a new service to the list */ -}}
{{- $services = coll.Append "web" $services -}}
{{- /* Use the collections in a template */ -}}
Affected Services: {{ range $services }}{{ . }},{{ end }}
Alert Metadata:
{{- range $k, $v := $metadata }}
{{ $k }}: {{ $v }}
{{- end }}
{{ end }}
Output:
Affected Services: database,cache,api,web,
Alert Metadata:
environment: production
severity: critical
team: infrastructure
Data Functions
Example using data functions:
{{ define "data.example" }}
{{- /* First, let's create some alert data as a JSON string */ -}}
{{ $jsonString := `{
"service": {
"name": "payment-api",
"environment": "production",
"thresholds": {
"error_rate": 5,
"latency_ms": 100
}
}
}` }}
{{- /* Parse the JSON string into an object we can work with */ -}}
{{ $config := $jsonString | data.JSON }}
{{- /* Create a new alert payload */ -}}
{{ $payload := coll.Dict
"service" $config.service.name
"environment" $config.service.environment
"status" .Status
"errorThreshold" $config.service.thresholds.error_rate
}}
{{- /* Output the payload in different JSON formats */ -}}
Compact JSON: {{ $payload | data.ToJSON }}
Pretty JSON with 2-space indent:
{{ $payload | data.ToJSONPretty " " }}
{{ end }}
Output:
Compact JSON: {"environment":"production","errorThreshold":5,"service":"payment-api","status":"resolved"}
Pretty JSON with 2-space indent:
{
"environment": "production",
"errorThreshold": 5,
"service": "payment-api",
"status": "resolved"
}
Template Functions
{{ define "template.example" -}}
{{ coll.Dict
"info" (tmpl.Exec `info` . | data.JSON)
"severity" (tmpl.Inline `{{ print "critical" | toUpper }}` . )
| data.ToJSONPretty " "}}
{{- end }}
{{- /* Define a sub-template */ -}}
{{ define "info" -}}
{{coll.Dict
"team" "infrastructure"
"environment" "production" | data.ToJSON }}
{{- end }}
Output:
{
"info": {
"environment": "production",
"team": "infrastructure"
},
"severity": "CRITICAL"
}
Time Functions
Example using time functions:
{{ define "time.example" }}
{{- /* Get current time in different formats */ -}}
Current Time (UTC): {{ (time.Now).UTC.Format "2006-01-02 15:04:05 MST" }}
Current Time (Local): {{ (time.Now).Format "Monday, January 2, 2006 at 15:04:05" }}
{{- /* Compare alert time with current time */ -}}
{{ $timeAgo := (time.Now).Sub .StartsAt }}
Alert fired: {{ $timeAgo }} ago
{{ end }}
Output:
Current Time (UTC): 2025-03-08 18:14:27 UTC
Current Time (Local): Saturday, March 8, 2025 at 14:14:27
Alert fired: 25h49m32.78574723s ago
Differences with annotation and label templates
In the alert rule, you can also template annotations and labels to include additional information. For example, you might add a summary
annotation that displays the query value triggering the alert.
Annotation and label templates add relevant information to individual alert instances, while notification templates inform about a group of alert instances.
Since both types of templates operate in distinct contexts, the functions and variables available in annotation and label templates differ from those used in notification templates.