This repository was archived by the owner on Oct 27, 2023. It is now read-only.
Description 现象:增加了kratos的tracing中间件后,在gin.Context中获取不到traceid。
示例代码:
func NewHTTPServer(c *conf.Server, logger log.Logger) *http.Server {
engine := gin.New()
engine.Use(gin.Logger(), kgin.Middlewares(
recovery.Recovery(),
tracing.Server(),
))
engine.GET("/dummy", func(c *gin.Context) {
ctx := c.Request.Context()
span := trace.SpanContextFromContext(ctx)
if span.HasTraceID() {
fmt.Println("found traceid ", span.TraceID().String())
} else {
fmt.Println("no traceid")
}
})
srv := http.NewServer(http.Address(":18200"))
srv.HandlePrefix("/", engine)
return srv
}
请求示例:
curl http://127.0.0.1:18200/dummy
"no traceid"
原因:
kratos中间件在调用next函数时,接收context为参数并传递给下一个next处理。tracing.Server()中间件使用WithValue方法延长了context链。
// Handler defines the handler invoked by Middleware.
type Handler func(ctx context.Context, req interface{}) (interface{}, error)
在原生kratos中,context是传递的,这没有问题。但gin里总是使用gin.Conetxt。在gin.Context链之上的上下文都无法检索到。
因此需要在kratos中间件处理完成时,将最后的context重新绑定到gin.Request上。
next := func(ctx context.Context, req interface{}) (interface{}, error) {
c.Next()
var err error
if c.Writer.Status() >= 400 {
err = errors.Errorf(c.Writer.Status(), errors.UnknownReason, errors.UnknownReason)
}
return c.Writer, err
}
next = chain(next)
ctx := NewGinContext(c.Request.Context(), c)
c.Request = c.Request.WithContext(ctx)
if ginCtx, ok := FromGinContext(ctx); ok {
thttp.SetOperation(ctx, ginCtx.FullPath())
}
next(c.Request.Context(), c.Request) // 注意:这里的next实际是kratos注册的第一个中间件,所有其他中间件依次执行后将调用上面的next回调函数。需要在这里将最后的context重新绑定到gin.Request。
Reactions are currently unavailable
现象:增加了kratos的tracing中间件后,在gin.Context中获取不到traceid。
示例代码:
请求示例:
原因:
kratos中间件在调用next函数时,接收context为参数并传递给下一个next处理。
tracing.Server()中间件使用WithValue方法延长了context链。在原生kratos中,context是传递的,这没有问题。但gin里总是使用gin.Conetxt。在gin.Context链之上的上下文都无法检索到。
因此需要在kratos中间件处理完成时,将最后的context重新绑定到gin.Request上。