实际使用Logback上下文选择器 [英] Practical use of Logback context selectors

查看:176
本文介绍了实际使用Logback上下文选择器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于Logback 记录分离的文档表明我可以使用上下文选择器在同一JVM上创建不同的日志记录配置。不知何故,上下文选择器将允许我调用 LoggerFactory.getLogger(Foo.class),并且根据上下文,我将获得一个不同配置的记录器。

The documentation on Logback logging separation indicates that I can use context selectors to create different logging configurations on the same JVM. Somehow a context selector will allow me to call LoggerFactory.getLogger(Foo.class) and, based upon the context, I will get a differently configured logger.

不幸的是,这些示例仅在特殊配置的Web服务器(如Tomcat或Jetty)的上下文中处理JNDI。我想知道如何自己实际使用上下文选择器,例如在非Web应用程序中。

Unfortunately the examples only deal with JNDI in the context of a specially configured web server such as Tomcat or Jetty. I want to know how I can practically use a context selector myself, for example in a non-web application.

我的目标是在上面设置多个日志记录配置。相同的JVM。这是一个场景:

My goal is to have more than one logging configuration on the same JVM. Here is one scenario:


  • 我想要一个线程使用默认的 logback.xml获取记录器在类路径上配置。

  • 我希望另一个线程从自定义目录中使用另一个 logback.xml 来获取记录器。 / li>
  • 我想要第三个线程从编程配置中获取记录器。

  • I want one thread to get loggers using the default logback.xml configuration on the classpath.
  • I want another thread to get loggers using another logback.xml from a custom directory.
  • I want a third thread to get loggers from a programmatic configuration.

我提供这些示例方案只是为了了解实际使用上下文选择器 - 我将如何在现实生活中对它们做一些有用的事情。

I provide these example scenarios just to get an idea of practical use of context selectors---how I would do something useful with them in real life.


  1. 我如何使用上下文选择器来实现上述场景,以便 LoggerFactory.getLogger(Foo.class)从正确的配置中返回一个记录器线程?

  2. 如果上下文选择器不能完成任务,我怎么能手动获得一个 ILoggerFactory 实例,它会给我记录器从程序化配置?

  1. How could I use context selectors to implement the scenarios above, so that LoggerFactory.getLogger(Foo.class) returns a logger from the correct configuration based on the thread?
  2. If context selectors are not up to the task, how could I manually get an ILoggerFactory instance that would give me loggers from a programmatic configuration?


推荐答案

我曾问过这个问题,使我不至于需要通过的logback源代码跟踪,但由于最初的答案是不够彼时我有这么无论如何做。因此,让我解释一下SLF4J + Logback系统的初始化以及它与上下文选择器的关系。

I had asked this question to prevent my needing to trace through the Logback source code, but as the initial answers were inadequate I wound up having to do so anyway. So let me explain the initialization of the SLF4J+Logback system and how it relates to context selectors.

SLF4J是一个日志API,它允许各种实现,其中一个是Logback 。

SLF4J is a logging API that allows various implementations, one of them being Logback.


  1. 当第一个请求发送到 org.slf4j.LoggerFactory.getLogger(... ),通过创建 org.slf4j.impl.StaticLoggerBinder 来初始化SLF4J框架。诀窍是 StaticLoggerBinder 不与SLF4J一起分发;它实际上是在使用的任何日志记录实现中实现的(例如Logback)。这是加载特定实现的一种有点繁琐的方法(服务加载器可能是更好的选择),但这在某种程度上与此不同。

  1. When the first request is made to org.slf4j.LoggerFactory.getLogger(...), the SLF4J framework is initialized by creating a org.slf4j.impl.StaticLoggerBinder. The trick is that StaticLoggerBinder is not distributed with SLF4J; it is actually implemented in whichever logging implementation is being used (e.g. Logback). This is a somewhat cumbersome approach to loading a specific implementation (a service loader might have been a better choice), but that's somewhat beside the point here.

Logback的 StaticLoggerBinder 的实现创建一个单例 ch.qos.logback.classic.util.ContextSelectorStaticBinder 。这是设置上下文选择器的类。逻辑如下所述。

Logback's implementation of StaticLoggerBinder creates a singleton ch.qos.logback.classic.util.ContextSelectorStaticBinder. This is the class that sets up the context selector. The logic goes something like is outlined below.

a。如果logback.ContextSelector系统属性包含JNDI,请使用 ContextJNDISelector

a. If the "logback.ContextSelector" system property contains "JNDI", use a ContextJNDISelector.

b。如果logback.ContextSelector系统属性包含其他任何内容,则假定该值是上下文选择器类的名称并尝试实例化该值。

b. If the "logback.ContextSelector" system property contains anything else, assume the value is the name of a context selector class and try to instantiate that.

c。否则,如果没有logback.ContextSelector系统属性,请使用 DefaultContextSelector

c. Otherwise if there is no "logback.ContextSelector" system property, use a DefaultContextSelector.

如果使用自定义 ContextSelector ContextSelectorStaticBinder 将使用a实例化它将 LoggerContext 作为参数的构造函数,并将默认 LoggerContext 传递给它 StaticLoggerBinder 已创建并自动配置。 (更改默认配置策略是一个单独的主题,我将不在此处介绍。)

If a custom ContextSelector is used, ContextSelectorStaticBinder will instantiate it using a constructor that takes a LoggerContext as a parameter, and will pass it the default LoggerContext which StaticLoggerBinder has created and auto-configured. (Changing the default configuration strategy is a separate subject I won't cover here.)

正如Pieter指出的那样另一个答案,安装自定义上下文选择器的方法是在logback.ContextSelector系统属性中提供实现类的名称。不幸的是,这种方法有点不稳定,显然必须1)手动完成,2)在进行任何SLF4J调用之前。 (这里再一次服务加载器机制会好得多;我已经提交了问题 LOGBACK-1196 对于这种改进。)

As Pieter points out in another answer, the way to install a custom context selector is to provide the name of the implementing class in the "logback.ContextSelector" system property. Unfortunately this approach is a bit precarious, and it obviously has to be done 1) manually and 2) before any SLF4J calls are made. (Here again a service loader mechanism would be been much better; I have filed issue LOGBACK-1196 for this improvement.)

如果您设法安装了自定义Logback上下文选择器,您可能希望存储 LoggerContext ,以便您可以在 ContextSelector.getDefaultLoggerContext()中返回它。除此之外, ContextSelector 中最重要的方法是 ContextSelector.getLoggerContext();从这个方法中,你将确定哪个记录器上下文适合当前上下文并返回它。

If you manage to get your custom Logback context selector installed, you'll probably want to store the LoggerContext you receive in the constructor so that you can return it in ContextSelector.getDefaultLoggerContext(). Other than this, the most important method in ContextSelector is ContextSelector.getLoggerContext(); from this method you will determine what logger context is appropriate for the current context and return it.

LoggerContext 哪个非常重要的是 ch.qos.logback.classic.LoggerContext ,它实现了 ILoggerFactory 。当您访问主 org.slf4j.LoggerFactory.getLogger(...)方法时,它使用单例 StaticLoggerBinder (上面讨论过)查找记录器工厂。对于Logback StaticLoggerBinder 将使用单例 ContextSelectorStaticBinder (也在上面讨论过),希望它将返回到您现在安装的自定义 LoggerContext

The LoggerContext which is so important here is ch.qos.logback.classic.LoggerContext, which implements ILoggerFactory. When you access the main org.slf4j.LoggerFactory.getLogger(...) method, it uses the singleton StaticLoggerBinder (discussed above) to look up the logger factory. For Logback StaticLoggerBinder will use the singleton ContextSelectorStaticBinder (also discussed above) which hopefully will return to your now installed custom LoggerContext.

ContextSelector.getLoggerContext(String name) ContextSelector.detachLoggerContext(String loggerContextName) ContextSelector.getContextNames()方法似乎只用于某种情况例如JNDI上下文选择器,您希望在其中使用名称跟踪上下文选择器。如果您不需要命名上下文选择器,则可以安全地返回 null 和适合这些方法的空列表。)

(The ContextSelector.getLoggerContext(String name), ContextSelector.detachLoggerContext(String loggerContextName), and ContextSelector.getContextNames() methods seem to only be used in a situation such as the JNDI context selector in which you wish to keep track of context selectors using names. If you don't need named context selectors, it appears you can safely return null and an empty list as appropriate for these methods.)

因此自定义 ContextSelector 只需提供一些 LoggerContext 为调用线程正确配置;这个 LoggerContext 将作为 ILoggerFactory 创建一个基于 LoggerContext的记录器配置。配置包含在 Logback文档中;也许这里的讨论更清楚地说明Logback记录器上下文的内容。

Thus the custom ContextSelector need simply provide some LoggerContext appropriately configured for the calling thread; this LoggerContext will serve as the ILoggerFactory that creates a logger based upon the LoggerContext configuration. Configuration is covered in the Logback documentation; perhaps this discussion here makes clearer what the Logback logger context is all about.

关于 LoggerContext 有一个帖子,这对我来说从来都不是问题。这很简单:我将使用我自己的 Csar 库,它可以轻松处理这些事情。现在我已经想出了如何挂钩记录器上下文选择过程,我已经在名为的日志记录辅助库中实现了这一点。 Clogr 使用Csar,我现在已公开发布。

As for the actual mechanics of associating a LoggerContext with a thread, that was never an issue for me. It's simple: I'll be using my own Csar library, which handles such things with ease. And now that I've figured out how to hook into the logger context selection process, I've already implemented this in a logging assistance library named Clogr which uses Csar and which I have now publicly released.

因为我自己完成了所有的研究,所以我将标记自己的作为接受的答案回答,除非有人在我自己没有提及的其他答案中指出了一些重要的事情。

Because I wound up having to do all the research myself, I'll be marking my own answer as the accepted answer unless someone points out something important in one of the other answers which I didn't cover in my own.

这篇关于实际使用Logback上下文选择器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆