java 无法将值放入 MDC
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16815602/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
not able to put the values in the MDC
提问by Ram Dutt Shukla
I am trying to log few values in the onBeginRequest()
of RequestCycle()
in wicket.
But the values are not being logged in the debug file. I am putting the values in the MDC in RequestCycleListeners()
.
我试图在检票口的onBeginRequest()
ofRequestCycle()
中记录几个值。但是这些值没有记录在调试文件中。我将 MDC 中的值放入RequestCycleListeners()
.
Following is the code:
以下是代码:
getRequestCycleListeners().add(new AbstractRequestCycleListener()
{
public void onBeginRequest(RequestCycle cycle)
{
if( cycle.getRequest().getContainerRequest() instanceof HttpServletRequest )
{
HttpServletRequest containerRequest =
(HttpServletRequest)cycle.getRequest().getContainerRequest();
MDC.put("serverName", containerRequest.getServerName());
MDC.put("sessionId", containerRequest.getSession().getId());
LOGGER.debug("logging from RequestCycleListeners() !!!");
WebClientInfo webClientInfo = new WebClientInfo(RequestCycle.get());
System.out.println(webClientInfo.getUserAgent());
System.out.println("webClientInfo.getProperties().getBrowserVersionMajor() " +containerRequest.getRemoteAddr());
}
};
};
I am expecting 'serverName', 'sessionId' to be logged in the debug file.
我希望在调试文件中记录“serverName”、“sessionId”。
I have added this listener
in the class which is extending the WebApplication
.
我listener
在扩展WebApplication
.
I am using log4j.xml the DEBUG appender
is looks as below:
我正在使用 log4j.xml DEBUG appender
,如下所示:
<appender name="DEBUG" class="org.apache.log4j.rolling.RollingFileAppender">
<param name="Append" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ISO8601} %t %5p] %m -- %X{serverName} -- %X{sessionId} -- %X{portNumber}%n"/>
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="DEBUG"/>
<param name="LevelMax" value="WARN"/>
</filter>
</appender>
and we are defining scope in root tag :
我们在根标签中定义范围:
<root>
<priority value="INFO" />
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG" />
<appender-ref ref="ERROR" />
</root>
回答by superEb
Typically, MDC values are only output to logs if you include MDC keys in your logging pattern via configuration. Since slf4j is just a facade, you need to have framework-specific support and configuration underneath slf4j to make use of MDC. Read slf4j's notes on that here.
通常,如果您通过配置在日志记录模式中包含 MDC 键,则 MDC 值仅输出到日志。由于 slf4j 只是一个外观,您需要在 slf4j 下有特定于框架的支持和配置才能使用 MDC。在此处阅读 slf4j 对此的说明。
So, for example, if you're using log4j as the impl underneath slf4j, then you would need log4j config (ConversionPattern) like:
因此,例如,如果您使用 log4j 作为 slf4j 下的 impl,那么您将需要 log4j 配置(ConversionPattern),例如:
%d %-5p [%c] [%X{serverName} %X{sessionId}] %m%n
Where %X{serverName} %X{sessionId}
is the relevant part that pulls values from the MDC.
%X{serverName} %X{sessionId}
从 MDC 中提取值的相关部分在哪里。
Here's a pretty good example using log4j without sl4j. See notes on X
Conversion Character in log4j javadoc here.
这是一个使用 log4j 而没有 sl4j 的很好的例子。请参阅此处有关X
log4j javadoc 中的转换字符的注释。
Note that pattern syntax for logback is identical. See specifics for logback here.
请注意,logback 的模式语法是相同的。在此处查看 logback 的详细信息。
Also note that best practice for MDC (which uses a ThreadLocal
under-the-hood) is to clear the context (remove the values you put in the map) when the context is no longer in scope. That typically means calling remove
or clear
in a finally
block, like:
另请注意,ThreadLocal
当上下文不再在范围内时,MDC(使用底层技术)的最佳实践是清除上下文(删除您放入映射中的值)。这通常意味着调用remove
或clear
在finally
块中,例如:
try {
//...
MDC.put("key1", value1);
MDC.put("key2", value2);
//...
} finally {
//this
MDC.remove("key1");
MDC.remove("key2");
//or this
MDC.clear();
}
This is especially important if the thread that holds the MDC belongs to a pool for later reuse. You certainly don't want to unintentionally log invalid context values since that will just cause confusion.
如果持有 MDC 的线程属于一个池以供以后重用,这一点尤其重要。您当然不想无意中记录无效的上下文值,因为这只会引起混淆。
EDIT
编辑
Your log4j configuration seems a little odd, for the following reasons:
您的 log4j 配置似乎有点奇怪,原因如下:
- You are naming your appenders after log levels, which may cause confusion
- Your
RollingFileAppender
does not define a file - Your
root
logger will log to 3 different appenders, one of which is namedDEBUG
, but it is configured to only logINFO
level and greater (based on thepriority
tag), so debug statements will not be logged
- 您在日志级别后命名您的附加程序,这可能会导致混淆
- 你
RollingFileAppender
没有定义文件 - 您的
root
记录器将记录到 3 个不同的附加程序,其中一个名为DEBUG
,但它被配置为仅记录INFO
级别和更高(基于priority
标签),因此不会记录调试语句
Unless you have some specific categories configured separately that are not shown, I would guess that noneof your LOGGER.debug
statements are being logged, regardless of your attempt to use MDC.
除非您单独配置了一些未显示的特定类别,否则我猜想您的任何LOGGER.debug
语句都不会被记录,无论您尝试使用 MDC。
回答by J?rg
Note, that if you are using AsyncAppender, clearing MDCfrom your thread won't protect you, since the log event and MDC handling happens in the AsyncAppender's thread. See also this related bug
请注意,如果您使用AsyncAppender,则从您的线程中清除MDC不会保护您,因为日志事件和 MDC 处理发生在 AsyncAppender 的线程中。另请参阅此相关错误
Unfortunately, in v1.2.17the latest released version of the EOLed log4j-1.x, the AsyncAppender's Dispatcher-Thread does not clear the MDC upon stopping either.
不幸的是,以V 1.2.17的EOLed的log4j-1.x的最新发布的版本中,AsyncAppender的分派线程不会在停止或者清除MDC。
Since, the AsyncAppender/Dispatcher is fairly simple, it's easy to patch it by putting
由于 AsyncAppender/Dispatcher 相当简单,因此很容易通过放置
finally
{
MDC.clear();
}
at the try-block in org.apache.log4j.AsyncAppender.Dispatcher.run()method.
在org.apache.log4j.AsyncAppender.Dispatcher.run()方法中的 try-block 处。
Of course, one can also workaround this by not using AsyncAppender when executing in a ServletContainer.
当然,也可以通过在 ServletContainer 中执行时不使用 AsyncAppender 来解决此问题。