Docs: Templating notifications (#60109)

* Docs: Templating notifications

* Feedback

* More feedback

* Edit template notifications

* More edits

* Fix typo

Co-authored-by: brendamuir <100768211+brendamuir@users.noreply.github.com>
Co-authored-by: Armand Grillet <2117580+armandgrillet@users.noreply.github.com>
This commit is contained in:
George Robinson 2022-12-19 15:01:18 +00:00 committed by GitHub
parent f67b8fe0dc
commit f6aea16894
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 667 additions and 0 deletions

View File

@ -0,0 +1,46 @@
---
aliases:
keywords:
- grafana
- alerting
- notifications
- templates
title: Customize notifications
weight: 100
---
# Customize notifications
Customize your notifications by creating message templates to use in the notifications sent to contact points.
You can use message templates to change the title, message, and format of the message in your notifications.
Message templates are not tied to specific contact point integrations, such as email or Slack. However, you can choose to create separate message templates for different contact point integrations.
You can use message templates to:
- Add, remove, or re-order information in the notification including the summary, description, labels and annotations, values, and links
- Format text in bold and italic, and add or remove line breaks
You cannot use message templates to:
- Change how images are included in notifications, such as the number of images in each notification or where in the notification inline images are shown
- Change the design of notifications in instant messaging services such as Slack and Microsoft Teams
- Change the data in webhook notifications, including the structure of the JSON request or sending data in other formats such as XML
- Add or remove HTTP headers in webhook notifications other than those in the contact point configuration
[Using Go's templating language]({{< relref "./using-go-templating-language" >}})
Learn how to write the content of your message templates in Gos templating language.
[Create message templates]({{< relref "./create-message-templates" >}})
Create reusable message templates for your contact points.
[Use message templates]({{< relref "./use-message-templates" >}})
Use message templates to send notifications to your contact points.
[Reference]({{< relref "./reference" >}})
Data that is available when writing templates.

View File

@ -0,0 +1,253 @@
---
aliases:
keywords:
- grafana
- alerting
- notifications
- templates
- create templates
- edit templates
- delete templates
title: Create message templates
weight: 300
---
# Create message templates
Create reusable message templates to send to your contact points.
You can add one or more templates to your message template.
Your message template name must be unique. You cannot have two templates with the same name in the same message template or in different message templates. Avoid defining templates with the same name as default templates, such as: `__subject`, `__text_values_list`, `__text_alert_list`, `default.title` and `default.message`.
In the Contact points tab, you can see a list of your message templates.
To create a template, complete the following steps.
1. Click New template.
2. Choose a name for the message template.
3. Write the content of the template in the content field.
{{< figure max-width="940px" src="/static/img/docs/alerting/unified/new-message-template-email-subject-9-3.png" caption="New message template email.subject" >}}
5. Click Save.
`{{ define "email.subject" }}` and `{{ end }}` is automatically added to the start and end of the content:
{{< figure max-width="940px" src="/static/img/docs/alerting/unified/edit-message-template-email-subject-9-3.png" caption="Edit message template email.subject" >}}
To create a message template that contains more than one template:
1. Click New Template.
2. Enter a name for the message template.
3. Write each template in the Content field, including `{{ define "name-of-template" }}` and `{{ end }}` at the start and end of each template.
{{< figure max-width="940px" src="/static/img/docs/alerting/unified/new-message-template-email-9-3.png" caption="New message template" >}}
5. Click Save.
## Template the subject of an email
Template the subject of an email to contain the number of firing and resolved alerts:
```
1 firing alert(s), 0 resolved alerts(s)
```
1. Create a template called `email.subject` with the following content:
```
{{ define "email.subject" }}
{{ len .Alerts.Firing }} firing alert(s), {{ len .Alerts.Resolved }} resolved alert(s)
{{ end }}
```
2. Execute the template from the subject field in your contact point integration:
```
{{ template "email.subject" . }}
```
## Template the message of an email
Template the message of an email to contain a summary of all firing and resolved alerts:
```
There are 2 firing alert(s), and 1 resolved alert(s)
Firing alerts:
- alertname=Test 1 grafana_folder=GrafanaCloud has value(s) B=1
- alertname=Test 2 grafana_folder=GrafanaCloud has value(s) B=2
Resolved alerts:
- alertname=Test 3 grafana_folder=GrafanaCloud has value(s) B=0
```
1. Create a message template called `email` with two templates in the content: `email.message_alert` and `email.message`.
The `email.message_alert` template is used to print the labels and values for each firing and resolved alert while the `email.message` template contains the structure of the email.
```
{{- define "email.message_alert" -}}
{{- range .Labels.SortedPairs }}{{ .Name }}={{ .Value }} {{ end }} has value(s)
{{- range $k, $v := .Values }} {{ $k }}={{ $v }}{{ end }}
{{- end -}}
{{ define "email.message" }}
There are {{ len .Alerts.Firing }} firing alert(s), and {{ len .Alerts.Resolved }} resolved alert(s)
{{ if .Alerts.Firing -}}
Firing alerts:
{{- range .Alerts.Firing }}
- {{ template "email.message_alert" . }}
{{- end }}
{{- end }}
{{ if .Alerts.Resolved -}}
Resolved alerts:
{{- range .Alerts.Resolved }}
- {{ template "email.message_alert" . }}
{{- end }}
{{- end }}
{{ end }}
```
2. Execute the template from the message field in your contact point integration:
```
{{ template "email.message" . }}
```
## Template the title of a Slack message
Template the title of a Slack message to contain the number of firing and resolved alerts:
```
1 firing alert(s), 0 resolved alerts(s)
```
1. Create a template called `slack.title` with the following content:
```
{{ define "slack.title" }}
{{ len .Alerts.Firing }} firing alert(s), {{ len .Alerts.Resolved }} resolved alert(s)
{{ end }}
```
2. Execute the template from the title field in your contact point integration:
```
{{ template "slack.title" . }}
```
## Template the content of a Slack message
Template the content of a Slack message to contain a description of all firing and resolved alerts, including their labels, annotations, Silence URL and Dashboard URL:
```
1 firing alert(s):
[firing] Test1
Labels:
- alertname: Test1
- grafana_folder: GrafanaCloud
Annotations:
- description: This is a test alert
Silence: https://example.com/alerting/silence/new?alertmanager=grafana&matcher=alertname%3DTest1&matcher=grafana_folder%3DGrafanaCloud
Go to dashboard: https://example.com/d/dlhdLqF4z?orgId=1
1 resolved alert(s):
[firing] Test2
Labels:
- alertname: Test2
- grafana_folder: GrafanaCloud
Annotations:
- description: This is another test alert
Silence: https://example.com/alerting/silence/new?alertmanager=grafana&matcher=alertname%3DTest2&matcher=grafana_folder%3DGrafanaCloud
Go to dashboard: https://example.com/d/dlhdLqF4z?orgId=1
```
1. Create a template called `slack` with two templates in the content: `slack.print_alert` and `slack.message`.
The `slack.print_alert` template is used to print the labels, annotations, SilenceURL and DashboardURL while the `slack.message` template contains the structure of the notification.
```
{{ define "slack.print_alert" -}}
[{{.Status}}] {{ .Labels.alertname }}
Labels:
{{ range .Labels.SortedPairs -}}
- {{ .Name }}: {{ .Value }}
{{ end -}}
{{ if .Annotations -}}
Annotations:
{{ range .Annotations.SortedPairs -}}
- {{ .Name }}: {{ .Value }}
{{ end -}}
{{ end -}}
{{ if .SilenceURL -}}
Silence: {{ .SilenceURL }}
{{ end -}}
{{ if .DashboardURL -}}
Go to dashboard: {{ .DashboardURL }}
{{- end }}
{{- end }}
{{ define "slack.message" -}}
{{ if .Alerts.Firing -}}
{{ len .Alerts.Firing }} firing alert(s):
{{ range .Alerts.Firing }}
{{ template "slack.print_alert" . }}
{{ end -}}
{{ end }}
{{ if .Alerts.Resolved -}}
{{ len .Alerts.Resolved }} resolved alert(s):
{{ range .Alerts.Resolved }}
{{ template "slack.print_alert" .}}
{{ end -}}
{{ end }}
{{- end }}
```
2. Execute the template from the text body field in your contact point integration:
```
{{ template "slack.message" . }}
```
## Template both email and Slack with shared templates
Instead of creating separate message templates for email and Slack, you can share the same template.
For example, if you want to send an email with this subject and Slack message with this title:
```
1 firing alert(s), 0 resolved alerts(s)
```
1. Create a template called `common.subject_title` with the following content:
```
{{ define "common.subject_title" }}
{{ len .Alerts.Firing }} firing alert(s), {{ len .Alerts.Resolved }} resolved alert(s)
{{ end }}
```
2. For email, execute the template from the subject field in your email contact point integration:
```
{{ template "common.subject_title" . }}
```
3. For Slack, execute the template from the title field in your Slack contact point integration:
```
{{ template "common.subject_title" . }}
```

View File

@ -0,0 +1,75 @@
---
aliases:
keywords:
- grafana
- alerting
- notifications
- templates
title: Reference
weight: 600
---
# Reference
## Data
### Alert
| Name | Kind | Description | Example |
| ------------ | -------- | ------------------------------------------------------------------------------------ | --------------------- |
| Status | `string` | Firing or resolved | `{{ .Status }}` |
| Labels | `KV` | The labels for this alert | `{{ .Labels }}` |
| Annotations | `KV` | The annotations for this alert | `{{ .Annotations }}` |
| Values | `KV` | The values of all expressions, including Classic Conditions | `{{ .Values }}` |
| StartsAt | `Time` | The time the alert fired | `{{ .StartsAt }}` |
| EndsAt | `Time` | | `{{ .EndsAt }}` |
| GeneratorURL | `string` | A link to Grafana, or the Alertmanager if using an external Alertmanager | `{{ .GeneratorURL }}` |
| SilenceURL | `string` | A link to silence the alert | `{{ .SilenceURL }}` |
| DashboardURL | `string` | A link to the Grafana Dashboard if the alert has a Dashboard UID annotation | `{{ .DashboardURL }}` |
| PanelURL | `string` | A link to the panel if the alert has a Panel ID annotation | `{{ .PanelID }}` |
| Fingerprint | `string` | A unique string that identifies the alert | `{{ .Fingerprint }}` |
| ValueString | `string` | A string that contains the labels and value of each reduced expression in the alert. | `{{ .ValueString }}` |
### ExtendedData
| Name | Kind | Description | Example |
| ----------------- | --------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| Receiver | `string` | The name of the contact point sending the notification | `{{ .Receiver }}` |
| Status | `string` | The status is `firing` if at least one alert is firing, otherwise `resolved` | `{{ .Status }}` |
| Alerts | `[]Alert` | List of all firing and resolved alerts in this notification | `There are {{ len .Alerts }} alerts` |
| Firing alerts | `[]Alert` | List of all firing alerts in this notification | `There are {{ len .Alerts.Firing }} firing alerts` |
| Resolved alerts | `[]Alert` | List of all resolved alerts in this notification | `There are {{ len .Alerts.Resolved }} resolved alerts` |
| GroupLabels | `KV` | The labels that group these alerts in this | `{{ .GroupLabels }}` |
| CommonLabels | `KV` | The labels common to all alerts in this notification | `{{ .CommonLabels }}` |
| CommonAnnotations | `KV` | The annotations common to all alerts i this notification | `{{ .CommonAnnotations }}` |
| ExternalURL | `string` | A link to Grafana, or the Alertmanager that sent this notification if using an external Alertmanager | `{{ .ExternalURL }}` |
### KV
`KV` is a set of key value pairs, where each key and value is a string. If a KV happens to contain numbers or bools then these are string representations of the numeric or boolean value.
Here is an example of a KV, the annotations of an alert:
```yaml
summary: 'A summary of the alert'
description: 'A description of the alert'
```
In addition to iterating over each key value pair, you can sort the pairs, remove keys, and iterate over just the keys or the values.
| Name | Description | Arguments | Returns | Example |
| ----------- | ---------------------------------------------- | --------- | ------- | ------------------------------------- |
| SortedPairs | Sorts | | | `{{ .Annotations.SortedPairs }}` |
| Remove | Returns a copy of the KV with the keys removed | []string | | `{{ .Annotations.Remove "summary" }}` |
| Names | A list of the names | | | `{{ .Names }}` |
| Values | A list of the values | | | `{{ .Values }}` |
### Time
Time is from the Go [`time`](https://pkg.go.dev/time#Time) package. You can print a time in a number of different formats. For example, to print the time that an alert fired in the format `Monday, 1st January 2022 at 10:00AM` you would write the following template:
```
{{ .StartsAt.Format "Monday, 2 January 2006 at 3:04PM" }}
```
You can find a reference for Go's time format [here](https://pkg.go.dev/time#pkg-constants).

View File

@ -0,0 +1,29 @@
---
aliases:
keywords:
- grafana
- alerting
- notifications
- templates
- use templates
title: Use message templates
weight: 400
---
# Use message templates
Use templates in contact points to customize your notifications.
In the Contact points tab, you can see a list of your contact points.
1. To create a new contact point, click New.
**Note:** You can edit an existing contact by clicking the Edit icon.
2. Execute a template from one or more fields such as Message and Subject:
{{< figure max-width="940px" src="/static/img/docs/alerting/unified/use-message-template-9-3.png" caption="Use message template" >}}
For more information on how to write and execute templates, refer to [Using Go's templating language]({{< relref "./using-go-templating-language" >}}) and [Create message templates]({{< relref "./create-message-templates" >}}).
4. Click Save template.

View File

@ -0,0 +1,264 @@
---
aliases:
keywords:
- grafana
- alerting
- notifications
- templates
- write templates
title: Using Go's templating language
weight: 200
---
# Using Go's templating language
You write message templates in Go's templating language, [text/template](https://pkg.go.dev/text/template).
Before you start creating your own message templates, we recommend that you read through this topic, which provides you with an overview of Go's templating language and writing templates in text/template.
## Dot
In text/template there is a special cursor called dot, and is written as `.`. You can think of this cursor as a variable whose value changes depending where in the template it is used. For example, at the start of a message template `.` refers to something called [`ExtendedData`]({{< relref "./reference" >}}) which contains a number of fields including `Alerts`, `Status`, `GroupLabels`, `CommonLabels`, `CommonAnnotations` and `ExternalURL`. However, dot might refer to something else when used in a range over a list, when used inside a `with`, or when writing feature templates to be used in other templates. You can see examples of this in [Template examples]({{< relref "./template-examples" >}}), and all data and functions in the [Reference]({{< relref "./reference" >}}).
## Opening and closing tags
In text/template, templates start with `{{` and end with `}}` irrespective of whether the template prints a variable or executes control structures such as if statements. This is different from other templating languages such as Jinja where printing a variable uses `{{` and `}}` and control structures use `{%` and `%}`.
## Print
To print the value of something use `{{` and `}}`. You can print the value of dot, a field of dot, the result of a function, and the value of a [variable]({{< relref "#variables" >}}). For example, to print the `Alerts` field where dot refers to `ExtendedData` you would write the following:
```
{{ .Alerts }}
```
## Iterate over alerts
To print just the labels of each alert, rather than all information about the alert, you can use a `range` to iterate the alerts in `ExtendedData`:
```
{{ range .Alerts }}
{{ .Labels }}
{{ end }}
```
Inside the range dot no longer refers to `ExtendedData`, but to an `Alert`. You can use `{{ .Labels }}` to print the labels of each alert. This works because `{{ range .Alerts }}` changes dot to refer to the current alert in the list of alerts. When the range is finished dot is reset to the value it had before the start of the range, which in this example is `ExtendedData`:
```
{{ range .Alerts }}
{{ .Labels }}
{{ end }}
{{/* does not work, .Labels does not exist here */}}
{{ .Labels }}
{{/* works, cursor was reset */}}
{{ .Status }}
```
## Iterate over annotations and labels
Let's write a template to print the labels of each alert in the format `The name of the label is $name, and the value is $value`, where `$name` and `$value` contain the name and value of each label.
Like in the previous example, use a range to iterate over the alerts in `.Alerts` such that dot refers to the current alert in the list of alerts, and then use a second range on the sorted labels so dot is updated a second time to refer to the current label. Inside the second range use `.Name` and `.Value` to print the name and value of each label:
```
{{ range .Alerts }}
{{ range .Labels.SortedPairs }}
The name of the label is {{ .Name }}, and the value is {{ .Value }}
{{ end }}
{{ range .Annotations.SortedPairs }}
The name of the annotation is {{ .Name }}, and the value is {{ .Value }}
{{ end }}
{{ end }}
```
## If statements
You can use if statements in templates. For example, to print `There are no alerts` if there are no alerts in `.Alerts` you would write the following:
```
{{ if .Alerts }}
There are alerts
{{ else }}
There are no alerts
{{ end }}
```
## With
With is similar to if statements, however unlike if statements, `with` updates dot to refer to the value of the with:
```
{{ with .Alerts }}
There are {{ len . }} alert(s)
{{ else }}
There are no alerts
{{ end }}
```
## Variables
Variables in text/template must be created within the template. For example, to create a variable called `$variable` with the current value of dot you would write the following:
```
{{ $variable := . }}
```
You can use `$variable` inside a range or `with` and it will refer to the value of dot at the time the variable was defined, not the current value of dot.
For example, you cannot write a template that use `{{ .Labels }}` in the second range because here dot refers to the current label, not the current alert:
```
{{ range .Alerts }}
{{ range .Labels.SortedPairs }}
{{ .Name }} = {{ .Value }}
{{/* does not work because in the second range . is a label not an alert */}}
There are {{ len .Labels }}
{{ end }}
{{ end }}
```
You can fix this by defining a variable called `$alert` in the first range and before the second range:
```
{{ range .Alerts }}
{{ $alert := . }}
{{ range .Labels.SortedPairs }}
{{ .Name }} = {{ .Value }}
{{/* works because $alert refers to the value of dot inside the first range */}}
There are {{ len $alert.Labels }}
{{ end }}
{{ end }}
```
## Range with index
You can get the index of each alert within a range by defining index and value variables at the start of the range:
```
{{ $num_alerts := len .Alerts }}
{{ range $index, $alert := .Alerts }}
This is alert {{ $index }} out of {{ $num_alerts }}
{{ end }}
```
## Define templates
You can define templates using `define` and the name of the template in double quotes. You should not define templates with the same name as other templates, including default templates such as `__subject`, `__text_values_list`, `__text_alert_list`, `default.title` and `default.message`. Where a template has been created with the same name as a default template, or a template in another message template, Grafana might use either template. Grafana does not prevent, or show an error message, when there are two or more templates with the same name.
```
{{ define "print_labels" }}
{{ end }}
```
## Execute templates
You can execute defined templates using `template`, the name of the template in double quotes, and the cursor that should be passed to the template:
```
{{ template "print_labels" . }}
```
## Pass data to templates
Within a template dot refers to the value that is passed to the template.
For example, if a template is passed a list of firing alerts then dot refers to that list of firing alerts:
```
{{ template "print_alerts" .Alerts }}
```
If the template is passed the sorted labels for an alert then dot refers to the list of sorted labels:
```
{{ template "print_labels" .SortedLabels }}
```
This is useful when writing reusable templates. For example, to print all alerts you might write the following:
```
{{ template "print_alerts" .Alerts }}
```
Then to print just the firing alerts you could write this:
```
{{ template "print_alerts" .Alerts.Firing }}
```
This works because both `.Alerts` and `.Alerts.Firing` is a list of alerts.
```
{{ define "print_alerts" }}
{{ range . }}
{{ template "print_labels" .SortedLabels }}
{{ end }}
{{ end }}
```
## Comments
You can add comments with `{{/*` and `*/}}`:
```
{{/* This is a comment */}}
```
To prevent comments from adding line breaks use:
```
{{- /* This is a comment with no leading or trailing line breaks */ -}}
```
## Indentation
You can use indentation, both tabs and spaces, and line breaks, to make templates more readable:
```
{{ range .Alerts }}
{{ range .Labels.SortedPairs }}
{{ .Name }} = {{ .Value }}
{{ end }}
{{ end }}
```
However, indentation in the template will also be present in the text. Next we will see how to remove it.
## Remove spaces and line breaks
In text/template use `{{-` and `-}}` to remove leading and trailing spaces and line breaks.
For example, when using indentation and line breaks to make a template more readable:
```
{{ range .Alerts }}
{{ range .Labels.SortedPairs }}
{{ .Name }} = {{ .Value }}
{{ end }}
{{ end }}
```
The indentation and line breaks will also be present in the text:
```
alertname = "Test"
grafana_folder = "Test alerts"
```
You can remove the indentation and line breaks from the text changing `}}` to `-}}` at the start of each range:
```
{{ range .Alerts -}}
{{ range .Labels.SortedPairs -}}
{{ .Name }} = {{ .Value }}
{{ end }}
{{ end }}
```
The indentation and line breaks in the template are now absent from the text:
```
alertname = "Test"
grafana_folder = "Test alerts"
```