SLF4J初始化 - 替代记录器

Kul*_*mpa 9 logging scala logback slf4j race-condition

我正在Scala中做一个项目,我正在使用带有Logback的slf4j进行日志记录.现在,日志记录初始化似乎不是线程安全的.作为解决方案,slf4j正在创建替代记录器,即NoOp-loggers,它吞下初始化期间生成的日志语句.slf4j主页说明了这件事:

替代记录器是在底层日志记录系统的默认配置阶段创建的

高度可配置的日志记录系统(如logback和log4j)可以创建在自己的初始化期间调用记录器的组件.有关典型事件,请参阅问题LOGBACK-127.但是,由于SLF4J的绑定过程尚未完成(因为底层日志记录系统尚未完全加载到内存中),因此无法遵守此类记录器创建请求.

为了避免这种鸡蛋问题,SLF4J在此阶段(初始化)创建了替代记录器.在此阶段对替代记录器进行的调用将被删除.初始化完成后,替代记录器会将日志记录调用委托给相应的记录器实现,否则将像LoggerFactory返回的任何其他记录器一样运行.

如果必须创建任何替代记录器,SLF4J将发出此类记录器的列表.此列表旨在让您知道在初始化期间对这些记录器进行的任何日志记录调用都已被删除.

还有一个尚未解决的问题描述了这个问题.

对我来说,当我测试应用程序的各个部分如何协同工作时,问题就出现了.在自己的线程中运行的生产者的日志语句丢失了,因为它们被发送到替代记录器.在创建生产者线程之前添加日志语句似乎有助于及时初始化记录器.但是,我想知道在应用程序中对LoggerFactory.getLogger的任意调用是否保证我永远不会登录到替代记录器.

简而言之,我的问题是:

  • LoggerFactory.getLogger(classOf [A])是否实例化所有记录器,或者可能是两个以后对LoggerFactory.getLogger(classOf [B])的并发调用将产生一个替代记录器?

  • 有没有办法获得保证,即检查,记录器已初始化(我无法检查记录器的类型,因为它被slf4j外观隐藏)编辑:实际上,我只是认为我可能是能够检查记录器的类型.以下想法能否带来有用的解决方案?:

    def logger(context: Class[_]) = {
      log = LoggerFactory.getLogger(context)
      if (log.isInstanceOf[SubstituteLogger]) logger(context) else log
    
    Run Code Online (Sandbox Code Playgroud)

    我用这种方法看到的问题是它依赖于一个特定于实现的类,即NOPLogger SubstituteLogger.

附录:我不确定这是否与此问题相关,但我将slf4j记录器包装在一个类中,该类为每个日志记录上下文实例化(context =调用记录器的类).此外,还有一个对象创建此包装器的实例,该实例作为隐式构造函数参数传递给要进行日志记录的每个类.我将记录器作为参数传递,而不是记录到静态对象(或混合在特征中)以启用在单元测试中传递特殊记录器.

Arn*_*sen 0

我遇到了同样的问题,因为多个依赖项带来了它们自己的 NoOp Logger 重复副本。就我而言,解决方案是明确slf4j-log4j12通过以下方式固有的依赖关系:

libraryDependencies = Seq(
  ...
  ).map(_.exclude("org.slf4j", "slf4j-log4j12" ))
Run Code Online (Sandbox Code Playgroud)