仪表板设计
仪表板是 Grafana 中组织的可视化页面,包含多个面板和配置。
仪表板结构
基础结构
json
{
"title": "Application Monitoring",
"uid": "app-monitoring",
"tags": ["app", "monitoring"],
"timezone": "browser",
"schemaVersion": 38,
"version": 1,
"panels": [],
"variables": [],
"annotations": []
}网格布局
┌─────────────────────────────────────────────────────┐
│ Title: Application Monitoring Dashboard │
├────────────┬────────────┬────────────┬─────────────┤
│ Panel 1 │ Panel 2 │ Panel 3 │ Panel 4 │
│ (QPS) │ (Latency) │ (Errors) │ (Status) │
│ 6x4 │ 6x4 │ 6x4 │ 6x4 │
├────────────┴────────────┴────────────┴─────────────┤
│ Panel 5 (Time Series - CPU/Memory) │
│ 24x8 │
├─────────────────────────────────────────────────────┤
│ Panel 6 (Table - Service Details) │
│ 24x6 │
└─────────────────────────────────────────────────────┘gridPos 配置
json
{
"gridPos": {
"x": 0, // 横向位置 (0-23)
"y": 0, // 纵向位置
"w": 12, // 宽度 (1-24)
"h": 8 // 高度
}
}变量系统
查询变量
json
{
"name": "service",
"type": "query",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"definition": "label_values(up, job)",
"query": {
"query": "label_values(up, job)",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"multi": true,
"includeAll": true,
"allValue": ".+",
"sort": 1
}自定义变量
json
{
"name": "interval",
"type": "custom",
"options": [
{"text": "1m", "value": "1m"},
{"text": "5m", "value": "5m"},
{"text": "15m", "value": "15m"},
{"text": "1h", "value": "1h"}
],
"current": {
"text": "5m",
"value": "5m"
}
}文本框变量
json
{
"name": "threshold",
"type": "textbox",
"current": {
"text": "80",
"value": "80"
}
}常量变量
json
{
"name": "app_version",
"type": "constant",
"current": {
"text": "v1.0.0",
"value": "v1.0.0"
}
}变量使用
promql
# 单选变量
sum(rate(http_requests_total{service="$service"}[5m]))
# 多选变量
sum(rate(http_requests_total{service=~"$service"}[5m]))
# 排除变量
sum(rate(http_requests_total{service!~"$service"}[5m]))
# 使用间隔变量
rate(http_requests_total[$interval])
# 使用阈值变量
http_requests_total > $threshold注解
添加注解
json
{
"list": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"enable": true,
"expr": "changes(deploy_event_total[1h]) > 0",
"iconColor": "blue",
"name": "Deployments",
"step": "1h",
"tagKeys": "event,type",
"titleFormat": "{{ event }}"
}
]
}查询注解
bash
# 通过 API 添加注解
curl -X POST http://admin:admin@localhost:3000/api/annotations \
-H "Content-Type: application/json" \
-d '{
"dashboardId": 1,
"time": 1612345678000,
"timeEnd": 1612345678000,
"tags": ["deploy", "production"],
"text": "Deployed version v1.2.3"
}'仪表板链接
内部链接
json
{
"links": [
{
"title": "Go to Infrastructure Dashboard",
"type": "link",
"url": "/d/infrastructure",
"icon": "external link",
"asDropdown": false,
"includeVars": true,
"keepTime": true,
"targetBlank": false
}
]
}外部链接
json
{
"links": [
{
"title": "View Logs",
"type": "link",
"url": "http://loki:3100/logs",
"icon": "external link",
"asDropdown": false,
"includeVars": true,
"keepTime": false,
"targetBlank": true
}
]
}仪表板配置文件
provisioning 配置
yaml
# /etc/grafana/provisioning/dashboards/dashboard.yml
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
folderUid: ''
type: file
disableDeletion: false
updateIntervalSeconds: 30
allowUiUpdates: true
options:
path: /var/lib/grafana/dashboards仪表板 JSON 文件
json
{
"annotations": {
"list": []
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 1,
"id": 1,
"links": [],
"liveNow": false,
"panels": [
{
"type": "timeseries",
"title": "HTTP QPS",
"gridPos": {
"x": 0,
"y": 0,
"w": 12,
"h": 8
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"expr": "sum(rate(http_requests_total[5m]))",
"refId": "A"
}
]
}
],
"refresh": "5s",
"schemaVersion": 38,
"tags": ["monitoring", "app"],
"templating": {
"list": []
},
"time": {
"from": "now-1h",
"to": "now"
},
"timepicker": {},
"timezone": "browser",
"title": "Application Monitoring",
"uid": "app-monitoring",
"version": 1
}仪表板 API
创建仪表板
bash
curl -X POST http://admin:admin@localhost:3000/api/dashboards/db \
-H "Content-Type: application/json" \
-d '{
"dashboard": {
"title": "My Dashboard",
"uid": "my-dashboard",
"panels": []
},
"overwrite": false
}'更新仪表板
bash
curl -X PUT http://admin:admin@localhost:3000/api/dashboards/db \
-H "Content-Type: application/json" \
-d '{
"dashboard": {
"id": 1,
"title": "Updated Dashboard",
"uid": "my-dashboard",
"version": 2,
"panels": []
},
"overwrite": true
}'查询仪表板
bash
# 列出所有仪表板
curl http://admin:admin@localhost:3000/api/search?type=dash-db
# 获取仪表板详情
curl http://admin:admin@localhost:3000/api/dashboards/uid/my-dashboard
# 删除仪表板
curl -X DELETE http://admin:admin@localhost:3000/api/dashboards/uid/my-dashboard导入导出
导出仪表板
- 打开仪表板
- 点击 Share → Export
- 选择导出格式(JSON)
- 下载文件
导入仪表板
- 导航到 Dashboards → Import
- 上传 JSON 文件或输入 ID
- 配置数据源映射
- 点击 Import
通过 API 导入
bash
curl -X POST http://admin:admin@localhost:3000/api/dashboards/import \
-H "Content-Type: application/json" \
-d @dashboard.json仪表板最佳实践
布局原则
- 层次结构:重要信息在顶部,细节在底部
- 逻辑分组:相关指标放在一起
- 响应式设计:考虑不同屏幕尺寸
- 避免拥挤:每个仪表板不超过 20 个面板
设计模式
三段式布局
顶部: 关键指标 (QPS, 错误率, 响应时间)
中间: 时间序列 (详细趋势图)
底部: 表格/详情 (服务列表、日志)分组布局
应用监控组: QPS, 错误率, 响应时间
资源监控组: CPU, 内存, 磁盘
网络监控组: 流量, 连接数, 延迟变量使用
yaml
# 推荐变量
variables:
- service: 服务选择
- instance: 实例选择
- interval: 时间间隔
- datasource: 数据源选择刷新策略
yaml
# 推荐刷新间隔
refresh_intervals:
- 5s: 实时监控
- 10s: 近实时监控
- 30s: 一般监控
- 1m: 离线分析
- 5m: 趋势分析标签使用
yaml
# 推荐标签
tags:
- app: 应用监控
- infra: 基础设施
- business: 业务监控
- security: 安全监控仪表板模板
应用监控仪表板
json
{
"title": "Application Monitoring",
"panels": [
{
"type": "stat",
"title": "Total QPS",
"gridPos": {"x": 0, "y": 0, "w": 6, "h": 4},
"targets": [
{"expr": "sum(rate(http_requests_total[5m]))"}
]
},
{
"type": "stat",
"title": "Error Rate",
"gridPos": {"x": 6, "y": 0, "w": 6, "h": 4},
"targets": [
{"expr": "sum(rate(http_requests_total{status=~\"5..\"}[5m])) / sum(rate(http_requests_total[5m])) * 100"}
]
},
{
"type": "timeseries",
"title": "Request Rate by Service",
"gridPos": {"x": 0, "y": 4, "w": 24, "h": 8},
"targets": [
{"expr": "sum(rate(http_requests_total[5m])) by (service)", "legendFormat": "{{service}}"}
]
}
]
}资源监控仪表板
json
{
"title": "Infrastructure Monitoring",
"panels": [
{
"type": "gauge",
"title": "CPU Usage",
"gridPos": {"x": 0, "y": 0, "w": 8, "h": 6},
"targets": [
{"expr": "100 - avg(irate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100"}
]
},
{
"type": "gauge",
"title": "Memory Usage",
"gridPos": {"x": 8, "y": 0, "w": 8, "h": 6},
"targets": [
{"expr": "(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100"}
]
},
{
"type": "gauge",
"title": "Disk Usage",
"gridPos": {"x": 16, "y": 0, "w": 8, "h": 6},
"targets": [
{"expr": "(node_filesystem_size_bytes - node_filesystem_free_bytes) / node_filesystem_size_bytes * 100"}
]
}
]
}