feat(monitor): 1 分钟采集 + 连续 N 次异常才告警(去抖)
避免瞬时尖峰/部署窗口误报(此前 sing-box 部署期 activating 触发了一次误报)。 - 采集间隔 5min → 1min(MONITOR_INTERVAL_MIN=1) - 新增 MONITOR_BREACH_RUNS=5:连续 5 次采样都异常才告警一次(状态存 /var/lib/pangolin-monitor/breach_count);恢复后发一条恢复通知并清零 - 去掉 MONITOR_SEND_OK_PULSE(被去抖逻辑取代) - 已在 racknerd 验证:连 4 次异常不报、恢复清零 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -23,9 +23,11 @@ TELEGRAM_BOT_TOKEN=""
|
|||||||
TELEGRAM_CHAT_ID=""
|
TELEGRAM_CHAT_ID=""
|
||||||
# 本节点在告警里显示的名字
|
# 本节点在告警里显示的名字
|
||||||
NODE_NAME="racknerd-la"
|
NODE_NAME="racknerd-la"
|
||||||
# 上报间隔(分钟)
|
# 采集间隔(分钟)
|
||||||
MONITOR_INTERVAL_MIN=5
|
MONITOR_INTERVAL_MIN=1
|
||||||
# 阈值(百分比);超过即告警
|
# 连续几次采集都异常才告警(去抖)。间隔 1min × 5 次 = 持续 5 分钟异常才报。
|
||||||
|
MONITOR_BREACH_RUNS=5
|
||||||
|
# 阈值(百分比);超过即算一次异常采样
|
||||||
CPU_ALERT_PCT=80
|
CPU_ALERT_PCT=80
|
||||||
MEM_ALERT_PCT=80
|
MEM_ALERT_PCT=80
|
||||||
DISK_ALERT_PCT=80
|
DISK_ALERT_PCT=80
|
||||||
@@ -33,5 +35,3 @@ DISK_ALERT_PCT=80
|
|||||||
MONITOR_UNITS="sing-box pangolin-agent"
|
MONITOR_UNITS="sing-box pangolin-agent"
|
||||||
# 出网连通探测目标
|
# 出网连通探测目标
|
||||||
MONITOR_NET_PROBE="https://www.cloudflare.com/cdn-cgi/trace"
|
MONITOR_NET_PROBE="https://www.cloudflare.com/cdn-cgi/trace"
|
||||||
# 周期性"健康"心跳是否也推送(true=每次都报,false=仅异常时报)
|
|
||||||
MONITOR_SEND_OK_PULSE=false
|
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ FW_ALLOW_UDP="443"
|
|||||||
TELEGRAM_BOT_TOKEN=""
|
TELEGRAM_BOT_TOKEN=""
|
||||||
TELEGRAM_CHAT_ID=""
|
TELEGRAM_CHAT_ID=""
|
||||||
NODE_NAME="$(hostname)"
|
NODE_NAME="$(hostname)"
|
||||||
MONITOR_INTERVAL_MIN=5
|
MONITOR_INTERVAL_MIN=1
|
||||||
|
MONITOR_BREACH_RUNS=5
|
||||||
CPU_ALERT_PCT=80
|
CPU_ALERT_PCT=80
|
||||||
MEM_ALERT_PCT=80
|
MEM_ALERT_PCT=80
|
||||||
DISK_ALERT_PCT=80
|
DISK_ALERT_PCT=80
|
||||||
MONITOR_UNITS="sing-box pangolin-agent"
|
MONITOR_UNITS="sing-box pangolin-agent"
|
||||||
MONITOR_NET_PROBE="https://www.cloudflare.com/cdn-cgi/trace"
|
MONITOR_NET_PROBE="https://www.cloudflare.com/cdn-cgi/trace"
|
||||||
MONITOR_SEND_OK_PULSE=false
|
|
||||||
|
|
||||||
if [ -f "$SCRIPT_DIR/bootstrap.env" ]; then
|
if [ -f "$SCRIPT_DIR/bootstrap.env" ]; then
|
||||||
log "读取配置 $SCRIPT_DIR/bootstrap.env"
|
log "读取配置 $SCRIPT_DIR/bootstrap.env"
|
||||||
@@ -199,7 +199,7 @@ MEM_ALERT_PCT=${MEM_ALERT_PCT}
|
|||||||
DISK_ALERT_PCT=${DISK_ALERT_PCT}
|
DISK_ALERT_PCT=${DISK_ALERT_PCT}
|
||||||
MONITOR_UNITS="${MONITOR_UNITS}"
|
MONITOR_UNITS="${MONITOR_UNITS}"
|
||||||
MONITOR_NET_PROBE="${MONITOR_NET_PROBE}"
|
MONITOR_NET_PROBE="${MONITOR_NET_PROBE}"
|
||||||
MONITOR_SEND_OK_PULSE=${MONITOR_SEND_OK_PULSE}
|
MONITOR_BREACH_RUNS=${MONITOR_BREACH_RUNS}
|
||||||
MENV
|
MENV
|
||||||
umask 022
|
umask 022
|
||||||
sed -e "s/__INTERVAL__/${MONITOR_INTERVAL_MIN}/g" \
|
sed -e "s/__INTERVAL__/${MONITOR_INTERVAL_MIN}/g" \
|
||||||
@@ -207,7 +207,7 @@ MENV
|
|||||||
install -m 644 "$SCRIPT_DIR/monitor/pangolin-monitor.service" /etc/systemd/system/pangolin-monitor.service
|
install -m 644 "$SCRIPT_DIR/monitor/pangolin-monitor.service" /etc/systemd/system/pangolin-monitor.service
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable --now pangolin-monitor.timer >/dev/null
|
systemctl enable --now pangolin-monitor.timer >/dev/null
|
||||||
log " 监控已装:每 ${MONITOR_INTERVAL_MIN} 分钟上报;发送一条启动通知"
|
log " 监控已装:每 ${MONITOR_INTERVAL_MIN} 分钟采集,连续 ${MONITOR_BREACH_RUNS} 次异常才告警;发送一条启动通知"
|
||||||
/usr/local/bin/pangolin-monitor --boot || true
|
/usr/local/bin/pangolin-monitor --boot || true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
# pangolin-monitor —— 节点自监控:采集 CPU/内存/磁盘/进程/网络,经 Telegram 上报。
|
# pangolin-monitor —— 节点自监控:采集 CPU/内存/磁盘/进程/网络,经 Telegram 上报。
|
||||||
# 由 systemd timer 定期触发(见 pangolin-monitor.timer)。配置在 /etc/pangolin-monitor.env。
|
# 由 systemd timer 定期触发(见 pangolin-monitor.timer)。配置在 /etc/pangolin-monitor.env。
|
||||||
#
|
#
|
||||||
# 阈值越界 / 受监控单元掉线 / 出网不通 → 标 🔴 并必报;
|
# 阈值越界 / 受监控单元掉线 / 出网不通 = 一次"异常采样";
|
||||||
# 一切正常 → 🟢,是否推送由 MONITOR_SEND_OK_PULSE 决定(心跳)。
|
# 连续 MONITOR_BREACH_RUNS 次异常才告警一次(去抖),恢复后发一条恢复通知。
|
||||||
|
# 建议配合 1 分钟一次的 timer:连续 5 次 = 持续 5 分钟异常才报。
|
||||||
# --boot:发送一条"初始化完成"启动通知。
|
# --boot:发送一条"初始化完成"启动通知。
|
||||||
#
|
#
|
||||||
# 注意:节点宕机后无法自报("不上报"类告警)需在常在线主机上跑 deadman-watch.sh(见 README)。
|
# 注意:节点宕机后无法自报("不上报"类告警)需在常在线主机上跑 deadman-watch.sh(见 README)。
|
||||||
@@ -17,7 +18,7 @@ ENV_FILE=/etc/pangolin-monitor.env
|
|||||||
: "${NODE_NAME:=$(hostname)}"
|
: "${NODE_NAME:=$(hostname)}"
|
||||||
: "${CPU_ALERT_PCT:=90}"; : "${MEM_ALERT_PCT:=90}"; : "${DISK_ALERT_PCT:=85}"
|
: "${CPU_ALERT_PCT:=90}"; : "${MEM_ALERT_PCT:=90}"; : "${DISK_ALERT_PCT:=85}"
|
||||||
: "${MONITOR_UNITS:=}"; : "${MONITOR_NET_PROBE:=https://www.cloudflare.com/cdn-cgi/trace}"
|
: "${MONITOR_UNITS:=}"; : "${MONITOR_NET_PROBE:=https://www.cloudflare.com/cdn-cgi/trace}"
|
||||||
: "${MONITOR_SEND_OK_PULSE:=true}"
|
: "${MONITOR_BREACH_RUNS:=5}" # 连续几次采样异常才告警(去抖)
|
||||||
|
|
||||||
send_tg() {
|
send_tg() {
|
||||||
local text="$1"
|
local text="$1"
|
||||||
@@ -73,21 +74,36 @@ main() {
|
|||||||
if curl -fsS --max-time 8 "$MONITOR_NET_PROBE" >/dev/null 2>&1; then net="ok"; else net="FAIL"; alert=1; fi
|
if curl -fsS --max-time 8 "$MONITOR_NET_PROBE" >/dev/null 2>&1; then net="ok"; else net="FAIL"; alert=1; fi
|
||||||
lines+=("出网: ${net}")
|
lines+=("出网: ${net}")
|
||||||
|
|
||||||
local head body ts
|
local ts metrics l
|
||||||
ts="$(date -u '+%Y-%m-%d %H:%M:%SZ')"
|
ts="$(date -u '+%Y-%m-%d %H:%M:%SZ')"
|
||||||
if $boot; then
|
metrics=""
|
||||||
head="🟢 [${NODE_NAME}] 初始化完成 / 监控已上线"
|
for l in "${lines[@]}"; do metrics+="${l}"$'\n'; done
|
||||||
elif [ "$alert" -eq 1 ]; then
|
|
||||||
head="🔴 [${NODE_NAME}] 异常告警"
|
|
||||||
else
|
|
||||||
head="🟢 [${NODE_NAME}] 正常"
|
|
||||||
fi
|
|
||||||
body="${head}\n${ts}\n"
|
|
||||||
printf -v body '%s\n%s\n' "$head" "$ts"
|
|
||||||
local l; for l in "${lines[@]}"; do body+="${l}"$'\n'; done
|
|
||||||
|
|
||||||
if $boot || [ "$alert" -eq 1 ] || [ "$MONITOR_SEND_OK_PULSE" = "true" ]; then
|
# ── 去抖:每次采集,但连续 MONITOR_BREACH_RUNS 次异常才告警(避免瞬时尖峰/重启误报)──
|
||||||
send_tg "$body"
|
local sdir=/var/lib/pangolin-monitor cntf alertedf cnt
|
||||||
|
mkdir -p "$sdir"
|
||||||
|
cntf="$sdir/breach_count"; alertedf="$sdir/alerted"
|
||||||
|
|
||||||
|
if $boot; then
|
||||||
|
send_tg "🟢 [${NODE_NAME}] 初始化完成 / 监控已上线"$'\n'"${ts}"$'\n'"${metrics}"
|
||||||
|
echo 0 > "$cntf"; rm -f "$alertedf"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$alert" -eq 1 ]; then
|
||||||
|
cnt=$(( $(cat "$cntf" 2>/dev/null || echo 0) + 1 ))
|
||||||
|
echo "$cnt" > "$cntf"
|
||||||
|
# 达到连续阈值且尚未告警过 → 发一次(不重复刷屏)
|
||||||
|
if [ "$cnt" -ge "$MONITOR_BREACH_RUNS" ] && [ ! -f "$alertedf" ]; then
|
||||||
|
send_tg "🔴 [${NODE_NAME}] 异常告警(连续 ${cnt} 次采样异常)"$'\n'"${ts}"$'\n'"${metrics}"
|
||||||
|
touch "$alertedf"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# 恢复:若此前已告警,发一条恢复通知
|
||||||
|
if [ -f "$alertedf" ]; then
|
||||||
|
send_tg "🟢 [${NODE_NAME}] 已恢复正常"$'\n'"${ts}"$'\n'"${metrics}"
|
||||||
|
fi
|
||||||
|
echo 0 > "$cntf"; rm -f "$alertedf"
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user