feat(notify): dummy notifier writing structured log lines

This commit is contained in:
2026-04-28 22:28:47 +08:00
parent d9a8c04195
commit 83c63c5f93
2 changed files with 58 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
package notify
import (
"context"
"log/slog"
)
// DummyNotifier 仅用于本地与测试环境,将通知以结构化日志形式打印,不做任何
// 真实外发。生产环境如未配置真实 Notifier,可注册此实现作为兜底,避免投递
// 流程因缺少 channel 而中断。
type DummyNotifier struct {
log *slog.Logger
}
// NewDummyNotifier 用调用方提供的 logger 构造 DummyNotifier。logger 为 nil 时
// 调用 Send 会 panic,这是显式契约——上层负责传入有效 logger。
func NewDummyNotifier(log *slog.Logger) *DummyNotifier { return &DummyNotifier{log: log} }
// Name 返回 ChannelDummy,标识该 Notifier 的通道身份。
func (d *DummyNotifier) Name() Channel { return ChannelDummy }
// Send 将消息以 Info 级别结构化日志输出。ctx 在 dummy 实现中不消费,
// 真实通道(email/webhook/IM)应尊重 ctx 的取消与超时。
func (d *DummyNotifier) Send(_ context.Context, msg Message) error {
d.log.Info("notify[dummy]",
"topic", msg.Topic,
"severity", string(msg.Severity),
"user_id", msg.UserID.String(),
"title", msg.Title,
)
return nil
}
+26
View File
@@ -0,0 +1,26 @@
package notify
import (
"bytes"
"context"
"log/slog"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
)
func TestDummy_Send_LogsAndReturnsNil(t *testing.T) {
var buf bytes.Buffer
log := slog.New(slog.NewJSONHandler(&buf, nil))
d := NewDummyNotifier(log)
require.Equal(t, ChannelDummy, d.Name())
err := d.Send(context.Background(), Message{
ID: uuid.New(), UserID: uuid.New(),
Topic: "x", Severity: SeverityInfo, Title: "hi", Body: "world",
})
require.NoError(t, err)
require.Contains(t, buf.String(), "notify[dummy]")
require.Contains(t, buf.String(), `"topic":"x"`)
}