4. 报警源接入:Prometheus接入、Zabbix接入、自定义API接入、日志文件接入

报警源接入,说白了就是让我们的报警系统能“听懂”各种监控工具说的话。我见过不少团队,监控工具装了一堆,但报警各自为战,运维得同时盯着好几个屏幕。嗯,这章我们就来解决这个问题。

核心思路:不管数据源是什么,最终都统一转换成标准报警事件格式,进入统一的事件处理管道。

4.1 整体架构与数据流

先看一张图,你就明白这四种接入方式在整个系统中的位置了。

报警源接入架构图 Prometheus Alertmanager Webhook Zabbix Action → Script 自定义API HTTP POST JSON 日志文件 Filebeat + 正则 报警适配器层(Adapter) 格式转换 · 字段映射 · 去重 · 过滤 统一报警事件总线 标准事件格式 · 队列缓冲 · 持久化 事件处理引擎 · 通知分发 · 自愈

你看,不管数据从哪来,经过适配器层之后,都变成了统一格式。我个人习惯把适配器做成插件式,加一个新数据源只需要写一个插件,不用改主流程。

4.2 Prometheus 接入

Prometheus 是目前云原生监控的事实标准。它的报警通过 Alertmanager 管理,我们只需要让 Alertmanager 把报警推送到我们的系统就行。

4.2.1 配置 Alertmanager Webhook

在 Alertmanager 的配置文件里加一个 receiver:

# alertmanager.yml
receivers:
  - name: 'my-alert-system'
    webhook_configs:
      - url: 'http://your-alert-system:8080/api/v1/alert/prometheus'
        send_resolved: true
        http_config:
          basic_auth:
            username: 'alertmanager'
            password: 'your-password'

然后在 route 里引用这个 receiver:

route:
  receiver: 'my-alert-system'
  group_wait: 10s
  group_interval: 2m
  repeat_interval: 4h

小技巧:send_resolved 建议开启。这样恢复通知也能收到,方便做告警闭环统计。我在项目里吃过亏,没开恢复通知,结果半夜排查了半天才发现是误报。

4.2.2 接收端接口设计

Prometheus 发来的 JSON 结构长这样:

{
  "version": "4",
  "groupKey": "{}:{alertname=\"CPU使用率过高\"}",
  "status": "firing",
  "alerts": [
    {
      "status": "firing",
      "labels": {
        "alertname": "CPU使用率过高",
        "instance": "192.168.1.100:9090",
        "severity": "critical"
      },
      "annotations": {
        "summary": "CPU 使用率超过 90%",
        "description": "实例 192.168.1.100 CPU 使用率已达 95%"
      },
      "startsAt": "2024-01-15T10:00:00Z",
      "endsAt": "0001-01-01T00:00:00Z"
    }
  ]
}

我们的接收接口要做的事:

  • 解析 JSON,提取 alerts 数组
  • 把 labels 和 annotations 合并成事件字段
  • 根据 severity 映射成我们系统的事件级别
  • 生成唯一事件 ID(我用 alertname + instance + startsAt 做 hash)

4.3 Zabbix 接入

Zabbix 是老牌监控,很多传统企业还在用。它的接入方式比较灵活,我推荐用 Action + Script 的方式。

4.3.1 配置 Zabbix Action

在 Zabbix Web 界面里:

  1. 进入 配置 → 动作 → 创建动作
  2. 设置触发条件,比如问题严重性 ≥ 警告
  3. 在操作标签页,添加一个操作,类型选“远程命令”
  4. 命令内容写一个脚本调用:
# 在 Zabbix Server 上执行的脚本
/usr/local/bin/zabbix_alert.sh "{TRIGGER.STATUS}" "{TRIGGER.SEVERITY}" "{ITEM.NAME}" "{ITEM.VALUE}" "{HOST.NAME}" "{EVENT.DATE} {EVENT.TIME}"

4.3.2 脚本实现示例

#!/bin/bash
# zabbix_alert.sh

STATUS=$1
SEVERITY=$2
ITEM_NAME=$3
ITEM_VALUE=$4
HOST_NAME=$5
EVENT_TIME=$6

# 构建 JSON 并发送
curl -X POST http://your-alert-system:8080/api/v1/alert/zabbix \
  -H "Content-Type: application/json" \
  -d '{
    "source": "zabbix",
    "status": "'$STATUS'",
    "severity": "'$SEVERITY'",
    "title": "'$ITEM_NAME'",
    "message": "主机: '$HOST_NAME', 当前值: '$ITEM_VALUE'",
    "event_time": "'$EVENT_TIME'"
  }'

注意:Zabbix 的宏变量里可能包含特殊字符,比如引号、换行符。脚本里一定要做转义处理。我曾经因为这个原因,导致报警发出去是乱码,排查了半天才发现是 JSON 格式被破坏了。

4.4 自定义 API 接入

这个最灵活。任何系统,只要它能发 HTTP 请求,就能接入。我设计了一个通用的接收接口,支持多种认证方式。

4.4.1 API 接口规范

项目 说明
请求方式 POST
Content-Type application/json
认证方式 (Header: X-Auth-)或 Basic Auth
请求体 标准事件 JSON
响应 {"code": 0, "message": "success", "event_id": "xxx"}

4.4.2 标准事件 JSON 格式

{
  "source": "custom_app",
  "event_type": "error",
  "severity": "critical",
  "title": "数据库连接失败",
  "message": "无法连接到 192.168.1.200:3306,超时 30 秒",
  "host": "app-server-01",
  "service": "order-service",
  "timestamp": "2024-01-15T10:05:00+08:00",
  "tags": {
    "env": "production",
    "region": "cn-beijing"
  },
  "details": {
    "error_code": "DB_TIMEOUT",
    "retry_count": 3
  }
}

建议:tags 和 details 字段设计成 KV 结构,方便后续做过滤和聚合。我习惯在 details 里放机器可读的字段,在 message 里放人可读的描述。

4.5 日志文件接入

日志文件接入,说白了就是“从文本里捞报警”。很多老系统没有监控接口,但日志写得还算规范,这时候日志接入就派上用场了。

4.5.1 技术选型

我推荐用 Filebeat + 自定义处理管道:

  • Filebeat:轻量级日志采集器,负责 tail 日志文件
  • Logstash 或自定义处理器:做正则匹配和字段提取
  • 输出到报警系统 API:把匹配到的日志行转成报警事件

4.5.2 Filebeat 配置示例

# filebeat.yml
filebeat.inputs:
  - type: log
    enabled: true
    paths:
      - /var/log/app/*.log
    multiline:
      pattern: '^\d{4}-\d{2}-\d{2}'
      negate: true
      match: after

output.logstash:
  hosts: ["localhost:5044"]

4.5.3 正则匹配与事件生成

在 Logstash 或自定义处理器里做匹配:

# 匹配规则示例
patterns:
  - name: "OOM异常"
    regex: "java\.lang\.OutOfMemoryError"
    severity: "critical"
    title: "应用 OOM"
  - name: "连接超时"
    regex: "Connection timed out"
    severity: "warning"
    title: "网络连接超时"
  - name: "错误率过高"
    regex: "ERROR.*rate.*>.*threshold"
    severity: "error"
    title: "错误率超过阈值"

避坑指南:日志接入最容易踩的坑是正则性能。我曾经在一个每天产生 50GB 日志的系统上,用了一个贪婪匹配的正则,结果 Filebeat CPU 直接飙到 100%。后来改成非贪婪匹配,加上日志采样,才稳定下来。

4.6 接入方式对比

接入方式 适用场景 实时性 开发成本 维护成本
Prometheus 云原生、K8s 环境 高(秒级) 低 低
Zabbix 传统 IDC、网络设备 中(分钟级) 中 中
自定义 API 自研系统、SaaS 服务 取决于调用方 低 低
日志文件 老旧系统、无 API 的系统 中(分钟级) 高 高