Grafana Alerting Notification Templates Prompt
Author custom Grafana alert notification message templates with Go templating for contact points (Slack, email, PagerDuty).
- Target user
- SREs and on-call engineers customizing alert payloads
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT
The prompt
You are a senior SRE who builds Grafana unified-alerting notification templates using Go text/template so on-call gets actionable, deduplicated messages.
I will provide:
- The contact point type (Slack, email, PagerDuty, webhook)
- The alert rules and label/annotation schema
- Current message (if any) and what is missing
Your job:
1. **Template scope**: define a named template with `{{ define "myorg.title" }}` and reference it from the contact point's Title/Message fields via `{{ template "myorg.title" . }}`.
2. **Iterate alerts**: loop `{{ range .Alerts }}` and split firing vs resolved with `.Alerts.Firing` and `.Alerts.Resolved`; show counts with `{{ len .Alerts.Firing }}`.
3. **Surface context**: print `{{ .Labels.alertname }}`, `{{ .Labels.severity }}`, `{{ .Annotations.summary }}`, `{{ .Annotations.description }}`, and the runbook via `{{ .Annotations.runbook_url }}`.
4. **Add links**: include `{{ .GeneratorURL }}`, `{{ .SilenceURL }}`, `{{ .DashboardURL }}`, and `{{ .PanelURL }}` for one-click triage.
5. **Group cleanly**: use `{{ .GroupLabels }}` and `{{ .CommonLabels }}` for the title; avoid dumping every label. Sort with `{{ .Labels.SortedPairs }}`.
6. **Format per channel**: Slack supports mrkdwn (`*bold*`, `<url|text>`); email supports HTML; keep PagerDuty summary under length limits.
7. **Guard emptiness**: wrap optional fields in `{{ if .Annotations.runbook_url }}...{{ end }}` so missing annotations do not render blank lines.
8. **Test**: preview under Alerting > Contact points > template preview, or fire a test notification before shipping.
Mark DESTRUCTIVE: editing a shared org-wide template used by many contact points, or removing a `define` block other contact points reference (silent broken notifications).
---
Contact point: [DESCRIBE]
Alert labels/annotations: [DESCRIBE]
Current message: [DESCRIBE]
Why this prompt works
Grafana’s unified alerting exposes a rich data model (.Alerts, .GroupLabels, .CommonLabels, annotation fields) to Go templates, but the docs scatter the field names across pages. This prompt forces a channel-aware template that separates firing from resolved, surfaces runbook and silence links, and guards against missing fields — the difference between an actionable page and a wall of labels.
How to use it
- Name the contact point type so formatting (mrkdwn vs HTML) is correct.
- Paste your label/annotation schema so templates reference real keys.
- Preview in the UI before saving to a live contact point.
- Version the template in provisioning YAML once validated.
Useful commands
# List contact points and templates via API
curl -s -H "Authorization: Bearer $TOKEN" \
http://localhost:3000/api/v1/provisioning/templates | jq
# Create/update a notification template group
curl -X PUT -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:3000/api/v1/provisioning/templates/myorg-slack \
-d '{"name":"myorg-slack","template":"{{ define \"myorg.slack.title\" }}...{{ end }}"}'
# Trigger a test notification for a contact point
curl -X POST -H "Authorization: Bearer $TOKEN" \
http://localhost:3000/api/alertmanager/grafana/config/api/v1/receivers/test
Relevant grafana.ini keys:
[server]
root_url = https://grafana.example.com
[unified_alerting]
enabled = true
Example config
Provisioned template plus contact point reference:
apiVersion: 1
templates:
- orgId: 1
name: myorg-slack
template: |
{{ define "myorg.slack.title" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }}{{ end }}
{{ define "myorg.slack.body" }}
{{ range .Alerts.Firing }}
*{{ .Labels.severity | toUpper }}* {{ .Annotations.summary }}
{{ if .Annotations.runbook_url }}<{{ .Annotations.runbook_url }}|Runbook> · {{ end }}<{{ .SilenceURL }}|Silence> · <{{ .DashboardURL }}|Dashboard>
{{ end }}{{ end }}
contactPoints:
- orgId: 1
name: slack-critical
receivers:
- uid: slack-crit-1
type: slack
settings:
recipient: "#alerts-critical"
title: '{{ template "myorg.slack.title" . }}'
text: '{{ template "myorg.slack.body" . }}'
Common findings this catches
- Wall-of-labels messages → switch to
SortedPairsand select fields. - Broken links →
root_urlmissing soSilenceURL/DashboardURL404. - Blank lines → unguarded optional annotations.
- Resolved spam → separate
.Alerts.Resolvedhandling or suppress. - Truncated PagerDuty pages → summary too long.
- HTML in Slack → wrong channel formatting.
When to escalate
- Org-wide shared templates touched by many teams — coordinate changes.
- Compliance review of what leaves via external channels — security.
- Alert routing/grouping redesign — alerting platform owner.
Related prompts
-
Grafana Alert Silences and Mute Timings Prompt
Suppress Grafana alert noise during maintenance and off-hours using silences and mute timings without dropping real incidents.
-
Grafana Incident Timeline Dashboard Prompt
Build a single-pane incident timeline dashboard in Grafana correlating annotations, deploys, alerts, and key signals on one shared time axis.
-
Grafana PagerDuty/Opsgenie Contact Point Prompt
Configure Grafana Alerting contact points for PagerDuty and Opsgenie with notification policies, routing by label, and severity mapping.