跳转至

告警通知

详细参见文件 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 的软件,如 DiscordSlack、 飞书、 企业版微信(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
      }
    }]
  """