Fiber 默认不生成请求 ID 是因设计上将链路追踪视为可选能力,需开发者按需启用;官方 fiber.RequestID 中间件可自动生成 UUID v4 请求 ID 并写入响应头与上下文,但不兼容 OpenTelemetry,对接需手动解析 traceparent、绑定 span 并写回 X-Request-ID。

为什么 Fiber 默认不生成请求 ID?
Fiber 的中间件体系里,fiber.New() 初始化的实例默认不注入任何请求标识,包括 Trace ID 或 Request ID。这不是遗漏,而是设计取向:Fiber 把链路追踪视为可选、可插拔的能力,由开发者按需组合。如果你看到日志里全是 <nil></nil> 或空字符串,大概率是没启用任何 ID 生成逻辑,也不是框架 bug。
用 fiber.RequestID 中间件最简单
官方维护的 fiber.RequestID 中间件会自动生成 UUID v4 格式的请求 ID,并写入响应头 X-Request-ID 和上下文值 fiber.Context.Locals("requestid")。它默认不覆盖已有 ID(比如上游已透传),适合大多数场景。
实操建议:
- 在
app.Use(fiber.RequestID())后注册其他中间件,确保后续能读到 ID - 若需自定义格式(如带服务前缀),传入
fiber.RequestIDConfig,改写Generator字段,返回string - 注意:该中间件不参与 OpenTracing / OpenTelemetry 标准,只解决“有 ID 可打日志”这个基本需求
app := fiber.New()
app.Use(fiber.RequestID(fiber.RequestIDConfig{
Generator: func() string {
return "svc-a-" + uuid.NewString()
},
}))
对接 OpenTelemetry 需要手动注入 trace ID
如果你已在用 go.opentelemetry.io/otel,Fiber 本身不自动集成 trace context 解析。必须显式从请求头(如 traceparent)提取 span context,并绑定到 fiber.Ctx 的 context.Context 上,否则 trace.SpanFromContext(c.Context()) 拿不到活跃 span。
立即学习“go语言免费学习笔记(深入)”;
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
关键点:
- 用
otel.GetTextMapPropagator().Extract()从c.Request().Header解析 trace context - 调用
c.Context()获取当前 context,再用trace.ContextWithSpan()绑定 span - 生成新 trace ID 的时机应为“无上游 traceparent 时”,避免覆盖调用链
- 别忘了把 trace ID 写回
X-Request-ID响应头,方便日志串联
容易被忽略的坑:日志中间件顺序和 Context 生命周期
很多人把日志中间件放在最前面,但此时 fiber.RequestID 还没运行,c.Locals("requestid") 是空的;或者在 handler 里用 c.Context().Value() 取 ID,却忘了 c.Context() 默认不携带 Locals 数据——那是 Fiber 自己的存储,和 Go 原生 context 是两套。
正确姿势:
- 日志中间件必须在
RequestID之后注册 - 取 ID 优先用
c.Locals("requestid").(string),不是c.Context().Value() - 如果要用 OpenTelemetry 的 trace ID 打日志,得从 span 中显式获取:
span.SpanContext().TraceID().String()
链路 ID 不是加个中间件就完事,它得贯穿解析、传播、记录、输出四个环节。少一环,日志就断掉。

















