首页 文章

SLF4J初始化 - 替代 Logger

提问于
浏览
8

我正在Scala中做一个项目,我正在使用带有Logback的slf4j进行日志记录 . 现在,日志记录初始化似乎不是线程安全的 . 作为一种解决方案,slf4j正在创建替代 Logger ,即NoOp-loggers,它吞下初始化期间生成的日志语句 . The slf4j homepage就此问题表示:

替代记录程序是在底层日志记录系统的默认配置阶段创建的 . 高度可配置的日志记录系统(如logback和log4j)可能会创建在自己的初始化期间调用记录程序的组件 . 有关典型事件,请参阅问题LOGBACK-127 . 但是,由于SLF4J的绑定过程尚未完成(因为底层日志记录系统尚未完全加载到内存中),因此无法遵守此类 Logger 创建请求 . 为避免这种鸡蛋问题,SLF4J在此阶段(初始化)期间创建替代 Logger . 在此阶段对替代 Logger 进行的调用将被删除 . 初始化完成后,替代 Logger 会将日志记录调用委托给相应的 Logger 实现,否则将像LoggerFactory返回的任何其他 Logger 一样运行 . 如果必须创建任何替代 Logger ,SLF4J将发出这样的 Logger 列表 . 此列表旨在让您知道在初始化期间对这些 Logger 进行的任何日志记录调用都已被删除 .

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

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

简而言之,我的问题是:

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

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

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

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

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

1 回答

  • 0

    我遇到了同样的问题,因为多个依赖项带来了他们自己的NoOp Logger的重复副本 . 在我的案例中,解决方案明确表达了对 slf4j-log4j12 的内在依赖性:

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

相关问题