如何将Log4j2 ThreadContext值注入Jersey的LoggingFeature

时间:2017-01-20 11:38:10

标签: java spring jersey-2.0 log4j2 java.util.logging

我想在日志文件中记录我的服务器的请求/响应。我使用的是Springboot + jersey 2.x + log4j2。我注册了球衣的LoggingFeature -

jerseyConfig.register(
    new LoggingFeature(
          java.util.logging.Logger.getLogger(
                     LoggingFeature.DEFAULT_LOGGER_NAME),
          java.util.logging.Level.SEVERE,
          LoggingFeature.Verbosity.PAYLOAD_ANY,
          Integer.MAX_VALUE)
);

log4j2.xml

<!-- Jersey logger -->
<AsyncLogger name="org.glassfish" level="all" additivity="false">
    <AppenderRef ref="Console" level="off" />
    <AppenderRef ref="RollingFileIO" level="error" />
</AsyncLogger>

在模式中,我在log4j2的ThreadContext的帮助下注入了transaction-id。我的pom.xml中有log4j-jul 2.1,我用

运行它

-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager

事情正常,唯一的问题是,在球衣的日志中,我无法插入交易ID。我尝试用我的自定义代码记录utils,我可以将transaction-id放入其中。但是当球衣写下这些日志时,ThreadContext会被清除,并且transaction-id值会变空。

2 个答案:

答案 0 :(得分:0)

如果日志流是JUL->log4j2->FooAppender->Layout->ThreadContext.pop那么

Including the ThreadContext when writing logs

  

PatternLayout提供了打印ThreadContext Map和Stack内容的机制。

     
      
  • 单独使用%X包含地图的全部内容。
  •   
  • 使用%X{key}包含指定的密钥。
  •   
  • 使用%x包含堆栈的全部内容。
  •   

如果流量为log4j2->JUL->FooHandler->Formatter->ThreadContext.pop,则必须安装或创建知道ThreadContext的格式化程序。您还必须确保在此配置中log4j2->ThreadContext.pop->JUL->FooHandler->Formatter没有发生,因为在它到达JUL之前会忘记所有信息。

文档中的所有示例都显示在调用记录器之前设置了ThreadContext。这意味着您必须在任何Jersey代码执行之前设置ThreadContext

答案 1 :(得分:0)

我没有详细查看过泽西岛,但是从问题描述来看,它似乎有一个线程模型,使得single_sprite难以使用。

幸运的是,Log4j 2.7提供了一种工具,允许您将键值对(如ID)注入来自除ThreadContext之外的其他源的日志事件。这是为了帮助Finagle之类的异步框架而引入的,所以它对Jersey也很有用。

Log4j2手册在Custom ContextDataInjectors一节中简要提到了此功能。

如果要使用此工具,则需要编写自定义ContextDataInjector并通过指定ContextDataInjectorFactory告诉Log4j使用该注入器而不是默认注入器。您的自定义注入器需要从某处获取键值对。在Jersey的情况下,RequestContext.getProperty和setProperty是否合适?