Contact points and notification policies

Grafana · Practical · 12 min

Alerts are only as good as who receives them and when; routing decides whether a page is useful or noise.

A contact point is a named destination with one or more integrations: email, Slack, Microsoft Teams, PagerDuty, Opsgenie, Discord, Telegram, webhook, OnCall, and others. Each has its own settings and a Test button that sends a sample alert. The message content comes from notification templates, Go templates you can customise, for example a Slack title that lists {{ .CommonLabels.alertname }} and a body that loops over .Alerts with their annotations and silence links.

The notification policy tree decides which contact point gets which alerts. The default policy at the root catches everything; child policies add label matchers (team = api, severity =~ "page|critical"). Evaluation walks the tree depth-first and stops at the first matching policy, unless that policy sets continue matching, which lets an alert hit several siblings (a Slack channel and PagerDuty). Each policy can override:

  • Group by labels (default grafana_folder, alertname): alerts with the same values are bundled into one notification.
  • Group wait (30s): how long to collect alerts before the first notification of a new group.
  • Group interval (5m): minimum time between updates for a changed group.
  • Repeat interval (4h): how often an unchanged, still-firing group is re-sent.

Mute timings are schedules (weekends, nightly maintenance) attached to a policy; during them notifications are held, not dropped. Silences are ad hoc: label matchers plus a duration, created from a firing alert with one click, and they only stop notifications, the rule keeps evaluating and the alert shows as suppressed.

An alert rule can also name a contact point directly (simplified routing), bypassing the tree, which is handy for small teams. Both contact points and policies can be exported as YAML or Terraform and provisioned.

Example

# Notification policy tree (Alerting > Notification policies), exported form
apiVersion: 1
policies:
  - orgId: 1
    receiver: default-email            # root: catches everything else
    group_by: [grafana_folder, alertname]
    group_wait: 30s
    group_interval: 5m
    repeat_interval: 4h
    routes:
      - receiver: api-pagerduty
        object_matchers:
          - [team, =, api]
          - [severity, =, page]
        continue: true                 # also try the next sibling
      - receiver: api-slack
        object_matchers:
          - [team, =, api]
        mute_time_intervals: [weekends]
        repeat_interval: 24h

Remember

  • Contact points send; policies match labels to contact points, first match wins unless continue is set
  • Group by, group wait, group interval and repeat interval control bundling and repetition
  • Mute timings are scheduled, silences are ad hoc; both only suppress notifications

Watch out for

  • A child policy with continue off placed above a more specific one, so the specific policy never receives anything.

Check yourself

  1. An alert with team=api, severity=page should go to both PagerDuty and the team's Slack channel. What makes that possible?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: grafana.com/docs/grafana/latest/alerting/configure-notifications/create-notification-policy/