当前位置: 首页 > 知识库问答 >
问题:

SLF4J初始化-替代记录器

壤驷麒
2023-03-14

我正在Scala中做一个项目,我正在使用slf4j和Logback进行日志记录。现在,日志初始化似乎不是线程安全的。作为一种解决方案,slf4j正在创建替代记录器,即NoOp记录器,该记录器吞咽初始化期间生成的日志语句。slf4j主页就此问题声明

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

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

为了避免这种鸡和蛋的问题,SLF4J在此阶段(初始化)创建了替代记录器。在此阶段,只需删除对替代记录器的调用。初始化完成后,替代记录器将把日志调用委托给相应的记录器实现,否则将与LoggerFactory返回的任何其他记录器一样工作。

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

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

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

简而言之,我的问题是:

>

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

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

我在这种方法中看到的问题是它依赖于一个特定于实现的类,即 NOPLogger Subthy teLogger。

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

共有1个答案

刘令
2023-03-14

我遇到了同样的问题,因为多个依赖项带来了它们自己的NoOp记录器副本。在我的例子中,解决方案是通过以下方式显式显示slf4j-log4j12上的固有依赖项:

libraryDependencies = Seq(
  ...
  ).map(_.exclude("org.slf4j", "slf4j-log4j12" ))
 类似资料:
  • 我想使用slf4j而不是Log4J。我在我的pom.xml中添加了以下依赖项(我对slf4j使用了1.7.25,对log4j2使用了2.10.0): 一切都构建得很好,没有编译错误或缺乏依赖,但我未能在类中指定负责日志程序初始化的配置(log4j2.xml)文件。在这种情况下,它总是打印相同的警告 我搜索了一种提供配置文件的适当方法,结果是: 问题是,在我的例子中,LogManager.getCo

  • 我目前在班上使用slf4j记录器: 尽管我在代码中使用替换,如下所示: 请在下面检查我的登录配置: 即使我使用的是最新的稳定版本slf4j 1 . 7 . 25 ,< code > { } 仍然没有被正确替换。 以下文本是logger.info的输出: “用户{}成功登录到系统” 我使用LoggerFactory创建记录器:

  • 我已将 Log4J2 添加到我的应用程序中。我通过LIB将所有Log4J2.jar文件复制到,并创建了Log4J2.xml文件来支持它。我的代码已更新为导入必要的日志管理器和记录器 API。然后,我添加了静态的最终记录器方法,并在我的代码中调用了记录器 API。一切都在Eclipse中编译文件。我继续在 DEV 计算机上启动服务器以对其进行验证。启动服务器后,我收到以下错误: 我的配置有什么问题?

  • 类似于这个问题:如何在Jooq中初始化和创建ResultSet和记录?但使用自定义行类型记录而不是简单的表记录。我正在实例化一个jooq记录以用于模拟,但该记录有超过22列并包含来自许多连接表的行,所以我使用RecordImpl。 这引发异常 java.lang.IllegalArgumentException:行()中不包含字段(“course\u id”) 注意,我没有直接使用RecordIm

  • Initialization 初始化 Although it doesn’t look superficially very different from initialization in C or C++, initialization in Go is more powerful. Complex structures can be built during initialization a

  • 初始化是为类、结构体或者枚举准备实例的过程。这个过需要给实例里的每一个存储属性设置一个初始值并且在新实例可以使用之前执行任何其他所必须的配置或初始化。 你通过定义初始化器来实现这个初始化过程,它更像是一个用来创建特定类型新实例的特殊的方法。不同于 Objective-C 的初始化器,Swift 初始化器不返回值。这些初始化器主要的角色就是确保在第一次使用之前某类型的新实例能够正确初始化。 类类型的