我想在日志文件中记录我的服务器的请求/响应。我使用的是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值会变空。
答案 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是否合适?