如何在Golang slog包中添加Trace ID/Correlation ID实现请求链路追踪
给Go slog日志添加Trace/Correlation ID的实现方法
核心逻辑
slog默认不会主动读取context中的值并注入日志,需要通过自定义Handler包装JSONHandler,实现从context提取Trace ID并添加到日志字段的功能。
完整实现代码
1. 自定义TraceHandler
package main import ( "context" "log/slog" "os" ) // 自定义Handler,包装原生JSONHandler type TraceHandler struct { slog.Handler } // 重写Handle方法,注入Trace ID func (h *TraceHandler) Handle(ctx context.Context, r slog.Record) error { // 从context中提取trace_id(建议用常量代替字符串key避免拼写错误) if traceID, ok := ctx.Value("trace_id").(string); ok { r.AddAttrs(slog.String("trace_id", traceID)) } return h.Handler.Handle(ctx, r) } // 实现WithAttrs,保持日志器链式调用能力 func (h *TraceHandler) WithAttrs(attrs []slog.Attr) slog.Handler { return &TraceHandler{Handler: h.Handler.WithAttrs(attrs)} } // 实现WithGroup,保持日志器分组能力 func (h *TraceHandler) WithGroup(name string) slog.Handler { return &TraceHandler{Handler: h.Handler.WithGroup(name)} }
2. 初始化日志器并使用
func main() { // 创建原生JSONHandler jsonHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ AddSource: true, }) // 用自定义TraceHandler包装,设置为默认日志器 logger := slog.New(&TraceHandler{Handler: jsonHandler}) slog.SetDefault(logger) // 模拟请求上下文,注入trace_id ctx := context.Background() ctx = context.WithValue(ctx, "trace_id", "abc-123-xyz-789") // 业务代码中记录日志,trace_id会自动加入输出 slog.InfoContext(ctx, "请求进入", "path", "/api/v1/user") slog.InfoContext(ctx, "用户信息查询完成", "user_id", 456) slog.ErrorContext(ctx, "操作失败", "err_msg", "数据库连接超时") }
补充说明
- 建议定义常量作为context的key,避免硬编码字符串出错:
const TraceIDKey = "trace_id" - 如果使用OpenTelemetry等链路追踪框架,可直接从context中提取官方标准的trace ID,无需自定义key
内容的提问来源于stack exchange,提问作者Manzurul Hoque Rumi
相关产品推荐
相关产品推荐

