Files
iotlcm/internal/notify/alertstate.go
T
MiFaZhan 5732bf3384 chore: 初始开源发布
iotlcm-bot:独立飞书应用机器人(读取 Worker 终态 Run JSON,渲染并发送全量同步结果卡片)。

- Go module:git.5iot.com/iotlcm/iotlcm-bot → git.5iot.com/iotlcm-public/iotlcm-bot
- 飞书凭据占位:appId/appSecret/chatId → ${FEISHU_APP_ID}/${FEISHU_APP_SECRET}/${FEISHU_CHAT_ID}
- 移除内部资产:CI 触发器
- Dockerfile 改用公共基础镜像(golang:1.25-alpine → scratch)
- README 重写(命令/配置/挂载契约/常见问题),去掉内部环境路径
- 补 Apache-2.0 LICENSE,LF 行尾 + .gitattributes
2026-10-22 16:14:24 +08:00

71 lines
2.0 KiB
Go

package notify
import (
"encoding/json"
"os"
"path/filepath"
"time"
)
// alertState 记录告警节流信息。
//
// 为什么必须落盘:进程检测到挂载失效后会主动退出、由 restart 策略拉起。
// 若节流时间只存在内存里,重启后 lastAlert 归零,会立刻再次告警 ——
// 持续故障就变成「每轮重启都发一条飞书」,把真正的告警淹成骚扰。
type alertState struct {
// LastDegradedAlert 是上次发送「归档目录不可用」告警的时间。
LastDegradedAlert time.Time `json:"lastDegradedAlert,omitempty"`
// LastDegradedReason 用于在故障原因变化时立即重新告警。
LastDegradedReason string `json:"lastDegradedReason,omitempty"`
// ExitCount 统计因挂载失效而退出的累计次数,用于识别「反复重启」。
ExitCount int `json:"exitCount,omitempty"`
}
func alertStatePath(stateDir string) string {
return filepath.Join(stateDir, "alert-state.json")
}
func loadAlertState(stateDir string) alertState {
var st alertState
if stateDir == "" {
return st
}
body, err := os.ReadFile(alertStatePath(stateDir))
if err != nil {
return st
}
_ = json.Unmarshal(body, &st)
return st
}
func saveAlertState(stateDir string, st alertState) error {
if stateDir == "" {
return nil
}
path := alertStatePath(stateDir)
if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
return err
}
body, err := json.MarshalIndent(st, "", " ")
if err != nil {
return err
}
tmp := path + ".tmp"
if err := os.WriteFile(tmp, body, 0o600); err != nil {
return err
}
return os.Rename(tmp, path)
}
// shouldAlert 判断是否该发告警:间隔到了,或故障原因发生变化。
func (st alertState) shouldAlert(reason string, now time.Time, interval time.Duration) bool {
if st.LastDegradedAlert.IsZero() {
return true
}
if reason != st.LastDegradedReason {
// 原因变了(例如从「目录不存在」变成「不可读」)值得立刻提醒。
return true
}
return now.Sub(st.LastDegradedAlert) >= interval
}