web-app/src/assets/doc/alert-integration/zabbix.zh-CN.md
将 Zabbix 的告警通过 Webhook 方式发送到 HertzBeat 告警平台。
登录 Zabbix Web 界面
进入 告警 > 媒介类型 > 创建媒介类型
配置基本信息
在 参数 部分添加以下字段
| 名称 | 值 |
|---|---|
| URL | http://your-hertzbeat-server:1157/api/alerts/report/zabbix |
| AlertName | {TRIGGER.NAME} |
| AlertId | {EVENT.ID} |
| HostName | {HOST.NAME} |
| HostIp | {HOST.IP} |
| TriggerDescription | {TRIGGER.DESCRIPTION} |
| TriggerSeverity | {TRIGGER.SEVERITY} |
| TriggerStatus | {EVENT.STATUS} |
| ItemName | {ITEM.NAME} |
| ItemValue | {ITEM.VALUE} |
| ItemLastValue | {ITEM.LASTVALUE} |
| EventDate | {EVENT.DATE} |
| EventTime | {EVENT.TIME} |
| EventTags | {EVENT.TAGS} |
| EventRecoveryDate | {EVENT.RECOVERY.DATE} |
| EventRecoveryTime | {EVENT.RECOVERY.TIME} |
在 脚本 部分添加以下 JavaScript 代码
var HertzBeat = {
sendMessage: function(url, alert) {
request = new HttpRequest();
request.addHeader('Content-Type: application/json');
data = JSON.stringify(alert);
Zabbix.Log(4, '[HertzBeat Webhook] params: ' + data);
// 推送告警消息
response = request.post(url, data);
Zabbix.Log(4, '[HertzBeat Webhook] HTTP code: ' + request.Status());
Zabbix.Log(4, '[HertzBeat Webhook] response: ' + response);
// 格式化返回的结果并做出判断,有异常则抛出异常。
try {
response = JSON.parse(response);
} catch (error) {
response = null;
Zabbix.Log(4, '[HertzBeat Webhook] response parse error');
}
if (request.Status() !== 200 || response.errcode !== 0 || response.errmsg !== 'ok') {
if (typeof response.errmsg === 'string') {
throw response.errmsg;
}
else {
throw 'Unknown error. Check debug log for more information.'
}
}
}
}
try {
var params = JSON.parse(value);
// 判断Webhook_url参数是否定义,未定义抛出错误。
if (typeof params.URL === 'undefined') {
throw 'Incorrect value is given for parameter "Webhook_url": parameter is missing';
}
var currentTimestamp = Date.now();
// 转换 zabbix 严重性到 HertzBeat 优先级
function convertSeverity(severity) {
var severityMap = {
"信息": "info",
"Information": "info",
"警告": "warning",
"Warning": "warning",
"一般严重": "error",
"Average": "error",
"严重": "critical",
"High": "critical",
"灾难": "emergency",
"Disaster": "emergency"
};
return severityMap[severity] || "error";
}
// 构建指纹唯一标识
var fingerprint = "zabbix-event:" + params.AlertId + "-" + params.HostName;
// 构建 labels
var labels = {
"alertname": params.AlertName,
"source": "zabbix",
"severity": convertSeverity(params.TriggerSeverity),
"host": params.HostName,
"hostip": params.HostIp,
"itemname": params.ItemName
};
// 解析事件标签
if (params.EventTags) {
var tags = params.EventTags.split(',');
for (var i = 0; i < tags.length; i++) {
var tagParts = tags[i].split(':');
if (tagParts.length == 2) {
var key = tagParts[0].trim();
var value = tagParts[1].trim();
labels[key] = value;
}
}
}
// 构建注解信息
var annotations = {
"summary": params.AlertName,
"description": params.TriggerDescription,
"value": params.ItemValue,
"lastValue": params.ItemLastValue
};
// 构建告警内容
var content = "主机: " + params.HostName +
"\nIP: " + params.HostIp +
"\n告警: " + params.AlertName +
"\n级别: " + params.TriggerSeverity +
"\n描述: " + params.TriggerDescription +
"\n监控项: " + params.ItemName +
"\n当前值: " + params.ItemValue +
"\n上次值: " + params.ItemLastValue +
"\n时间: " + params.EventDate + " " + params.EventTime;
// 确定状态
var status = params.TriggerStatus === "RESOLVED" ? "resolved" : "firing";
// 计算时间戳
var startAt = currentTimestamp;
var endAt = null;
// 如果是恢复事件,计算结束时间
if (status === "resolved" && params.EventRecoveryDate && params.EventRecoveryTime) {
endAt = currentTimestamp;
}
// 构建发送到 HertzBeat 的 payload
var hertzbeatAlert = {
"fingerprint": fingerprint,
"labels": labels,
"annotations": annotations,
"content": content,
"status": status,
"triggerTimes": 1,
"startAt": startAt,
"activeAt": startAt,
"endAt": endAt
};
// 记录日志
Zabbix.Log(4, "HertzBeat webhook payload: " + JSON.stringify(hertzbeatAlert));
// 执行消息推送函数
HertzBeat.sendMessage(params.URL, hertzbeatAlert);
// 返回给zabbix,ok 在 Zabbix 动作中会被用来标识成功执行。
return 'OK';
} catch (error) {
Zabbix.Log(4, '[HertzBeat Webhook] notification failed: ' + error);
throw 'Sending failed: ' + error + '.';
}
更多信息请参考 Zabbix Webhook 以及 Zabbix 宏