98 lines
2.2 KiB
Go
98 lines
2.2 KiB
Go
package notifier
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"sysmonitord/internal/config"
|
|
"sysmonitord/internal/notifier/mail"
|
|
"sysmonitord/pkg/logger"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type AlertEvent struct {
|
|
Type string
|
|
Path string
|
|
Reason string
|
|
Details string
|
|
}
|
|
|
|
type Alerter struct {
|
|
cfg config.NotificationConfig
|
|
mailer *mail.Mailer
|
|
eventChan chan AlertEvent
|
|
buffer []AlertEvent
|
|
mu sync.Mutex
|
|
timer *time.Timer
|
|
interval time.Duration
|
|
}
|
|
|
|
func NewAlerter(cfg config.NotificationConfig) *Alerter {
|
|
return &Alerter{
|
|
cfg: cfg,
|
|
mailer: mail.NewMailer(cfg.Email),
|
|
eventChan: make(chan AlertEvent, 100),
|
|
buffer: make([]AlertEvent, 0),
|
|
interval: 1 * time.Minute, // Todo: 可配置化
|
|
}
|
|
}
|
|
|
|
func (a *Alerter) Start() {
|
|
go a.loop()
|
|
}
|
|
|
|
func (a *Alerter) PushAlert(event AlertEvent) {
|
|
select {
|
|
case a.eventChan <- event:
|
|
logger.Log.Debug("[notifier] 推送告警事件", zap.String("path", event.Path), zap.String("reason", event.Reason))
|
|
default:
|
|
logger.Log.Warn("[notifier] 告警事件通道已满,丢弃告警", zap.String("path", event.Path), zap.String("reason", event.Reason))
|
|
}
|
|
}
|
|
|
|
func (a *Alerter) loop() {
|
|
a.timer = time.NewTimer(a.interval)
|
|
|
|
for {
|
|
select {
|
|
case event := <-a.eventChan:
|
|
a.mu.Lock()
|
|
a.buffer = append(a.buffer, event)
|
|
a.mu.Unlock()
|
|
logger.Log.Debug("[notifier] 收到告警,加入待发送序列", zap.String("path", event.Path))
|
|
|
|
case <-a.timer.C:
|
|
a.mu.Lock()
|
|
if len(a.buffer) > 0 {
|
|
a.sendAlert()
|
|
a.buffer = make([]AlertEvent, 0)
|
|
}
|
|
a.mu.Unlock()
|
|
|
|
a.timer.Reset(a.interval)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (a *Alerter) sendAlert() {
|
|
if len(a.buffer) == 0 {
|
|
return
|
|
}
|
|
|
|
subject := fmt.Sprintf("【Sysmonitor】新增 %d 个告警", len(a.buffer))
|
|
body := "以下是最近的告警事件:\n\n"
|
|
|
|
for _, event := range a.buffer {
|
|
body += fmt.Sprintf("- [%s] %s: %s (%s)\n", event.Type, event.Path, event.Reason, event.Details)
|
|
}
|
|
|
|
body += "\n请及时关注系统安全状况。"
|
|
|
|
if err := a.mailer.Send(subject, body); err != nil {
|
|
logger.Log.Error("[notifier] 发送告警邮件失败", zap.Error(err))
|
|
} else {
|
|
logger.Log.Debug("[notifier] 告警邮件发送成功", zap.Int("count", len(a.buffer)))
|
|
}
|
|
}
|