0

我阅读了有关删除 ThreadLocal 的所有决定,我可以理解。似乎传递request.Context()typecontext.Context赋予了管理范围服务的能力。

我正在使用logrus日志记录并希望记录一个requestId从 midlleware 生成的 udidgin

我知道我可以做这样的事情

func Authentication(conf Configuration, logger ILogger, cache ICacheService) gin.HandlerFunc {
    return func(c *gin.Context) {

        logger := logrus.WithContext(c)
        c.Set("traceId", uuid.New().String())
        c.Next()
    }
}

并且绕过条目,甚至将条目存储在上下文中,无论如何都可以,但是......我也有一个RedisMongoDb客户端,singletons我用我自己的包包装它们,以方便记录任何传出的 I\O 请求。

因为它们是单例,所以我不能context.Context将它传递给构造函数,但我必须将它传递给每个方法,比如GetKey SetKet等等。

在 Singleton 服务中使用 context \ request id 日志记录的任何常见模式?

4

2 回答 2

2

惯用的方法是传递context.Context给每个方法。事实上,上下文不应该在构造函数中传递或存储为结构成员。如文档中所述:

不要将上下文存储在结构类型中;相反,将 Context 显式传递给需要它的每个函数。

于 2020-05-10T19:00:25.307 回答
0

我用我自己的包包装它们,以方便记录任何传出的 I\O 请求。

具有良好 API 设计的库提供了传输功能的自定义,或者可能提供了为此类目的添加钩子的能力,使用闭包上下文使您可以使用日志记录来装饰它们。Redis 应该支持自定义拨号器,您可以使用闭包函数直接注入日志记录活动,该函数可以访问上下文和记录器,因此如果这是唯一的原因,则无需进行包装。

更简洁的软件设计是将记录器实例化一次并将其传递给您的依赖项。Context.Values 是请求范围值,而不是范围服务。为此类目的使用动态上下文 api 会使您的软件很难预测,最好使用具有依赖注入的强类型 API 的便利性。

希望能帮助到你!

于 2020-05-10T23:23:56.210 回答