Scala SLF4J初始化-替换记录器

Scala SLF4J初始化-替换记录器,scala,logging,slf4j,logback,race-condition,Scala,Logging,Slf4j,Logback,Race Condition,我正在Scala中做一个项目,我正在使用slf4j和Logback进行日志记录。现在,日志初始化似乎不是线程安全的。作为一种解决方案,slf4j正在创建替代记录器,即NoOp记录器,该记录器接受初始化期间生成的日志语句。关于这一事项的国家: 替代记录器是在底层日志系统的默认配置阶段创建的 高度可配置的日志记录系统(如logback和log4j)可以创建在其自身初始化期间调用记录器的组件。有关典型事件,请参阅问题LOGBACK-127。但是,由于与SLF4J的绑定过程尚未完成(因为底层日志记录系统

我正在Scala中做一个项目,我正在使用slf4j和Logback进行日志记录。现在,日志初始化似乎不是线程安全的。作为一种解决方案,slf4j正在创建替代记录器,即NoOp记录器,该记录器接受初始化期间生成的日志语句。关于这一事项的国家:

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

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

为了避免这种鸡毛蒜皮的问题,SLF4J在此阶段(初始化)创建替代记录器。在这个阶段,对替代记录器的调用被简单地丢弃。初始化完成后,替代记录器将把日志调用委托给相应的记录器实现,否则将与LoggerFactory返回的任何其他记录器一样工作

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

还有一个尚未解决的问题

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

简言之,我的问题是:

  • 是LoggerFactory.getLogger(classOf[A])实例化了所有的记录器,还是两次之后,对LoggerFactory.getLogger(classOf[B])的并发调用将产生一个替代记录器

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

    def logger(context: Class[_]) = {
      log = LoggerFactory.getLogger(context)
      if (log.isInstanceOf[SubstituteLogger]) logger(context) else log
    
    我认为这种方法的问题在于它依赖于一个特定于实现的类,即nologger SubstituteLogger

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

我遇到了同样的问题,因为多个依赖项带来了自己的NoOp记录器副本。在我的案例中,解决方案是通过以下方式明确地依赖于
slf4j-log4j12

libraryDependencies = Seq(
  ...
  ).map(_.exclude("org.slf4j", "slf4j-log4j12" ))

刚用Akka得到这个。。。这是因为记录器初始化是多次同时进行的(第一次访问记录器)。因此,在应用程序启动时添加一个虚拟日志修复了它。我在scalatest并行测试中遇到了同样的问题。因为它对延迟不敏感,所以我已经用sleep进行了修复,并在
log
为substituteLoger时重试