Grafana’s alert notifications are surprisingly flexible, and you can actually embed rich, interactive dashboards directly into your alerts, not just static images.

Let’s say you have a Prometheus data source and you’ve set up an alert rule that triggers when your web server’s HTTP 5xx error rate exceeds 1%.

Here’s a typical alert rule in Grafana:

apiVersion: 1
datasources:
  - name: Prometheus
    type: prometheus
    url: http://prometheus.example.com:9090
    access: proxy
    isDefault: true
    jsonData:
      httpMethod: GET
      manageAlerts: true
  - name: Grafana
    type: grafana
    url: http://grafana.example.com:3000
    access: proxy
    isDefault: true

# Example alert rule
# In Grafana UI, this would be under Alerting -> Alert rules
# The rule below is a conceptual representation, actual creation is via UI or API.

# Alert rule definition (conceptual)
# Rule Name: High HTTP 5xx Errors
# Query: sum(rate(http_requests_total{status=~"5..", job="my-web-server"}[5m])) by (job) / sum(rate(http_requests_total{job="my-web-server"}[5m])) * 100
# Condition: > 1
# Evaluation interval: 1m
# For: 5m

# Notification channel setup (conceptual)
# Channel Name: WebOps Slack
# Type: Slack
# Settings:
#   - recipient: "#webops-alerts"

#   - message: "High 5xx errors detected on {{ $labels.job }}! Dashboard: {{ .URL }}"

When this alert fires, instead of just getting a text message, you can configure your notification channel to include a link that, when clicked, opens the relevant dashboard in Grafana, pre-filtered or focused on the problematic time range.

The magic happens in the notification template. Grafana uses Go templating for this. For a Slack notification, you might configure it like this in the Grafana UI (Alerting -> Notification channels -> your channel -> Edit):

Under "Message" or "Advanced options," you’d add something like this to your message body:

<p>

  <b>Alert:</b> {{ .Title }}<br>


  <b>Status:</b> {{ .Status | toUpper }}<br>


  <b>Severity:</b> {{ .Labels.severity }}<br>


  <b>Details:</b> {{ .Annotations.summary }}<br>


  <b>URL:</b> <a href="{{ .URL }}">{{ .URL }}</a><br>


  <b>Dashboard Link:</b> <a href="{{ .DashboardURL }}">View Dashboard</a>

</p>

When the alert triggers, the {{ .URL }} variable will contain a link to the alert rule itself, while {{ .DashboardURL }} will link directly to the dashboard associated with that alert, often pre-filtered to the time range of the alert. This is incredibly powerful for quick diagnosis.

Here’s how it works internally:

  1. Alerting Engine: Grafana’s alerting engine evaluates your alert rules against your data sources.
  2. State Change: When an alert transitions to a state like Firing, it triggers a notification.
  3. Templating: Before sending the notification, Grafana processes the message template. It injects context variables like .Title, .Status, .Labels, .Annotations, .URL (link to the alert rule), and crucially, .DashboardURL.
  4. DashboardURL Generation: The DashboardURL variable is dynamically generated. Grafana knows which dashboard is associated with the alert rule (you link them when creating the rule) and the alert’s time range. It constructs a URL that points to that dashboard, including parameters for the from and to timestamps of the alert.
  5. Notification Delivery: The templated message, now containing the actual URLs, is sent to your configured notification channel (Slack, PagerDuty, webhook, etc.).

The most surprising thing is how easily you can pass alert context directly into dashboard URLs, effectively creating a "drill-down" from the alert itself to the relevant visualization without manual intervention. For instance, you can even append custom URL parameters to the DashboardURL in your template if you want to highlight specific panels or variables on the dashboard.

Let’s say you want to specifically highlight the job label that triggered the alert on your dashboard. You could modify the template like this:

<p>

  <b>Alert:</b> {{ .Title }}<br>


  <b>Status:</b> {{ .Status | toUpper }}<br>


  <b>Details:</b> {{ .Annotations.summary }}<br>


  <b>Dashboard Link:</b> <a href="{{ .DashboardURL }}&var-job={{ urlquery .Labels.job }}">View Dashboard (Filtered by {{ .Labels.job }})</a>

</p>

This adds &var-job=<the-alerting-job-name> to the dashboard URL, assuming your dashboard has a template variable named job.

This mechanism allows you to build a seamless workflow from alert detection to root cause analysis directly within your observability platform.

The next step is to explore how to embed custom visualizations or even full dashboard snapshots as images directly within the notification payload, which requires different integrations and often external tools.

Want structured learning?

Take the full Grafana course →