[notifier] 新增email告警方式
This commit is contained in:
parent
9970e93665
commit
18e1672114
|
|
@ -9,6 +9,7 @@ import (
|
|||
"sysmonitord/internal/monitor/detector"
|
||||
"sysmonitord/internal/monitor/timer"
|
||||
"sysmonitord/internal/monitor/watcher"
|
||||
"sysmonitord/internal/notifier"
|
||||
"sysmonitord/internal/scanner/file"
|
||||
"sysmonitord/internal/scanner/process"
|
||||
"sysmonitord/internal/storage"
|
||||
|
|
@ -107,6 +108,10 @@ var StartCmd = &cobra.Command{
|
|||
procScheduler := timer.NewScheduler(time.Duration(cfg.Scanner.Process.Interval)*time.Second, procDetector)
|
||||
procScheduler.Start()
|
||||
|
||||
// ====== 启动告警管理器 ======
|
||||
alerter := notifier.NewAlerter(cfg.Notification)
|
||||
alerter.Start()
|
||||
|
||||
logger.Log.Info("系统监控守护服务已启动,正在监控系统变化...")
|
||||
|
||||
quit := make(chan os.Signal, 1)
|
||||
|
|
@ -126,6 +131,14 @@ var StartCmd = &cobra.Command{
|
|||
fileDetector.HandleEvent(event.Path, event.Op.String())
|
||||
}
|
||||
|
||||
// test
|
||||
alerter.PushAlert(notifier.AlertEvent{
|
||||
Type: "File",
|
||||
Path: event.Path,
|
||||
Reason: event.Op.String(),
|
||||
Details: "To test",
|
||||
})
|
||||
|
||||
case err := <-mon.Errors():
|
||||
logger.Log.Error("文件监听错误", zap.Error(err))
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,24 @@ type Config struct {
|
|||
Audit AuditConfig `yaml:"audit"`
|
||||
Scanner ScannerConfig `yaml:"scanner"`
|
||||
Storage StorageConfig `yaml:"storage"`
|
||||
Notification NotificationConfig `yaml:"notification"`
|
||||
}
|
||||
|
||||
type NotificationConfig struct {
|
||||
Email EmailConfig `yaml:"email"`
|
||||
}
|
||||
|
||||
type EmailConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Recipients []string `yaml:"recipients"`
|
||||
SMTP SMTPConfig `yaml:"smtp"`
|
||||
}
|
||||
|
||||
type SMTPConfig struct {
|
||||
Server string `yaml:"server"`
|
||||
Port int `yaml:"port"`
|
||||
Username string `yaml:"username"`
|
||||
Password string `yaml:"password"`
|
||||
}
|
||||
|
||||
type LogConfig struct {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
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)))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package mail
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/smtp"
|
||||
"sysmonitord/internal/config"
|
||||
"sysmonitord/pkg/logger"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type Mailer struct {
|
||||
cfg config.EmailConfig
|
||||
}
|
||||
|
||||
func NewMailer(cfg config.EmailConfig) *Mailer {
|
||||
return &Mailer{cfg: cfg}
|
||||
}
|
||||
|
||||
func (m *Mailer) Send(subject, body string) error {
|
||||
if !m.cfg.Enabled {
|
||||
logger.Log.Debug("[notifier] 未启用邮件通知,跳过....")
|
||||
return nil
|
||||
}
|
||||
|
||||
headers := make(map[string]string)
|
||||
headers["From"] = m.cfg.SMTP.Username
|
||||
headers["To"] = m.cfg.Recipients[0]
|
||||
headers["Subject"] = subject
|
||||
|
||||
message := ""
|
||||
for k, v := range headers {
|
||||
message += fmt.Sprintf("%s: %s\r\n", k, v)
|
||||
}
|
||||
message += "\r\n" + body
|
||||
|
||||
auth := smtp.PlainAuth("", m.cfg.SMTP.Username, m.cfg.SMTP.Password, m.cfg.SMTP.Server)
|
||||
addr := fmt.Sprintf("%s:%d", m.cfg.SMTP.Server, m.cfg.SMTP.Port)
|
||||
|
||||
logger.Log.Info("[notifier] 发送邮件通知", zap.String("subject", subject), zap.String("to", m.cfg.Recipients[0]))
|
||||
|
||||
err := smtp.SendMail(addr, auth, m.cfg.SMTP.Username, m.cfg.Recipients, []byte(message))
|
||||
if err != nil {
|
||||
logger.Log.Error("[notifier] 发送邮件失败", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Log.Info("[notifier] 邮件发送成功")
|
||||
return nil
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user