426 lines
11 KiB
Markdown
426 lines
11 KiB
Markdown
# Grafana Alerting - Detailed Reference
|
|
|
|
## Overview
|
|
|
|
Grafana Alerting is a unified alerting system for monitoring metrics and logs across multiple data sources. It fires notifications when conditions are breached.
|
|
|
|
Key capabilities:
|
|
- Query multiple data sources in a single alert rule
|
|
- Multi-dimensional alerts (one rule creates many alert instances)
|
|
- Flexible notification routing via policies
|
|
- Silences and mute timings for planned maintenance
|
|
- Alert history and state tracking
|
|
|
|
---
|
|
|
|
## Core Concepts
|
|
|
|
### Alert Rule
|
|
Defines what to monitor and when to fire. Contains: queries, a condition (threshold), an evaluation interval, and a pending period.
|
|
|
|
### Alert Instance
|
|
When a rule produces multi-dimensional data, it creates one alert instance per unique label combination. Example: an alert on `cpu_usage{host=~".*"}` creates one instance per host.
|
|
|
|
### Alert States
|
|
|
|
| State | Description |
|
|
|-------|-------------|
|
|
| **Normal** | Query running; condition not met |
|
|
| **Pending** | Condition met but pending period not yet elapsed |
|
|
| **Firing** | Condition met + pending period elapsed; notifications sent |
|
|
| **Resolved** | Previously firing alert returned to normal |
|
|
| **No Data** | Query returned no data (configurable behavior) |
|
|
| **Error** | Query failed with an error (configurable behavior) |
|
|
|
|
### Evaluation Group
|
|
Alert rules are organized into evaluation groups. All rules in a group share the same evaluation interval and are evaluated sequentially.
|
|
|
|
### Pending Period
|
|
How long the condition must be continuously met before firing.
|
|
- `0s` = fire immediately
|
|
- `5m` = must be in breach for 5 continuous minutes
|
|
|
|
### Keep Firing For
|
|
How long an alert continues firing after the condition resolves (prevents brief recovery from clearing the alert).
|
|
|
|
---
|
|
|
|
## Alert Rule Types
|
|
|
|
### Grafana-Managed Rules (Recommended)
|
|
- Stored in Grafana's database
|
|
- Can query any data source
|
|
- Support multi-dimensional alerting
|
|
- Support expressions (math, reduce, threshold)
|
|
|
|
### Data Source-Managed Rules (Prometheus/Mimir/Loki)
|
|
- Rules stored in the external system
|
|
- Evaluated by the external system
|
|
- Grafana provides UI to manage them
|
|
- Useful when migrating from Prometheus alerting
|
|
|
|
---
|
|
|
|
## Creating Grafana-Managed Alert Rules
|
|
|
|
Navigate to: **Alerting > Alert rules > New alert rule**
|
|
|
|
### Step 1: Define query and condition
|
|
|
|
Write one or more queries (labeled A, B, C...).
|
|
|
|
Example with Prometheus:
|
|
```promql
|
|
# Query A: CPU usage per host
|
|
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
|
|
```
|
|
|
|
Expression types you can add after queries:
|
|
- **Math**: `$A > 80` or `($A + $B) / 2`
|
|
- **Reduce**: Collapse time series to single value (Last, Mean, Sum, Max, Min)
|
|
- **Resample**: Change time resolution
|
|
- **Classic conditions**: Multiple threshold conditions with AND/OR
|
|
- **Threshold**: Set the firing threshold
|
|
|
|
### Step 2: Set evaluation behavior
|
|
|
|
| Setting | Description |
|
|
|---------|-------------|
|
|
| Folder | Organize rules; folder is the RBAC boundary |
|
|
| Evaluation group | Group name (all rules share this group's interval) |
|
|
| Evaluation interval | How often the rule is evaluated (e.g., 1m) |
|
|
| Pending period | How long condition must hold before firing (e.g., 5m) |
|
|
| Keep firing for | How long alert stays firing after recovery |
|
|
|
|
### Step 3: Configure labels and notifications
|
|
|
|
**Labels** - Key-value pairs attached to alert instances. Used for routing and grouping:
|
|
```
|
|
severity=critical
|
|
team=infrastructure
|
|
service=database
|
|
environment=production
|
|
```
|
|
|
|
**Annotations** - Context included in notification messages:
|
|
```
|
|
Summary: CPU usage above 80% on {{ $labels.instance }}
|
|
Description: CPU usage is {{ $values.A.Value | humanize }}% on {{ $labels.instance }}
|
|
Runbook URL: https://runbooks.company.com/cpu-high
|
|
```
|
|
|
|
**Notification settings**:
|
|
- Set a **Contact point** to send directly, bypassing the routing policy tree
|
|
- Or leave empty to use the notification policy routing tree
|
|
|
|
### Step 4: No data and error handling
|
|
|
|
| Situation | Options |
|
|
|-----------|---------|
|
|
| No data | Alerting, OK, No Data state, Keep last state |
|
|
| Query error | Alerting, OK, Error state, Keep last state |
|
|
|
|
---
|
|
|
|
## Contact Points
|
|
|
|
Contact points are notification destinations.
|
|
|
|
Navigate to: **Alerting > Contact points**
|
|
|
|
### Supported integrations
|
|
|
|
| Integration | Notes |
|
|
|-------------|-------|
|
|
| Email | Requires SMTP config in grafana.ini |
|
|
| Slack | Webhook URL or API token + channel |
|
|
| PagerDuty | Integration key |
|
|
| OpsGenie | API key |
|
|
| VictorOps (Splunk) | API key |
|
|
| Microsoft Teams | Incoming webhook URL |
|
|
| Discord | Webhook URL |
|
|
| Telegram | Bot token + chat ID |
|
|
| Webhook | HTTP POST to custom URL |
|
|
| Alertmanager | Forward to external Alertmanager |
|
|
| Pushover | User key + API token |
|
|
| LINE | LINE Notify token |
|
|
|
|
### Email configuration in grafana.ini
|
|
```ini
|
|
[smtp]
|
|
enabled = true
|
|
host = smtp.gmail.com:587
|
|
user = alerts@company.com
|
|
password = app-password
|
|
from_address = alerts@company.com
|
|
from_name = Grafana Alerts
|
|
```
|
|
|
|
### Webhook payload format
|
|
Grafana POSTs a JSON payload to webhook endpoints:
|
|
```json
|
|
{
|
|
"receiver": "webhook-receiver",
|
|
"status": "firing",
|
|
"alerts": [
|
|
{
|
|
"status": "firing",
|
|
"labels": { "alertname": "HighCPU", "instance": "server1" },
|
|
"annotations": { "summary": "CPU above 80%" },
|
|
"startsAt": "2024-01-15T10:00:00Z",
|
|
"generatorURL": "http://grafana/alerting/..."
|
|
}
|
|
],
|
|
"groupLabels": { "alertname": "HighCPU" },
|
|
"externalURL": "http://grafana"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Notification Policies
|
|
|
|
Notification policies route alerts to contact points based on label matchers.
|
|
|
|
Navigate to: **Alerting > Notification policies**
|
|
|
|
### Default policy
|
|
The root policy - all alerts reach here if no specific policy matches.
|
|
|
|
### Child policies
|
|
Add policies that match specific labels:
|
|
```
|
|
Match labels:
|
|
severity = critical -> contact: pagerduty
|
|
team = infrastructure -> contact: slack-infra
|
|
environment = staging -> contact: email-dev
|
|
```
|
|
|
|
### Policy settings
|
|
|
|
| Setting | Description |
|
|
|---------|-------------|
|
|
| Contact point | Where to send matching alerts |
|
|
| Continue matching | If true, also evaluate subsequent sibling policies |
|
|
| Group by | Labels used for batching alerts into single notifications |
|
|
| Group wait | Wait before sending first notification for a new group (default: 30s) |
|
|
| Group interval | Wait before sending updates for an existing group (default: 5m) |
|
|
| Repeat interval | Wait before re-sending for still-firing alerts (default: 4h) |
|
|
|
|
### Grouping
|
|
When multiple alerts have the same "group by" labels, they are batched into a single notification. This prevents notification storms.
|
|
|
|
Example:
|
|
- 50 hosts alert on HighCPU simultaneously
|
|
- Group by: `[alertname, datacenter]`
|
|
- Result: 1 notification per datacenter containing all affected hosts
|
|
|
|
---
|
|
|
|
## Notification Templates
|
|
|
|
Customize notification message format using Go templating.
|
|
|
|
Navigate to: **Alerting > Contact points > Notification templates**
|
|
|
|
### Built-in variables
|
|
```
|
|
{{ $labels }} # Alert labels as map
|
|
{{ $values }} # Query values map
|
|
{{ $labels.instance }} # Specific label value
|
|
{{ $values.A.Value }} # Specific query value
|
|
{{ $status }} # firing or resolved
|
|
{{ $startsAt }} # When alert started firing
|
|
```
|
|
|
|
### Example Slack template
|
|
```
|
|
{{ define "slack_message" }}
|
|
{{ if eq .Status "firing" }}:red_circle:{{ else }}:large_green_circle:{{ end }} *{{ .Labels.alertname }}*
|
|
|
|
*Status:* {{ .Status }}
|
|
*Severity:* {{ .Labels.severity }}
|
|
|
|
{{ range .Alerts }}
|
|
*Instance:* {{ .Labels.instance }}
|
|
*Value:* {{ .Values.A.Value | humanize }}
|
|
*Summary:* {{ .Annotations.summary }}
|
|
{{ end }}
|
|
{{ end }}
|
|
```
|
|
|
|
### Humanize functions
|
|
```
|
|
{{ $value | humanize }} # "12.3k"
|
|
{{ $value | humanize1024 }} # "12.3Ki"
|
|
{{ $value | humanizeBytes }} # "12.3 kB"
|
|
{{ $value | humanizeDuration }} # "3h 2m 1s"
|
|
{{ $value | humanizePercentage }} # "12.3%"
|
|
```
|
|
|
|
---
|
|
|
|
## Silences
|
|
|
|
Silences temporarily suppress alert notifications without stopping alert evaluation.
|
|
|
|
Navigate to: **Alerting > Silences**
|
|
|
|
### Create a silence
|
|
1. Click **Add silence**
|
|
2. Set start time and end time (or duration)
|
|
3. Add label matchers:
|
|
```
|
|
alertname = HighCPU
|
|
instance =~ ".*staging.*" # Regex match
|
|
severity != critical # Negative match
|
|
```
|
|
4. Add a comment explaining why
|
|
5. Save
|
|
|
|
### Use cases
|
|
- Planned maintenance windows
|
|
- Known issues being investigated
|
|
- Silencing noisy alerts during deploys
|
|
|
|
From a firing alert detail view: click **Silence** to pre-populate label matchers.
|
|
|
|
---
|
|
|
|
## Mute Timings
|
|
|
|
Recurring schedules when notifications are suppressed (unlike silences which are one-time).
|
|
|
|
Navigate to: **Alerting > Mute timings**
|
|
|
|
### Example mute timings
|
|
```
|
|
Name: no-alerts-weekends
|
|
Weekdays: Saturday, Sunday
|
|
|
|
Name: business-hours-only
|
|
Weekdays: Monday-Friday
|
|
Times: 09:00-17:00
|
|
```
|
|
|
|
Attach to notification policies in the policy settings.
|
|
|
|
---
|
|
|
|
## RBAC for Alerting
|
|
|
|
Default permissions by role:
|
|
|
|
| Action | Viewer | Editor | Admin |
|
|
|--------|--------|--------|-------|
|
|
| View alert rules | Yes | Yes | Yes |
|
|
| Create/edit alert rules | No | Yes | Yes |
|
|
| Delete alert rules | No | No | Yes |
|
|
| Manage contact points | No | No | Yes |
|
|
| Manage notification policies | No | No | Yes |
|
|
| Create silences | No | Yes | Yes |
|
|
|
|
---
|
|
|
|
## grafana.ini Alerting Configuration
|
|
|
|
```ini
|
|
[unified_alerting]
|
|
# Enable unified alerting (default: true since Grafana 9)
|
|
enabled = true
|
|
|
|
# Maximum alert instances a single rule can produce
|
|
max_annotations_to_keep = 100
|
|
|
|
# Evaluation timeout
|
|
evaluation_timeout = 30s
|
|
|
|
# Minimum evaluation interval (prevent too-frequent evaluation)
|
|
min_interval = 10s
|
|
|
|
[smtp]
|
|
# Required for email contact points
|
|
enabled = true
|
|
host = smtp.example.com:587
|
|
```
|
|
|
|
---
|
|
|
|
## Common Alert Rule Examples
|
|
|
|
### CPU usage above threshold
|
|
```promql
|
|
# Query A
|
|
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
|
|
# Threshold: A > 80
|
|
# Pending: 5m
|
|
# Labels: severity=warning
|
|
```
|
|
|
|
### Memory usage
|
|
```promql
|
|
# Query A
|
|
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
|
|
# Threshold: A > 90
|
|
```
|
|
|
|
### HTTP error rate
|
|
```promql
|
|
# Query A: error requests
|
|
sum(rate(http_requests_total{status=~"5.."}[5m]))
|
|
# Query B: total requests
|
|
sum(rate(http_requests_total[5m]))
|
|
# Expression C (Math): $A / $B * 100
|
|
# Threshold: C > 5
|
|
```
|
|
|
|
### Disk space
|
|
```promql
|
|
# Query A
|
|
(1 - (node_filesystem_free_bytes{fstype!="tmpfs"} / node_filesystem_size_bytes{fstype!="tmpfs"})) * 100
|
|
# Threshold: A > 85
|
|
```
|
|
|
|
### Service down (no data = firing)
|
|
```promql
|
|
# Query A
|
|
up{job="my-service"}
|
|
# Threshold: A < 1
|
|
# No data handling: Alerting (treat absence as firing)
|
|
```
|
|
|
|
### Loki log error rate
|
|
```logql
|
|
# Query A
|
|
sum(rate({job="api"} |= "ERROR" [5m]))
|
|
# Threshold: A > 10
|
|
```
|
|
|
|
---
|
|
|
|
## Connecting Alerts to Dashboards
|
|
|
|
### Create alert from panel
|
|
1. Open panel editor
|
|
2. Click **Alert** tab
|
|
3. Click **Create alert rule from this panel**
|
|
4. Pre-populates query from the panel
|
|
|
|
### Link alert to dashboard panel
|
|
In the alert rule definition, set **Dashboard** and **Panel** to link to a specific visualization. The alert state badge appears on the panel and clicking it goes to the alert rule.
|
|
|
|
---
|
|
|
|
## High Availability (HA) Alerting
|
|
|
|
```ini
|
|
[unified_alerting]
|
|
ha_peers = grafana-1:9094,grafana-2:9094,grafana-3:9094
|
|
ha_advertise_address = ${POD_IP}:9094
|
|
ha_peer_timeout = 15s
|
|
ha_gossip_interval = 200ms
|
|
ha_push_pull_interval = 60s
|
|
```
|
|
|
|
Multiple Grafana instances share state to avoid duplicate notifications.
|