告警通知¶
详细参见文件 config.toml
不需要全部配置,根据自己需要,选择任意一种通知即可
Telegram¶
bot_token
chat_id
申请 参见 https://core.telegram.org/bots/api#authorizing-your-bot
# https://core.telegram.org/bots/api
# https://jinja.palletsprojects.com/en/3.0.x/templates/#if
[tgbot]
# 开关 true 打开
enabled = false
bot_token = "<tg bot token>"
chat_id = "<chat id>"
# host 可用字段参见 payload.rs 文件 HostStat 结构, {{host.xxx}} 为占位变量
# 例如 host.name 可替换为 host.alias,大家根据自己的喜好来编写通知消息
# {{ip_info.query}} 主机 ip, {{sys_info.host_name}} 主机 hostname
title = "❗<b>Server Status</b>"
online_tpl = "{{config.title}} \n😆 {{host.location}} {{host.name}} 主机恢复上线啦"
offline_tpl = "{{config.title}} \n😱 {{host.location}} {{host.name}} 主机已经掉线啦"
# custom 模板置空则停用自定义告警,只保留上下线通知
custom_tpl = """
{% if host.memory_used / host.memory_total > 0.5 %}
<pre>😲 {{host.name}} 主机内存使用率超50%, 当前{{ (100 * host.memory_used / host.memory_total) | round }}% </pre>
{% endif %}
{% if host.hdd_used / host.hdd_total > 0.5 %}
<pre>😲 {{host.name}} 主机硬盘使用率超50%, 当前{{ (100 * host.hdd_used / host.hdd_total) | round }}% </pre>
{% endif %}
"""
WeChat¶
## 可选 微信通知
[wechat]
enabled = false
corp_id = "<corp id>"
corp_secret = "<corp secret>"
agent_id = "<agent id>"
title = "❗Server Status"
online_tpl = "{{config.title}} \n😆 {{host.location}} 的 {{host.name}} 主机恢复上线啦"
offline_tpl = "{{config.title}} \n😱 {{host.location}} 的 {{host.name}} 主机已经掉线啦"
custom_tpl = """
{% if host.memory_used / host.memory_total > 0.8 %}
😲 {{host.name}} 主机内存使用率超80%
{% endif %}
{% if host.hdd_used / host.hdd_total > 0.8 %}
😲 {{host.name}} 主机硬盘使用率超80%
{% endif %}
"""
Email¶
## 可选 邮件通知
[email]
enabled = false
server = "smtp.gmail.com"
username = "user@email.com"
password = "***"
to = "user1@email.com;user2@email.com"
subject = "ServerStatus Notification"
title = "❗<b>Server Status</b><br/>"
online_tpl = "{{config.title}} 😆 {{host.location}} 的 {{host.name}} 主机恢复上线啦"
offline_tpl = "{{config.title}} 😱 {{host.location}} 的 {{host.name}} 主机已经掉线啦"
custom_tpl = """
{% if host.memory_used / host.memory_total > 0.8 %}
<pre>😲 {{host.name}} 主机内存使用率超80%, 当前{{ (100 * host.memory_used / host.memory_total) | round }}% </pre>
{% endif %}
{% if host.hdd_used / host.hdd_total > 0.8 %}
<pre>😲 {{host.name}} 主机硬盘使用率超80%, 当前{{ (100 * host.hdd_used / host.hdd_total) | round }}% </pre>
{% endif %}
"""
Log¶
版本要求 >= 1.5.4
## 可选 单纯记录 event 到日志文件
[log]
enabled = false
log_dir = "/opt/ServerStatus/logs"
tpl = """{% set obj = dict(event=event, host=host, ip_info=ip_info, sys_info=sys_info) %} {{ obj | tojson}}"""
Webhook¶
版本要求 >= 1.5.4
webhook
为增加灵活性,并没有使用上面模块所使用的模版引擎,而是使用 脚本引擎 来实现接入自定义的 webhook
,
理论上支持所有支持 webhook
的软件,如 Discord
、 Slack
、 飞书、 企业版微信(WorkWechat)、 钉钉(DingTalk)等。
webhook
调用基本上都差不多,差异只在最后返回的 json
结构,根据各自的 api
文档自行构建相应的 json
结构即可。
## 可选 webhook
[webhook]
# 总开关
enabled = false
# 可多个 webhook.receiver
[[webhook.receiver]] # 通用型 webhook
# 局部开关
enabled = false
# https://webhook.site/#!/2b1ad731-45fe-49a8-ae91-614167019db2
url = "https://webhook.site/2b1ad731-45fe-49a8-ae91-614167019db2"
headers = { content-type = "application/json", x-data = "y-data" }
# headers = { content-type = "text/plain" }
# 可选 HTTP Basic Auth
username = "u"
password = "p"
timeout = 5 #s
# 简单发送一个 json 对象,#{} 为 Object 对象, [] 为数组
# 最终结果, 固定结构 [是否发送通知,结果对象]
script = """[true, #{config: config, event: event, host: host, ip_info: ip_info, sys_info:sys_info} ]"""
[[webhook.receiver]] # Discord
enabled = false
# https://discord.com/developers/docs/resources/webhook
url = "https://discord.com/api/webhooks/xxxxxxxxxxxxxxxxxxxxxxx"
headers = { content-type = "application/json" }
timeout = 5 #s
script = """
let message = "";
switch event {
"Custom" => { // 自定义事件
let threshold = 10;
let msgs = [];
let memory_usage = round(host.memory_used * 100.0 / host.memory_total);
if memory_usage > threshold {
msgs.push(`😲 ${host.location} ${host.name} 主机内存使用率超${threshold}%, 当前 ${memory_usage}%`);
}
let hdd_usage = round(host.hdd_used * 100.0 / host.hdd_total);
if hdd_usage > threshold {
msgs.push(`😲 ${host.location} ${host.name} 主机硬盘使用率超${threshold}%, 当前 ${hdd_usage}%`);
}
message = join(msgs, "\\n");
},
"NodeDown" => { // 掉线
message = `😱 ${host.location} ${host.name} 主机已经掉线啦`;
},
"NodeUp" => { // 上线
message = `😆 ${host.location} ${host.name} 主机恢复上线啦`;
}
}
// 返回的 json 结构,#{} 为 Object 对象, [] 为数组
// 最终结果, 固定结构 [是否发送通知,结果对象]
[message.len() > 0, #{ embeds: [ #{
title: ":bell: ServerStatus-Rust :bell:",
fields: [
#{ name: "Event", value: event, },
#{ name: "Datetime", value: now_str(), },
#{ name: "Message", value: message, },
]
}]}]
"""
[[webhook.receiver]] # Slack
enabled = false
# https://api.slack.com/messaging/webhooks
url = "https://hooks.slack.com/services/xxxxxxxxxxxxxxxxxxxxxxx"
headers = { content-type = "application/json" }
timeout = 5 #s
script = """
let message = "";
switch event {
"Custom" => { // 自定义事件
let threshold = 80;
let msgs = [];
let memory_usage = round(host.memory_used * 100.0 / host.memory_total);
if memory_usage > threshold {
msgs.push(`😲 ${host.location} ${host.name} 主机内存使用率超${threshold}%, 当前 ${memory_usage}%`);
}
let hdd_usage = round(host.hdd_used * 100.0 / host.hdd_total);
if hdd_usage > threshold {
msgs.push(`😲 ${host.location} ${host.name} 主机硬盘使用率超${threshold}%, 当前 ${hdd_usage}%`);
}
message = join(msgs, "\\n");
},
"NodeDown" => { // 掉线
message = `😱 ${host.location} ${host.name} 主机已经掉线啦`;
},
"NodeUp" => { // 上线
message = `😆 ${host.location} ${host.name} 主机恢复上线啦`;
}
}
// 最终结果, 固定结构 [是否发送通知,结果对象]
[message.len() > 0, #{text: message}]
"""
[[webhook.receiver]] # WorkWechat
enabled = false
# https://developer.work.weixin.qq.com/document/path/91770
url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxxxxxxxxxxxxxxxxxx"
headers = { content-type = "application/json" }
timeout = 5 #s
script = """
let message = "";
switch event {
"Custom" => { // 自定义事件
let threshold = 80;
let msgs = [];
let memory_usage = round(host.memory_used * 100.0 / host.memory_total);
if memory_usage > threshold {
msgs.push(`😲 ${host.location} ${host.name} 主机内存使用率超${threshold}%, 当前 ${memory_usage}%`);
}
let hdd_usage = round(host.hdd_used * 100.0 / host.hdd_total);
if hdd_usage > threshold {
msgs.push(`😲 ${host.location} ${host.name} 主机硬盘使用率超${threshold}%, 当前 ${hdd_usage}%`);
}
message = join(msgs, "\\n");
},
"NodeDown" => { // 掉线
message = `😱 ${host.location} ${host.name} 主机已经掉线啦`;
},
"NodeUp" => { // 上线
message = `😆 ${host.location} ${host.name} 主机恢复上线啦`;
}
}
// 最终结果, 固定结构 [是否发送通知,结果对象]
[message.len() > 0, #{
msgtype: "text",
text: #{
content: message
}
}]
"""