4. 报警源接入:Prometheus接入、Zabbix接入、自定义API接入、日志文件接入
报警源接入,说白了就是让我们的报警系统能“听懂”各种监控工具说的话。我见过不少团队,监控工具装了一堆,但报警各自为战,运维得同时盯着好几个屏幕。嗯,这章我们就来解决这个问题。
核心思路:不管数据源是什么,最终都统一转换成标准报警事件格式,进入统一的事件处理管道。
4.1 整体架构与数据流
先看一张图,你就明白这四种接入方式在整个系统中的位置了。
你看,不管数据从哪来,经过适配器层之后,都变成了统一格式。我个人习惯把适配器做成插件式,加一个新数据源只需要写一个插件,不用改主流程。
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 界面里:
- 进入 配置 → 动作 → 创建动作
- 设置触发条件,比如问题严重性 ≥ 警告
- 在操作标签页,添加一个操作,类型选“远程命令”
- 命令内容写一个脚本调用:
# 在 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 的系统 | 中(分钟级) | 高 | 高 |