fix(logger): 修复 caller 字段与 OpsSystemLogSink 停止刷盘
修复点: - zap logger 不再强制 AddCallerSkip(1),确保 caller 指向真实调用点 - slog handler 避免重复写 time 字段 - OpsSystemLogSink 优先从字段 component 识别业务组件;停止时 drain 队列并用可用 ctx 刷盘 补充:新增/完善对应单测
This commit is contained in:
@@ -36,11 +36,29 @@ func TestOpsSystemLogSink_ShouldIndex(t *testing.T) {
|
||||
event: &logger.LogEvent{Level: "info", Component: "http.access"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "access component from fields (real zap path)",
|
||||
event: &logger.LogEvent{
|
||||
Level: "info",
|
||||
Component: "",
|
||||
Fields: map[string]any{"component": "http.access"},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "audit component",
|
||||
event: &logger.LogEvent{Level: "info", Component: "audit.log_config_change"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "audit component from fields (real zap path)",
|
||||
event: &logger.LogEvent{
|
||||
Level: "info",
|
||||
Component: "",
|
||||
Fields: map[string]any{"component": "audit.log_config_change"},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "plain info",
|
||||
event: &logger.LogEvent{Level: "info", Component: "app"},
|
||||
@@ -205,6 +223,47 @@ func TestOpsSystemLogSink_FlushFailureUpdatesHealth(t *testing.T) {
|
||||
t.Fatalf("write_failed_count not updated")
|
||||
}
|
||||
|
||||
func TestOpsSystemLogSink_StopFlushUsesActiveContextAndDrainsQueue(t *testing.T) {
|
||||
var inserted int64
|
||||
var canceledCtxCalls int64
|
||||
repo := &opsRepoMock{
|
||||
BatchInsertSystemLogsFn: func(ctx context.Context, inputs []*OpsInsertSystemLogInput) (int64, error) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
atomic.AddInt64(&canceledCtxCalls, 1)
|
||||
return 0, err
|
||||
}
|
||||
atomic.AddInt64(&inserted, int64(len(inputs)))
|
||||
return int64(len(inputs)), nil
|
||||
},
|
||||
}
|
||||
|
||||
sink := NewOpsSystemLogSink(repo)
|
||||
sink.batchSize = 200
|
||||
sink.flushInterval = time.Hour
|
||||
sink.Start()
|
||||
|
||||
sink.WriteLogEvent(&logger.LogEvent{
|
||||
Time: time.Now().UTC(),
|
||||
Level: "warn",
|
||||
Component: "app",
|
||||
Message: "pending-on-shutdown",
|
||||
Fields: map[string]any{"component": "http.access"},
|
||||
})
|
||||
|
||||
sink.Stop()
|
||||
|
||||
if got := atomic.LoadInt64(&inserted); got != 1 {
|
||||
t.Fatalf("inserted = %d, want 1", got)
|
||||
}
|
||||
if got := atomic.LoadInt64(&canceledCtxCalls); got != 0 {
|
||||
t.Fatalf("canceled ctx calls = %d, want 0", got)
|
||||
}
|
||||
health := sink.Health()
|
||||
if health.WrittenCount != 1 {
|
||||
t.Fatalf("written_count = %d, want 1", health.WrittenCount)
|
||||
}
|
||||
}
|
||||
|
||||
type stringerValue string
|
||||
|
||||
func (s stringerValue) String() string { return string(s) }
|
||||
|
||||
Reference in New Issue
Block a user