将上下文传递给异步Logger

时间:2016-11-14 11:56:57

标签: java log4j2 apache-httpasyncclient threadcontext

我正在尝试从http客户端记录原始请求/响应。 我正在关注这些logging instructions中的log4j2配置。

HttpAsync客户端依赖关系: - httpasyncclient(版本4.1.1)

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
    <RollingRandomAccessFile name="app-log" fileName="${log.path}/app.log"
                             filePattern="${log.path}/app-%d{yyyy-MM-dd}.gz">
        <PatternLayout>
            <pattern>[%-5level] [%X{uuid}] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n</pattern>
        </PatternLayout>
        <Policies>
            <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
        </Policies>
    </RollingRandomAccessFile>
</Appenders>
<Loggers>
    <AsyncLogger name="org.apache.http.impl.conn.Wire" level="debug">
        <AppenderRef ref="app-log"/>
    </AsyncLogger>
    <AsyncRoot level="debug" includeLocation="true">
        <AppenderRef ref="app-log"/>
    </AsyncRoot>
</Loggers>
</Configuration>

打印正常,但是threadcontext没有传递给线记录器。

示例: -

// with uuid, output of logger.debug(ThreadContext.getImmutableContext().toString());

[DEBUG] [c48b97f7-0094-44af-82af-3d6b43d76014] 2016-11-14 17:06:03.408 [http-bio-8080-exec-1] OutboundRequestHandler - {uuid=c48b97f7-0094-44af-82af-3d6b43d76014}

// without uuid
[DEBUG] [] 2016-11-14 17:06:03.440 [I/O dispatcher 1] headers - http-outgoing-0 >> POST /abcd.json HTTP/1.1
[DEBUG] [] 2016-11-14 17:06:03.441 [I/O dispatcher 1] headers - http-outgoing-0 >> Content-Length: 2
[DEBUG] [] 2016-11-14 17:06:03.441 [I/O dispatcher 1] headers - http-outgoing-0 >> Content-Type: text/plain; charset=ISO-8859-1
[DEBUG] [] 2016-11-14 17:06:03.441 [I/O dispatcher 1] headers - http-outgoing-0 >> Host: 127.0.0.1:80
[DEBUG] [] 2016-11-14 17:06:03.441 [I/O dispatcher 1] headers - http-outgoing-0 >> Connection: Keep-Alive
[DEBUG] [] 2016-11-14 17:06:03.441 [I/O dispatcher 1] headers - http-outgoing-0 >> User-Agent: Apache-HttpAsyncClient/4.1.1 (Java/1.8.0_92)

如何将ThreadContext传递给记录器?

感谢。

3 个答案:

答案 0 :(得分:0)

由于设置UUID的线程(http-bio-8080-exec-1)与正在执行日志记录的应用程序中的线程(I / O调度程序1)不同,因此它们具有不同的ThreadContext映射和第二个线程无法看到第一个线程放在其地图中的内容。

从log4j 2.7开始,可以创建一个custom context data injector,它可以从其他地方获取上下文数据而不是ThreadLocal地图(因为这基本上就是ThreadContext的内容)。

这意味着您需要创建一个自定义外观,类似于log4j的ThreadContext,您可以将键值对放入某些数据结构中。我不熟悉AsyncHttpClient,但我找不到&#34; context&#34;允许单独的线程共享与同一会话关联的数据的概念。

您的自定义context injector implementation将获取键值对的快照,并将其注入LogEvent以获取每条日志消息。

答案 1 :(得分:0)

我不确定这在2019年有多重要,因为询问者肯定会转移到其他事情上。但仍然可以:

在log4j2中,我们必须使用ThreadContext.put而不是用于log4j的MDC.put。这将完美记录所有内容。休息一切都保持不变

答案 2 :(得分:0)

v2.13.2开始,建议创建一个ContextDataProvider而不是ContextDataInjector

ContextDataProvider(在Log4j 2.13.2中引入)是一个接口应用程序,并且库可用于将其他键值对注入LogEvent的上下文数据中。 Log4j的ThreadContextDataInjector使用java.util.ServiceLoader定位和加载ContextDataProvider实例。 Log4j本身使用org.apache.logging.log4j.core.impl.ThreadContextDataProvider将ThreadContextData添加到LogEvent中。定制实现应实现org.apache.logging.log4j.core.util.ContextDataProvider接口,并通过在名为META-INF / services / org.apache.logging.log4j.core的文件中定义实现类,将其声明为服务。 util.ContextDataProvider。