如何在log4j2的JsonLayout生成的json日志中添加MDC变量。我已经使用 KeyValuePair 标记将主机名等属性添加到日志中,但我没有找到任何方法将 MDC 变量添加到其中。在模式布局中,我使用了 %X{traceId} 但我确定 JsonLayout 无法解析这些转换字符(据我所知,转换字符仅用于模式布局)。我进入了 JsonLayout 的源代码,但没有找到实际上将所有数据放入日志消息的函数。
谢谢你。
是否有可能在运行时使用MDC命名日志文件.
我有一个Web应用程序,使用tomcat docbase同时使用不同的名称调用.所以我需要为每个文件都有单独的日志文件.
我使用 slf4j 登录我的项目。我想使用 MDC 来记录用户 ID 参数。所以我检查教程和文档,并编写如下代码:
MDC.put("key", userId)
Run Code Online (Sandbox Code Playgroud)
userId实际上是一个字符串。
我使用常用的 log4j xml 和附加程序等属性。在那里添加 %X{key} 但没有任何反应。我根本没有看到任何东西可以代替 %X{key},但其他参数如 %-5p 或 %c 效果很好。
所以我使用 debug 来观察 MDC.put() 方法中发生的情况,并发现在 MDC 的初始化中使用了:
MDCAdapter mdcAdapter;
mdcAdapter = StaticMDCBinder.SINGLETON.getMDCA();
Run Code Online (Sandbox Code Playgroud)
IDEA 中的调试显示它具有“Log4jMDCAdapter”,类似于 MDCAdapter 的实现之一。但后来我查看 StaticMDCBinder,有如下代码:
public MDCAdapter getMDCA() {
return new NOPMDCAdapter();
}
Run Code Online (Sandbox Code Playgroud)
那么 slf4j 如何使用适当的适配器(例如 log4j)初始化 MDC ???我没明白。因为它始终使用 NOPMDCAdapter,所以它无法在 MDC 中存储任何内容,也无法在日志记录中显示它。我该如何修复它?
在类路径中我有:
有没有人知道如何使用log4j的config xml为MDC中的缺失条目指定默认值?我在我的XML文件中定义了一个appender,如下所示:
<appender name="DBAppender" class="org.apache.log4j.jdbc.JDBCAppender">
<param name="URL" value="jdbc:sqlserver://phenom\\MSSQLSERVER_2012\;databaseName=pickmax_express" />
<param name="Driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<param name="User" value="user" />
<param name="Password" value="password" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="INSERT INTO LOG (source, message, order_id, log_level) VALUES ( 'TESTSOURCE','%m', %X{orderID}, 0)"
/>
</layout>
</appender>
Run Code Online (Sandbox Code Playgroud)
有问题的部分是来自MDC的订单ID(%X {orderID}).我四处搜索,只发现同一个线程的副本说了一些类似于$$ {orderID:-DefaultValue}的内容,但这在这个上下文中不起作用.我需要能够在没有订单ID的上下文中收到日志消息时将值默认为0或-1或其他一些sentinal值
我正在尝试根据通过MDCin log4j传递的值生成不同的日志文件。尝试了几种方法后,我无法正常工作。
这就是我要怎么做。
在 java 代码中。我在MDC.
public static void addHeadersToMDC(Map<String, String> headers) {
//headers contains other http headers such as uid,appid, client-type etc.
if (headers != null) {
Map<String, String> clonedHeaders =
new HashMap<String, String>(headers);
LogMasker.getInstance().maskHeaders(clonedHeaders);
clonedHeaders.put("APPNAME", "special");//setting APPNAME to MDC here.
for (String header : clonedHeaders.keySet()) {
ThreadContext.put(header, clonedHeaders.get(header))
}
}
}
Run Code Online (Sandbox Code Playgroud)
在 log4j2.xml 中,我试图通过执行 <
Routing name="Routing">
<Routes pattern="$${ctx:ROUTINGKEY}">
<Route key="async-perf">
<RollingFile name="Rolling-Async-Perf" fileName="/usr/local/logs/${ctx:APPNAME}.log"
filePattern="./logs/${date:yyyy-MM}/perf-%d{yyyy-MM-dd}-%i.log.gz" immediateFlush="false">
<PatternLayout charset="UTF-8">
<pattern>%d LogLevel=%p my_appid=%X{appid} uid=%X{uid} class=%c %m%n</pattern><!-- …Run Code Online (Sandbox Code Playgroud) 我想要一个添加requestId到我的web应用程序的日志,如图所示这里.
public class MDCFilter implements ContainerRequestFilter, ContainerResponseFilter
{
private static final String CLIENT_ID = "client-id";
@Context
protected HttpServletRequest r;
@Override
public void filter(ContainerRequestContext req) throws IOException
{
Optional<String> clientId = Optional.fromNullable(r.getHeader("X-Forwarded-For"));
MDC.put(CLIENT_ID, clientId.or(defaultClientId()));
}
@Override
public void filter(ContainerRequestContext req, ContainerResponseContext resp) throws IOException
{
MDC.remove(CLIENT_ID);
}
private String defaultClientId()
{
return "Direct:" + r.getRemoteAddr();
}
}
Run Code Online (Sandbox Code Playgroud)
这样做的问题是,它设置和删除 requestId从MDC上述过滤器.我还记录了我的应用程序生成的响应的主体WriterInterceptor.问题是,因为拦截器在过滤器之后运行,所以当我WriterInterceptor执行时,没有requestId MDC.
我的问题是,是否可以MDC.clear()在结束时打电话WriterInterceptor(感觉某种程度上是hacky),还是有更好的方法来实现这一目标?
我试图确定MDC使用 Cacheable ThreadPools 或 Spring 的 Async 注释时线程安全的程度。
我有一个方法可以调用多个CompletableFuture<>并使用线程池执行它们
@Async
public CompletableFuture<List> someMethod(String request) {
try {
MDC.put("request", request)
MDC.put("loggable1", "loggable1");
MDC.put("loggable2", "loggable2");
log.info("Log Event");
} finally {
MDC.clear();
}
}
Run Code Online (Sandbox Code Playgroud)
Logback 的 MDCAdapter 相关部分
final ThreadLocal<Map<String, String>> copyOnThreadLocal = new ThreadLocal<Map<String, String>>();
public void put(String key, String val) throws IllegalArgumentException {
if (key == null) {
throw new IllegalArgumentException("key cannot be null");
}
Map<String, String> oldMap = copyOnThreadLocal.get();
Integer lastOp = getAndSetLastOperation(WRITE_OPERATION);
if (wasLastOpReadOrNull(lastOp) || …Run Code Online (Sandbox Code Playgroud) 使用 Spring MVC,我有以下设置:
我正在尝试使用 MDC(或 ThreadLocal 对象)为处理请求所涉及的所有组件收集上下文信息。
我可以从@Async 线程正确检索 MDC 上下文信息。但是,如果@Async 线程要将上下文信息添加到 MDC,我现在如何将 MDC 上下文信息编组到处理响应的线程?
任务装饰器
public class MdcTaskDecorator implements TaskDecorator {
@Override
public Runnable decorate(Runnable runnable) {
// Web thread context
// Get the logging MDC context
Map<String, String> contextMap = MDC.getCopyOfContextMap();
return () -> {
try {
// @Async thread context
// Restore the web thread MDC context
if(contextMap != null) {
MDC.setContextMap(contextMap);
}
else {
MDC.clear(); …Run Code Online (Sandbox Code Playgroud) 我们正在使用:
现在,我们要使用MDC将 POST 请求 JSON 中提供的唯一跟踪号添加到给定请求的每个日志语句中。
我在谷歌上搜索了一些博客文章,这些对我来说没什么用。
下面是logback.xml我们正在使用的
<configuration>
<property name="PROJECT_ID" value="template-api"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Run Code Online (Sandbox Code Playgroud)
任何人都可以提供一些关于如何完成这项工作的帮助吗?
我需要记录请求的一些属性,比如请求 id 和语言环境,但是在使用 parallelStream 时,似乎 MDC 的 ThreadLocal 丢失了信息。
我分析了在创建parallelStream时在线程之间传递MDC上下文的解决方案,但它看起来很脏,我也有很多parallelStream的用法。
有没有其他方法可以做到这一点?
谢谢
mdc ×10
java ×7
logging ×5
log4j ×4
logback ×4
slf4j ×3
log4j2 ×2
spring-boot ×2
filter ×1
interceptor ×1
jax-rs ×1
spring-mvc ×1