Skip to content

TiDB 自定义监控开发

TiDB 提供了完善的监控体系,基于 Prometheus 和 Grafana。除了内置的监控指标外,用户还可以开发自定义监控,满足特定的业务需求。本文档介绍 TiDB 自定义监控的开发方法,包括 Prometheus 指标开发、Grafana 仪表盘开发和监控插件开发等内容。

监控系统架构

1. 基本架构

TiDB 监控系统的基本架构包括:

  • 指标采集层:TiDB、PD、TiKV 等组件暴露 Prometheus 格式的指标
  • 指标存储层:Prometheus 负责存储指标数据
  • 指标展示层:Grafana 负责展示监控数据
  • 告警系统:Prometheus Alertmanager 负责处理告警

2. 指标类型

Prometheus 支持以下指标类型:

  • Counter:单调递增的计数器,如请求数、错误数等
  • Gauge:可以增减的仪表盘,如 CPU 使用率、内存使用率等
  • Histogram:直方图,用于统计分布情况,如请求延迟分布
  • Summary:摘要,用于统计分位数,如请求延迟的 P50、P95、P99 等

自定义 Prometheus 指标开发

1. 在 TiDB 中添加自定义指标

TiDB 提供了 Prometheus 客户端库,可以方便地添加自定义指标。

1.1 添加指标定义

在 TiDB 代码中添加指标定义:

go
// 导入 Prometheus 客户端库
import (
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promauto"
)

// 定义指标
var (
    // 定义一个 Counter 类型的指标
    customRequestsTotal = promauto.NewCounter(
        prometheus.CounterOpts{
            Name: "tidb_custom_requests_total",
            Help: "The total number of custom requests",
            Labels: prometheus.Labels{
                "type": "custom",
            },
        },
    )

    // 定义一个 Gauge 类型的指标
    customGauge = promauto.NewGauge(
        prometheus.GaugeOpts{
            Name: "tidb_custom_gauge",
            Help: "A custom gauge metric",
        },
    )

    // 定义一个 Histogram 类型的指标
    customHistogram = promauto.NewHistogram(
        prometheus.HistogramOpts{
            Name:    "tidb_custom_request_duration_seconds",
            Help:    "The duration of custom requests in seconds",
            Buckets: prometheus.DefBuckets,
        },
    )
)

1.2 更新指标值

在代码中更新指标值:

go
// 增加 Counter 指标
customRequestsTotal.Inc()

// 增加指定值
customRequestsTotal.Add(5)

// 更新 Gauge 指标
customGauge.Set(0.5)
customGauge.Inc()
customGauge.Dec()

// 记录 Histogram 指标
startTime := time.Now()
// 执行操作
elapsed := time.Since(startTime)
customHistogram.Observe(elapsed.Seconds())

2. 开发独立的监控 exporter

对于无法直接修改 TiDB 代码的场景,可以开发独立的监控 exporter,定期采集自定义指标并暴露给 Prometheus。

2.1 使用 Go 开发 exporter

使用 Prometheus 客户端库开发 exporter:

go
package main

import (
    "log"
    "net/http"
    "time"

    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promauto"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

// 定义指标
var (
    customMetric = promauto.NewGaugeVec(
        prometheus.GaugeOpts{
            Name: "tidb_custom_metric",
            Help: "A custom metric for TiDB",
        },
        []string{"label1", "label2"},
    )
)

func main() {
    // 定期更新指标
    go func() {
        for {
            // 模拟采集指标
            customMetric.WithLabelValues("value1", "value2").Set(1.0)
            time.Sleep(10 * time.Second)
        }
    }()

    // 暴露指标端点
    http.Handle("/metrics", promhttp.Handler())
    log.Fatal(http.ListenAndServe(":8080", nil))
}

2.2 编译和运行 exporter

bash
# 编译 exporter
go build -o tidb-custom-exporter main.go

# 运行 exporter
./tidb-custom-exporter

2.3 配置 Prometheus 采集

在 Prometheus 配置文件中添加采集任务:

yaml
scrape_configs:
  - job_name: 'tidb-custom-exporter'
    static_configs:
      - targets: ['localhost:8080']
    scrape_interval: 15s

Grafana 自定义仪表盘开发

1. 仪表盘结构

Grafana 仪表盘由以下部分组成:

  • 面板(Panel):展示单个指标或指标组合
  • 行(Row):组织相关的面板
  • 变量(Variable):用于动态筛选数据
  • 查询(Query):从数据源获取数据
  • 可视化(Visualization):图表类型,如折线图、柱状图、仪表盘等

2. 创建自定义仪表盘

2.1 登录 Grafana

访问 Grafana 界面,使用管理员账号登录。

2.2 创建仪表盘

  1. 点击左侧菜单的 "+" 按钮,选择 "Dashboard"
  2. 点击 "Add new panel"
  3. 配置查询:
    • 选择数据源为 Prometheus
    • 输入 PromQL 查询语句,如 rate(tidb_custom_requests_total[5m])
  4. 配置可视化:
    • 选择图表类型,如 "Time series"
    • 配置图表标题、图例、轴标签等
  5. 点击 "Apply" 保存面板
  6. 点击 "Save dashboard" 保存仪表盘

3. 导入和导出仪表盘

3.1 导出仪表盘

  1. 打开要导出的仪表盘
  2. 点击右上角的 "Share" 按钮
  3. 选择 "Export" 标签页
  4. 选择导出选项,如是否包含注释和链接
  5. 点击 "Save to file" 下载 JSON 文件

3.2 导入仪表盘

  1. 点击左侧菜单的 "+" 按钮,选择 "Import"
  2. 选择要导入的 JSON 文件,或粘贴 JSON 内容
  3. 选择数据源
  4. 点击 "Import" 完成导入

4. 仪表盘最佳实践

  • 组织面板:将相关的面板组织在同一行,便于查看
  • 使用变量:使用变量实现动态筛选,提高仪表盘的灵活性
  • 选择合适的图表类型:根据指标类型选择合适的图表类型
  • 设置合理的时间范围:根据监控需求设置合适的时间范围
  • 添加注释:添加关键事件的注释,便于分析问题
  • 设置告警阈值:在面板上显示告警阈值,便于直观查看

监控插件开发

1. TiDB 监控插件架构

TiDB 支持通过插件扩展监控功能。监控插件可以:

  • 采集自定义指标
  • 实现自定义告警
  • 扩展监控展示

2. 开发监控插件

2.1 插件结构

监控插件的基本结构包括:

tidb-monitor-plugin/
├── plugin.json          # 插件元数据
├── main.go             # 插件入口
├── collector/          # 指标采集器
├── alert/              # 告警规则
└── dashboard/          # Grafana 仪表盘

2.2 插件元数据

plugin.json 包含插件的基本信息:

json
{
  "name": "tidb-custom-plugin",
  "version": "1.0.0",
  "description": "A custom monitoring plugin for TiDB",
  "author": "Your Name",
  "dependencies": [],
  "collectors": [
    {
      "name": "custom-collector",
      "type": "prometheus",
      "interval": 15
    }
  ],
  "dashboards": [
    {
      "name": "Custom Dashboard",
      "file": "dashboard/custom-dashboard.json"
    }
  ],
  "alerts": [
    {
      "name": "Custom Alert",
      "file": "alert/custom-alert.yaml"
    }
  ]
}

2.3 采集器开发

开发自定义采集器:

go
package collector

import (
    "context"
    "time"

    "github.com/prometheus/client_golang/prometheus"
)

// CustomCollector 自定义采集器
type CustomCollector struct {
    metric *prometheus.Desc
}

// NewCustomCollector 创建自定义采集器
func NewCustomCollector() *CustomCollector {
    return &CustomCollector{
        metric: prometheus.NewDesc(
            "tidb_custom_metric",
            "A custom metric for TiDB",
            []string{"label"}, nil,
        ),
    }
}

// Describe 实现 prometheus.Collector 接口
func (c *CustomCollector) Describe(ch chan<- *prometheus.Desc) {
    ch <- c.metric
}

// Collect 实现 prometheus.Collector 接口
func (c *CustomCollector) Collect(ch chan<- prometheus.Metric) {
    // 采集指标数据
    value := 1.0
    ch <- prometheus.MustNewConstMetric(
        c.metric,
        prometheus.GaugeValue,
        value,
        "test",
    )
}

3. 安装和使用插件

3.1 安装插件

bash
# 复制插件到 TiDB 监控插件目录
cp -r tidb-monitor-plugin /path/to/tidb-monitor/plugins/

# 重启 TiDB 监控组件
tiup cluster restart <cluster-name> -R monitoring

3.2 使用插件

  • 查看指标:访问 http://[monitor-ip]:9090/metrics 查看自定义指标
  • 查看仪表盘:在 Grafana 中查看导入的自定义仪表盘
  • 查看告警:在 Prometheus Alertmanager 中查看自定义告警

自定义告警规则开发

1. 告警规则格式

Prometheus 告警规则使用 YAML 格式定义:

yaml
groups:
- name: custom-alerts
  rules:
  - alert: CustomAlert
    expr: rate(tidb_custom_requests_total[5m]) > 100
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "Custom alert is firing"
      description: "The custom request rate is {{ $value }} per second, which is above the threshold of 100."

2. 配置告警规则

2.1 直接配置

将告警规则文件添加到 Prometheus 配置目录:

bash
# 将告警规则文件复制到 Prometheus 配置目录
cp custom-alert.yaml /path/to/prometheus/rules/

# 重启 Prometheus
systemctl restart prometheus

2.2 使用 TiUP 配置

在 TiUP 集群配置文件中添加告警规则:

yaml
global:
  user: "tidb"
  ssh_port: 22
  deploy_dir: "/tidb-deploy"
  data_dir: "/tidb-data"

monitored:
  node_exporter_port: 9100
  blackbox_exporter_port: 9115
  alertmanager_port: 9093
  grafana_port: 3000
  prometheus_port: 9090
  prometheus_retention_time: "15d"
  # 添加自定义告警规则
  alert_rules_files:
    - /path/to/custom-alert.yaml

监控数据导出和分析

1. 导出监控数据

使用 Prometheus API 导出监控数据:

bash
# 导出 5 分钟内的指标数据
curl -g 'http://localhost:9090/api/v1/query_range?query=tidb_custom_requests_total&start=1609459200&end=1609459500&step=15s'

2. 使用 PromQL 分析数据

PromQL 是 Prometheus 的查询语言,可以用于分析监控数据:

2.1 基本查询

# 查询当前值
tidb_custom_gauge

# 查询 5 分钟内的平均值
avg_over_time(tidb_custom_gauge[5m])

# 查询增长率
rate(tidb_custom_requests_total[5m])

# 查询分位数
histogram_quantile(0.95, rate(tidb_custom_request_duration_seconds_bucket[5m]))

2.2 高级查询

# 按标签分组查询
sum by (instance) (rate(tidb_custom_requests_total[5m]))

# 计算比率
sum(rate(tidb_custom_requests_total{status="error"}[5m])) / sum(rate(tidb_custom_requests_total[5m]))

# 预测趋势
predict_linear(tidb_custom_gauge[1h], 3600)

监控最佳实践

1. 指标命名规范

  • 遵循 Prometheus 命名规范,使用下划线分隔单词
  • 指标名称应包含组件名称,如 tidb_pd_tikv_
  • 指标名称应清晰描述指标含义,如 tidb_custom_requests_total
  • 使用合适的标签,便于按维度分析

2. 采集频率

  • 对于频繁变化的指标,如请求数,采集频率可以设置为 5-15 秒
  • 对于变化较慢的指标,如 CPU 使用率,采集频率可以设置为 30-60 秒
  • 避免过于频繁的采集,以免增加系统负担

3. 数据保留

  • 根据监控需求设置合适的数据保留时间
  • 对于长期趋势分析,可以考虑使用 Thanos 或 Cortex 等工具扩展 Prometheus 的存储能力

4. 告警规则

  • 告警规则应覆盖关键指标
  • 设置合理的告警阈值,避免误告警
  • 配置多级告警,区分不同严重程度
  • 配置合适的告警通知渠道

5. 仪表盘设计

  • 仪表盘应清晰易懂,重点突出
  • 避免在一个仪表盘上放置过多面板
  • 使用变量实现动态筛选
  • 定期更新和优化仪表盘

常见问题(FAQ)

Q1: 如何在 TiDB 中添加自定义指标?

A1: 可以通过以下方式在 TiDB 中添加自定义指标:

  • 在 TiDB 代码中使用 Prometheus 客户端库添加指标
  • 开发独立的监控 exporter,暴露自定义指标
  • 使用 TiDB 插件机制开发监控插件

Q2: 如何开发自定义 Grafana 仪表盘?

A2: 可以通过以下步骤开发自定义 Grafana 仪表盘:

  • 登录 Grafana,创建新仪表盘
  • 添加面板,配置 PromQL 查询
  • 选择合适的可视化类型
  • 配置变量、注释等高级功能
  • 保存并导出仪表盘

Q3: 如何配置自定义告警规则?

A3: 可以通过以下方式配置自定义告警规则:

  • 直接将告警规则文件添加到 Prometheus 配置目录
  • 在 TiUP 集群配置文件中添加告警规则
  • 使用 Prometheus API 动态添加告警规则

Q4: 如何导出和分析监控数据?

A4: 可以使用以下方式导出和分析监控数据:

  • 使用 Prometheus API 导出数据
  • 使用 PromQL 分析数据
  • 使用 Grafana 导出 CSV 数据
  • 使用第三方工具如 Thanos、Cortex 等进行长期存储和分析

Q5: 如何优化监控性能?

A5: 可以通过以下方式优化监控性能:

  • 合理设置采集频率
  • 减少不必要的指标
  • 使用标签选择器过滤数据
  • 优化 PromQL 查询
  • 扩展 Prometheus 存储能力

Q6: 如何开发 TiDB 监控插件?

A6: 可以通过以下步骤开发 TiDB 监控插件:

  • 创建插件目录结构
  • 编写插件元数据文件
  • 开发自定义采集器
  • 开发 Grafana 仪表盘
  • 开发告警规则
  • 安装和测试插件