docker run -d -p 3000:3000 grafana/grafana | Run with Docker |
brew install grafana | Install on macOS |
sudo apt-get install grafana | Install on Ubuntu |
grafana-server | Start server |
grafana-cli plugins install grafana-piechart-panel | Install plugin |
grafana-cli plugins list-remote | List available plugins |
Esc | Exit edit mode / Close modal |
Ctrl+S | Save dashboard |
E | Edit panel |
V | View panel fullscreen |
P S | Share panel |
D S | Dashboard settings |
Ctrl+F | Search dashboards |
Ctrl+H | Toggle all rows |
T Z | Zoom out time range |
T Left | Move time back |
T Right | Move time forward |
# /etc/grafana/provisioning/datasources/datasources.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: false
- name: Loki
type: loki
access: proxy
url: http://loki:3100
- name: InfluxDB
type: influxdb
access: proxy
url: http://influxdb:8086
database: mydb
user: admin
secureJsonData:
password: secret
- name: PostgreSQL
type: postgres
url: postgres:5432
database: grafana
user: grafana
secureJsonData:
password: secret
jsonData:
sslmode: disable # /etc/grafana/provisioning/dashboards/dashboards.yml
apiVersion: 1
providers:
- name: "Default"
orgId: 1
folder: ""
type: file
disableDeletion: false
updateIntervalSeconds: 10
options:
path: /var/lib/grafana/dashboards
foldersFromFilesStructure: true {
"dashboard": {
"title": "My Dashboard",
"tags": ["production"],
"timezone": "browser",
"refresh": "5s",
"time": {
"from": "now-6h",
"to": "now"
},
"panels": [
{
"id": 1,
"title": "CPU Usage",
"type": "graph",
"gridPos": { "x": 0, "y": 0, "w": 12, "h": 8 },
"targets": [
{
"expr": "100 - (avg(rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100)",
"legendFormat": "{{instance}}"
}
]
}
]
}
} # In Dashboard Settings > Variables
# Prometheus label values
Name: instance
Type: Query
Data source: Prometheus
Query: label_values(up, instance)
# Prometheus label values with filter
Query: label_values(up{job="$job"}, instance)
# Loki label values
Query: label_values({job="$job"}, level) # Custom static values
Name: environment
Type: Custom
Values: dev, staging, prod
# Or comma-separated
Values: dev : Development, staging : Staging, prod : Production # Auto interval based on time range
Name: interval
Type: Interval
Values: 1m, 5m, 10m, 30m, 1h, 6h, 12h, 1d
Auto option: enabled
Min interval: 1m # In queries
rate(http_requests_total{instance="$instance"}[$interval])
# Multiple selection
rate(http_requests_total{instance=~"$instance"}[$interval])
# In panel titles
CPU Usage - $instance
# Special variables
$__interval # Auto interval
$__interval_ms # Auto interval in ms
$__range # Time range
$__range_s # Time range in seconds
$__from # From timestamp (ms)
$__to # To timestamp (ms) # Alert rule structure
1. Query and condition
- Query: rate(http_errors_total[5m]) / rate(http_requests_total[5m])
- Condition: IS ABOVE 0.05
2. Evaluation behavior
- Evaluate every: 1m
- For: 5m (pending period)
3. Add details
- Rule name: High Error Rate
- Folder: Production
- Group: HTTP Alerts
- Summary: Error rate is {{ $values.A }}%
- Description: Check the application logs
4. Notifications
- Contact point: Slack, Email, PagerDuty, etc. # Available template variables in annotations
{{ $labels }} # All labels
{{ $labels.instance }} # Specific label
{{ $values }} # All values
{{ $values.A }} # Specific value (query refId)
{{ $value }} # Alert value
{{ humanize $value }} # Human readable value
{{ humanizePercentage $value }} # As percentage
{{ humanizeDuration $value }} # As duration # Custom template example
{{ define "slack.message" }}
{{ range .Alerts }}
*Alert:* {{ .Labels.alertname }}
*Severity:* {{ .Labels.severity }}
*Instance:* {{ .Labels.instance }}
*Summary:* {{ .Annotations.summary }}
*Value:* {{ .Values.A }}
{{ end }}
{{ end }} curl -H "Authorization: Bearer TOKEN" http://localhost:3000/api/org | Get current org |
curl -H "Authorization: Bearer TOKEN" http://localhost:3000/api/dashboards/db/my-dashboard | Get dashboard |
curl -H "Authorization: Bearer TOKEN" http://localhost:3000/api/search?query=cpu | Search dashboards |
curl -X POST -H "Content-Type: application/json" -d @dashboard.json http://localhost:3000/api/dashboards/db | Create dashboard |
curl -H "Authorization: Bearer TOKEN" http://localhost:3000/api/datasources | List data sources |
curl -H "Authorization: Bearer TOKEN" http://localhost:3000/api/alerts | List alerts |
[server]
http_port = 3000
domain = grafana.example.com
root_url = https://grafana.example.com/
[database]
type = postgres
host = localhost:5432
name = grafana
user = grafana
password = secret
[auth]
disable_login_form = false
disable_signout_menu = false
[auth.anonymous]
enabled = true
org_role = Viewer
[auth.github]
enabled = true
client_id = xxx
client_secret = xxx
allowed_organizations = my-org
[smtp]
enabled = true
host = smtp.gmail.com:587
user = alerts@example.com
password = secret
from_address = alerts@example.com
[log]
mode = console file
level = info