slog中间件添加的上下文属性在使用Logger.With派生日志实例时不生效的问题咨询
slog中间件添加的上下文属性在使用Logger.With派生日志实例时不生效的问题咨询
大家好,我在使用Go 1.24.2的标准库slog时遇到了一个困扰,想请教下各位:
问题背景
我实现了一个自定义的slog处理器中间件ContextHandler,用来自动从context.Context中提取请求域的属性(比如session_id)并添加到日志记录里。这个中间件会包装基础处理器(比如slog.JSONHandler或者第三方的devslog.Handler),代码大致如下:
// ContextHandler middleware type ContextHandler struct { slog.Handler } func NewContextHandler(handler slog.Handler) *ContextHandler { return &ContextHandler{Handler: handler} } func (h *ContextHandler) Handle(ctx context.Context, r slog.Record) error { // Example: Get session ID from context if sessionID, ok := contextkeys.GetSessionID(ctx); ok { r.AddAttrs(slog.String("session_id", sessionID)) // Add attribute to record } // Pass record to the next handler return h.Handler.Handle(ctx, r) } // Logger creation wraps the base handler func NewLogger( /* ... */ ) *slog.Logger { var baseHandler slog.Handler // ... logic to create baseHandler (JSON, devslog, etc.) ... contextAwareHandler := NewContextHandler(baseHandler) logger := slog.New(contextAwareHandler) return logger }
在我的gRPC处理器中,我注入了这个NewLogger创建的日志实例:
type AuthHandler struct { // ... other fields logger *slog.Logger } func NewAuthHandler( /* ... */ logger *slog.Logger) *AuthHandler { return &AuthHandler{ /* ... */ logger: logger} }
观察到的现象
- 正常生效的场景:直接使用注入的logger调用带上下文的方法时,中间件添加的
session_id能正确出现在日志输出里:
// Inside handler method func (h *AuthHandler) SomeMethod(ctx context.Context, /* ... */) { // ... h.logger.InfoContext(ctx, "Operation successful") // Output includes "session_id=xyz" }
- 不生效的场景:当我用
.With()派生出一个新的日志实例,再调用带上下文的方法时,中间件添加的session_id不会出现在最终日志里(或者出现得很不稳定),但通过.With()添加的属性(比如op)是正常显示的:
// Inside handler method func (h *AuthHandler) SomeMethod(ctx context.Context, /* ... */) { const op = "Handler.SomeMethod" // Create derived logger log := h.logger.With(slog.String("op", op)) // ... log.InfoContext(ctx, "Operation successful") // Output includes "op=Handler.SomeMethod" BUT NOT "session_id=xyz" }
我的疑问
- 这种行为是预期的吗?
- 为什么通过处理器中间件用
r.AddAttrs动态添加的属性,在使用.With()派生的日志实例调用时无法正常生效? - 有没有标准或者推荐的方式,能确保中间件添加的属性即使在使用
.With()派生日志实例时也能可靠生效?
内容来源于stack exchange
相关产品推荐
相关产品推荐

