一个支持 Grafana 和 Prometheus 告警格式的中间件,可以将告警消息推送到不同群的飞书/Lark Webhook 机器人。
- ✅ 自动识别告警来源 - 自动识别 Grafana 和 Prometheus 告警格式,无需指定端点
- ✅ 消息模板自定义 - 支持为每个 Webhook 配置独立的 Go Template (Markdown) 模板
- ✅ 数据持久化 - 使用 SQLite 存储统计数据和静默规则,服务重启不丢失
- ✅ Admin 后台 - 全中文 Web UI + REST 管理接口,支持 Webhook 管理、数据看板与静默规则
- ✅ 详细日志 - 记录原始请求体与解析后的告警对象,极大方便模板调试
- ✅ 自动将告警转换为飞书/Lark 富文本消息
- ✅ 健康检查端点
- ✅ 配置文件外挂 - 配置文件独立于二进制,方便修改和部署
lark-alert/
├── main.go # 主程序入口
├── config/ # 配置管理
│ └── config.go
├── models/ # 数据模型
│ └── alert.go
├── parser/ # 告警解析器
│ └── parser.go
├── webhook/ # Webhook 客户端
│ └── webhook.go
├── handler/ # HTTP 处理器(含 admin)
│ └── handler.go
├── store/ # 统计存储 (SQLite)
│ ├── db.go # 数据库初始化
│ ├── silence.go # 静默规则存储
│ └── stats.go # 统计数据存储
├── alert.db # SQLite 数据库文件 (运行时生成)
├── static/ # Admin 前端页面 (已嵌入二进制)
├── config.json.example # 配置文件示例
└── README.md
go mod tidy复制配置文件示例并修改:
cp config.json.example config.json编辑 config.json,填入你的 Webhook URL 与 admin token:
{
"server": {
"host": "0.0.0.0",
"port": 19527
},
"webhooks": {
"project-a": {
"url": "https://open.larksuite.com/open-apis/bot/v2/hook/project-a-webhook-url"
},
"project-b": {
"url": "https://open.larksuite.com/open-apis/bot/v2/hook/project-b-webhook-url"
},
"ops": {
"url": "https://open.larksuite.com/open-apis/bot/v2/hook/ops-webhook-url"
}
},
"admin": {
"token": "change-me-admin-token"
}
}配置说明:
webhooks中的键名(如project-a、project-b)是 webhook 配置名称- 通过
webhook_name参数可以引用这些配置名称 - 每个项目可以配置不同的 webhook URL
admin.token用于保护管理后台与统计接口(传入Authorization: Bearer <token>)
go run main.go -config config.json或者编译后运行:
go build -o lark-alert
./lark-alert -config config.jsonGET /health
支持灵活的请求参数配置,可以动态指定告警源和 webhook URL:
POST /webhook?source=<告警源>&lark_web_url=<webhook_url>&webhook_name=<webhook配置名>
请求参数说明:
source(可选): 指定告警源类型,支持grafana或prometheus。如果不指定,会自动识别。lark_web_url(可选): 指定飞书/Lark webhook,优先级最高。支持两种格式:- 完整 URL:
https://open.larksuite.com/open-apis/bot/v2/hook/xxx - 仅机器人 ID:
xxx(会自动拼接为完整 URL)
- 完整 URL:
webhook_name(可选): 指定 webhook 配置名称,从配置文件的webhooks中查找对应的 webhook URL。
优先级顺序:
lark_web_url参数(最高优先级)webhook_name参数(从配置查找)
示例:
# 方式1: 直接指定 webhook(最灵活)
# 方式1a: 使用完整 URL
curl -X POST "http://localhost:19527/webhook?source=grafana&lark_web_url=https://open.larksuite.com/open-apis/bot/v2/hook/xxx" \
-H "Content-Type: application/json" \
-d @grafana-alert.json
# 方式1b: 仅使用机器人 ID(推荐,更简洁)
curl -X POST "http://localhost:19527/webhook?source=grafana&lark_web_url=xxx" \
-H "Content-Type: application/json" \
-d @grafana-alert.json
# 方式2: 使用 webhook_name 参数(从配置查找)
curl -X POST "http://localhost:19527/webhook?source=prometheus&webhook_name=ops" \
-H "Content-Type: application/json" \
-d @prometheus-alert.json
# 方式3: 自动识别告警源
curl -X POST "http://localhost:19527/webhook?webhook_name=project-a" \
-H "Content-Type: application/json" \
-d @alert.jsonPOST /webhook/grafana
POST /webhook/prometheus
这些端点仍然可用,但建议使用统一的 /webhook 端点。
系统提供了一个功能强大的 Web 管理后台,访问地址:http://your-server:19527/admin
- 安全登录:支持 Token 认证登录与注销。
- Webhook 管理:在线查看、添加、编辑和删除 Webhook 配置。
- 仪表盘 (Dashboard):
- 实时查看告警总数、活跃来源数。
- 来源分布可视化(Grafana vs Prometheus)。
- 详细的告警活动日志(含相对时间显示)。
- 自定义模板:在编辑机器人时,支持输入 Markdown + Go Template 语法。
- 告警抑制 (Silences):
- 支持一键抑制 Dashboard 中的骚扰告警。
- 自定义抑制时长(15m, 1h, 24h 等)。
- 按 Webhook 或 指纹 (Fingerprint) 维度进行抑制。
- 规则持久化存储。
- 调试日志:控制台输出解析后的 JSON 对象,方便直接复制字段名到模板中。
除了 Web 界面,也支持 REST API 管理:
-
Webhooks:
GET /api/admin/webhooks:列出配置POST /api/admin/webhooks?name=xxx:新增PUT /api/admin/webhooks/{name}:更新DELETE /api/admin/webhooks/{name}:删除
-
Statistics:
GET /admin/stats:获取统计数据POST /admin/stats/clear:清空所有统计
-
Silences:
GET /api/admin/silences:列出静默规则POST /api/admin/silences:创建规则DELETE /api/admin/silences/{id}:删除规则
中间件支持两种方式指定告警来源:
-
自动识别(推荐):不指定
source参数时,会自动识别- 首先尝试解析为 Grafana 格式
- 如果失败,尝试解析为 Prometheus 格式
- 如果都失败,返回错误
-
手动指定:通过
source参数明确指定source=grafana- 强制按 Grafana 格式解析source=prometheus- 强制按 Prometheus 格式解析
支持两种方式配置 webhook URL:
-
动态指定:通过
lark_web_url参数直接指定- 完整 URL:
?lark_web_url=https://open.larksuite.com/open-apis/bot/v2/hook/xxx - 仅机器人 ID:
?lark_web_url=xxx(推荐,更简洁)
适用于临时或动态配置场景。
- 完整 URL:
-
配置名称映射(推荐):通过
webhook_name参数从配置文件查找?webhook_name=project-a需要在配置文件的
webhooks中配置对应的名称(如project-a,project-b,ops等)。 这是多项目多群组场景的推荐方式。
场景1:多项目多群组
# 项目A的告警发送到项目A的群组
curl -X POST "http://localhost:19527/webhook?source=grafana&webhook_name=project-a" \
-H "Content-Type: application/json" -d @alert.json
# 项目B的告警发送到项目B的群组
curl -X POST "http://localhost:19527/webhook?source=grafana&webhook_name=project-b" \
-H "Content-Type: application/json" -d @alert.json场景2:动态 webhook URL
# 不需要在配置文件中预先配置,直接指定 webhook(仅需机器人 ID)
curl -X POST "http://localhost:19527/webhook?lark_web_url=xxx" \
-H "Content-Type: application/json" -d @alert.json配置文件通过 -config 参数指定,不会打包进二进制文件,方便修改和部署:
./lark-alert -config /path/to/config.json修改配置文件后,需要重启服务才能生效。
支持标准的 Grafana 告警格式,包括:
alerts数组labels和annotationsstatus(firing/resolved)
支持 Prometheus Alertmanager 的告警格式,包括:
alerts数组labels和annotationsstatus(firing/resolved)
告警会被转换为飞书/Lark/Lark 的富文本消息格式,包含:
- 来源(Grafana/Prometheus)
您可以为每个 Webhook 配置专属的消息卡片内容。
在模板中,您可以使用 UnifiedAlert 结构体中的所有字段:
.Title: 告警标题.Status: 状态 (firing或resolved).Severity: 严重程度 (critical,warning,info).Message: 告警描述/详细信息.Source: 来源 (grafana或prometheus).StartsAt: 告警开始时间.Labels: 标签 Map (使用{{index .Labels "key"}}引用)
⚡ **级别**: {{.Severity}}
📝 **描述**: {{.Message}}
---
🏷️ **标签**:
{{range $k, $v := .Labels}}- `{{$k}}`: {{$v}}
{{end}}🔥 **告警: {{.Title}}**
---
节点: {{index .Labels "instance"}}
详情: {{.Message}}发送告警后,观察程序控制台日志。系统会打印 解析后的告警对象 [n]: { ... },其中的所有 Key 都可以通过 {{.KeyName}} 的方式在模板中引用。
- 进入 Grafana 的告警规则配置
- 添加通知渠道,选择 "Webhook"
- URL 设置示例:
- 使用 webhook_name:
http://your-server:19527/webhook?source=grafana&webhook_name=ops - 使用动态 URL(仅机器人 ID):
http://your-server:19527/webhook?source=grafana&lark_web_url=xxx - 自动识别:
http://your-server:19527/webhook?webhook_name=ops
- 使用 webhook_name:
- HTTP Method 选择 POST
- 保存配置
在 alertmanager.yml 中配置:
receivers:
- name: 'lark-alert'
webhook_configs:
- url: 'http://your-server:19527/webhook?source=prometheus&webhook_name=ops'
send_resolved: true或者使用动态 webhook URL(仅机器人 ID):
receivers:
- name: 'lark-alert'
webhook_configs:
- url: 'http://your-server:19527/webhook?source=prometheus&lark_web_url=xxx'
send_resolved: truego build -o lark-alertgo test ./...MIT