Gar*_*son 6 java logging logback slf4j
有关 Logback日志记录分离的文档表明我可以使用上下文选择器在同一 JVM 上创建不同的日志记录配置。不知何故,上下文选择器将允许我调用LoggerFactory.getLogger(Foo.class)
,并且根据上下文,我将获得不同配置的记录器。
不幸的是,这些示例仅在专门配置的 Web 服务器(例如 Tomcat 或 Jetty)上下文中处理 JNDI。我想知道如何自己实际使用上下文选择器,例如在非 Web 应用程序中。
我的目标是在同一个 JVM 上拥有多个日志配置。这是一种场景:
logback.xml
类路径上的默认配置来获取记录器。logback.xml
我想要另一个线程使用自定义目录中的另一个线程获取记录器。我提供这些示例场景只是为了了解上下文选择器的实际使用——我将如何在现实生活中使用它们做一些有用的事情。
LoggerFactory.getLogger(Foo.class)
根据线程从正确的配置返回记录器?ILoggerFactory
实例来从编程配置中为我提供记录器?我问这个问题是为了防止我需要跟踪 Logback 源代码,但由于最初的答案不够充分,我最终不得不这样做。那么我来解释一下SLF4J+Logback系统的初始化以及它与上下文选择器的关系。
SLF4J 是一种日志 API,允许各种实现,其中之一是 Logback。
当向 发出第一个请求时org.slf4j.LoggerFactory.getLogger(...)
,SLF4J 框架将通过创建org.slf4j.impl.StaticLoggerBinder
. 诀窍是它StaticLoggerBinder
不随 SLF4J 一起分发;它实际上是在正在使用的任何日志记录实现中实现的(例如Logback)。这是加载特定实现的一种有点麻烦的方法(服务加载器可能是更好的选择),但这有点偏离这里的重点。
Logback 的实现StaticLoggerBinder
创建了一个 singleton ch.qos.logback.classic.util.ContextSelectorStaticBinder
。这是设置上下文选择器的类。其逻辑如下所示。
A。如果“logback.ContextSelector”系统属性包含“JNDI”,请使用ContextJNDISelector
.
b. 如果"logback.ContextSelector"
系统属性包含其他内容,则假设该值是上下文选择器类的名称并尝试实例化它。
C。否则,如果没有"logback.ContextSelector"
系统属性,请使用DefaultContextSelector
.
ContextSelector
如果使用自定义,ContextSelectorStaticBinder
将使用以 a 作为参数的构造函数实例化它LoggerContext
,并将其传递给LoggerContext
已StaticLoggerBinder
创建和自动配置的默认值。(更改默认配置策略是一个单独的主题,我不会在这里讨论。)
正如 Pieter 在另一个答案中指出的那样,安装自定义上下文选择器的方法是在系统属性中提供实现类的名称"logback.ContextSelector"
。不幸的是,这种方法有点不稳定,显然必须在 1) 手动和 2) 进行任何 SLF4J 调用之前完成。(服务加载器机制会更好;我已针对此改进提交了问题LOGBACK-1196。)
如果您设法安装了自定义 Logback 上下文选择器,您可能希望将LoggerContext
收到的内容存储在构造函数中,以便可以在ContextSelector.getDefaultLoggerContext()
. 除此之外,最重要的方法ContextSelector
是ContextSelector.getLoggerContext()
;通过此方法,您将确定哪个记录器上下文适合当前上下文并返回它。
LoggerContext
这里最重要的是ch.qos.logback.classic.LoggerContext
实现ILoggerFactory
。当您访问 mainorg.slf4j.LoggerFactory.getLogger(...)
方法时,它使用单例StaticLoggerBinder
(如上所述)来查找记录器工厂。对于 LogbackStaticLoggerBinder
将使用单例ContextSelectorStaticBinder
(也在上面讨论过),它有望返回到您现在安装的自定义LoggerContext
.
(ContextSelector.getLoggerContext(String name)
、ContextSelector.detachLoggerContext(String loggerContextName)
、 和ContextSelector.getContextNames()
方法似乎只在诸如 JNDI 上下文选择器之类的情况下使用,在这种情况下您希望使用名称跟踪上下文选择器。如果您不需要命名上下文选择器,那么您似乎可以安全地返回null
并适用于这些方法的空列表。)
因此,自定义需要简单地为调用线程ContextSelector
提供一些适当的配置;LoggerContext
这LoggerContext
将用作ILoggerFactory
根据LoggerContext
配置创建记录器。Logback 文档中介绍了配置;也许这里的讨论更清楚地说明了 Logback 记录器上下文的含义。
至于将 aLoggerContext
与线程关联的实际机制,这对我来说从来都不是问题。很简单:我将使用我自己的Csar库,它可以轻松处理此类事情。现在我已经弄清楚如何连接到记录器上下文选择过程,我已经在名为Clogr的日志记录辅助库中实现了这一点,该库使用 Csar,现在我已经公开发布了该库。
因为我最终必须自己完成所有研究,所以我会将自己的答案标记为已接受的答案,除非有人在其他答案之一中指出我自己未涵盖的重要内容。
归档时间: |
|
查看次数: |
4674 次 |
最近记录: |