diff --git a/README.md b/README.md index 7246279f..d5243c05 100644 --- a/README.md +++ b/README.md @@ -73,8 +73,8 @@ enabled = false bot_token = "" chat_id = "" # host 可用字段参见 payload.rs 文件 HostStat 结构 -online_tpl = "❗Server Status\n❗ {{ host.name }} 主机上线 🟢" -offline_tpl = "❗Server Status\n❗ {{ host.name }} 主机下线 🔴" +online_tpl = "❗Server Status\n❗ {{ host.location }} 地区的 {{ host.name }} 主机恢复上线 🟢" +offline_tpl = "❗Server Status\n❗ {{ host.location }} 地区的 {{ host.name }} 主机已经下线 🔴" # 模板置空则停用自定义告警,只保留上下线通知 custom_tpl = """ {% if host.memory_used / host.memory_total > 0.5 %} @@ -100,15 +100,18 @@ wget --no-check-certificate -qO docker-compose.yml 'https://raw.githubuserconten wget --no-check-certificate -qO config.toml 'https://raw.githubusercontent.com/zdz/ServerStatus-Rust/master/config.toml' touch stats.json docker network create traefik_gw -# 默认使用 watchtower 自动更新,不需要可以去掉 docker-compose up -d +./stat_server -h # 手动运行 ./stat_server # 或 ./stat_server -c config.toml # 或 RUST_BACKTRACE=1 RUST_LOG=trace ./stat_server -c config.toml + +# 测试通知是否生效 +./stat_server -c config.toml --notify-test ``` ## 4.客户端说明 diff --git a/config.toml b/config.toml index 9c54e85f..80873940 100644 --- a/config.toml +++ b/config.toml @@ -23,8 +23,8 @@ enabled = false bot_token = "" chat_id = "" # host 可用字段参见 payload.rs 文件 HostStat 结构 -online_tpl = "❗Server Status\n❗ {{ host.name }} 主机上线 🟢" -offline_tpl = "❗Server Status\n❗ {{ host.name }} 主机下线 🔴" +online_tpl = "❗Server Status\n❗ {{ host.location }} 地区的 {{ host.name }} 主机恢复上线 🟢" +offline_tpl = "❗Server Status\n❗ {{ host.location }} 地区的 {{ host.name }} 主机已经下线 🔴" # 模板置空则停用自定义告警,只保留上下线通知 custom_tpl = """ {% if host.memory_used / host.memory_total > 0.5 %} @@ -41,8 +41,8 @@ enabled = false corp_id = "" corp_secret = "" agent_id = "" -online_tpl = "❗Server Status\n❗ {{ host.name }} 主机上线 🟢" -offline_tpl = "❗Server Status\n❗ {{ host.name }} 主机下线 🔴" +online_tpl = "❗Server Status\n❗ {{ host.location }} 地区的 {{ host.name }} 主机恢复上线 🟢" +offline_tpl = "❗Server Status\n❗ {{ host.location }} 地区的 {{ host.name }} 主机已经下线 🔴" custom_tpl = """ {% if host.memory_used / host.memory_total > 0.8 %} ❗{{ host.name }} 主机内存使用率超80% @@ -60,8 +60,8 @@ username = "user@email.com" password = "***" to = "user1@email.com;user2@email.com" subject = "ServerStatus Notification" -online_tpl = "❗Server Status
❗ {{ host.name }} 主机上线 🟢" -offline_tpl = "❗Server Status
❗ {{ host.name }} 主机下线 🔴" +online_tpl = "❗Server Status
❗ {{ host.location }} 地区的 {{ host.name }} 主机恢复上线 🟢" +offline_tpl = "❗Server Status
❗ {{ host.location }} 地区的 {{ host.name }} 主机已经下线 🔴" custom_tpl = """ {% if host.memory_used / host.memory_total > 0.8 %}
❗{{ host.name }} 主机内存使用率超80%, 当前{{ (100 * host.memory_used / host.memory_total) | round }}%  
diff --git a/server/src/main.rs b/server/src/main.rs index 5d8dd2b3..84cee3aa 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -15,6 +15,7 @@ use std::sync::Arc; use std::sync::Mutex; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::TcpListener; +use tokio::runtime::Handle; mod config; mod notifier; @@ -139,6 +140,8 @@ async fn shutdown_signal() { struct Args { #[clap(short, long, default_value = "config.toml")] config: String, + #[clap(long = "notify-test", help = "test notify, default:false")] + notify_test: bool, } async fn serv_tcp() -> Result<()> { @@ -215,7 +218,8 @@ async fn serv_tcp() -> Result<()> { }); } } - +use std::thread; +use std::time::Duration; #[tokio::main] async fn main() -> Result<()> { pretty_env_logger::init(); @@ -230,10 +234,11 @@ async fn main() -> Result<()> { process::exit(1); } + // init notifier + *notifier::NOTIFIER_HANDLE.lock().unwrap() = Some(Handle::current()); let cfg = G_CONFIG.get().unwrap(); let notifies: Arc>>> = Arc::new(Mutex::new(Vec::new())); - // init notifier if cfg.tgbot.enabled { let o = Box::new(notifier::tgbot::TGBot::new(&cfg.tgbot)); notifies.lock().unwrap().push(o); @@ -246,6 +251,18 @@ async fn main() -> Result<()> { let o = Box::new(notifier::email::Email::new(&cfg.email)); notifies.lock().unwrap().push(o); } + // init notifier end + + // notify test + if args.notify_test { + for notifier in &*notifies.lock().unwrap() { + eprintln!("send test message to {}", notifier.kind()); + notifier.notify_test().unwrap(); + } + thread::sleep(Duration::from_millis(7000)); // TODO: wait + eprintln!("Please check for notifications"); + process::exit(0); + } // init mgr let mut mgr = crate::stats::StatsMgr::new(); diff --git a/server/src/notifier/email.rs b/server/src/notifier/email.rs index 207f449c..593f3a3a 100644 --- a/server/src/notifier/email.rs +++ b/server/src/notifier/email.rs @@ -5,7 +5,7 @@ use lettre::{ transport::smtp::authentication::Credentials, AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor, }; -use log::{error, info, trace}; +use log::{error, info}; use serde::{Deserialize, Serialize}; use crate::notifier::{add_template, get_tag, render_template, Event, HostStat, NOTIFIER_HANDLE}; @@ -106,8 +106,11 @@ impl crate::notifier::Notifier for Email { KIND } + fn notify_test(&self) -> Result<()> { + self.send_msg("❗ServerStatus test msg".to_string()) + } + fn notify(&self, e: &Event, stat: &HostStat) -> Result<()> { - trace!("{} notify {:?} => {:?}", self.kind(), e, stat); match *e { Event::NodeUp | Event::NodeDown => render_template(KIND, get_tag(e), stat) .map(|content| self.send_msg(content)) diff --git a/server/src/notifier/mod.rs b/server/src/notifier/mod.rs index 3c953fac..371b561f 100644 --- a/server/src/notifier/mod.rs +++ b/server/src/notifier/mod.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use minijinja::{context, Environment}; +use minijinja::{context, Environment, Source}; use once_cell::sync::Lazy; use std::sync::Mutex; use tokio::runtime::Handle; @@ -23,6 +23,7 @@ pub enum Event { pub trait Notifier { fn kind(&self) -> &'static str; fn notify(&self, e: &Event, stat: &HostStat) -> Result<()>; + fn notify_test(&self) -> Result<()>; } fn get_tag(e: &Event) -> &'static str { @@ -47,7 +48,7 @@ fn add_template< .lock() .as_mut() .map(|env| { - let mut s = env.source().unwrap().to_owned(); + let mut s = env.source().unwrap_or(&Source::new()).to_owned(); s.add_template(tpl_name, tpl).unwrap(); env.set_source(s); }) diff --git a/server/src/notifier/tgbot.rs b/server/src/notifier/tgbot.rs index a8ac6175..81367f67 100644 --- a/server/src/notifier/tgbot.rs +++ b/server/src/notifier/tgbot.rs @@ -1,6 +1,6 @@ #![deny(warnings)] use anyhow::Result; -use log::{error, info, trace}; +use log::{error, info}; use reqwest; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -91,8 +91,11 @@ impl crate::notifier::Notifier for TGBot { KIND } + fn notify_test(&self) -> Result<()> { + self.send_msg("❗ServerStatus test msg".to_string()) + } + fn notify(&self, e: &Event, stat: &HostStat) -> Result<()> { - trace!("{} notify {:?} => {:?}", self.kind(), e, stat); match *e { Event::NodeUp | Event::NodeDown => render_template(KIND, get_tag(e), stat) .map(|content| self.send_msg(content)) diff --git a/server/src/notifier/wechat.rs b/server/src/notifier/wechat.rs index caeb2350..207e4491 100644 --- a/server/src/notifier/wechat.rs +++ b/server/src/notifier/wechat.rs @@ -1,6 +1,6 @@ #![deny(warnings)] use anyhow::Result; -use log::{error, info, trace}; +use log::{error, info}; use reqwest; use serde::{Deserialize, Serialize}; use serde_json; @@ -127,8 +127,11 @@ impl crate::notifier::Notifier for WeChat { KIND } + fn notify_test(&self) -> Result<()> { + self.send_msg("❗ServerStatus test msg".to_string()) + } + fn notify(&self, e: &Event, stat: &HostStat) -> Result<()> { - trace!("{} notify {:?} => {:?}", self.kind(), e, stat); match *e { Event::NodeUp | Event::NodeDown => render_template(KIND, get_tag(e), stat) .map(|content| self.send_msg(content)) diff --git a/server/src/stats.rs b/server/src/stats.rs index c9b56fd0..070984e6 100644 --- a/server/src/stats.rs +++ b/server/src/stats.rs @@ -220,13 +220,13 @@ impl StatsMgr { }); // notify thread - *NOTIFIER_HANDLE.lock().unwrap() = Some(Handle::current()); thread::spawn(move || loop { while let Ok(msg) = notifier_rx.recv() { let (e, stat) = msg; let notifiers = &*notifies.lock().unwrap(); trace!("recv notify => {:?}, {:?}", e, stat); for notifier in notifiers { + trace!("{} notify {:?} => {:?}", notifier.kind(), e, stat); notifier.notify(&e, stat.borrow()); } }