Add MDC variables in JsonLayout - log4j2
Asked Answered
P

1

9

How to add MDC variables in the json log generated by JsonLayout of log4j2. I've used KeyValuePair tag to add properties like host name into the log, but I didn't found any way to add MDC variables into it. In pattern layout I used %X{traceId} but I'm sure JsonLayout can't parse those conversion chars(As far as I know conversion chars are used by pattern layout only). I went into source code of JsonLayout but didn't found function which actually puts all of the data into the log message.

Thank you.

Pavis answered 21/9, 2018 at 15:8 Comment(0)
O
15

What you're looking for is a log4j2 lookup. It sounds like you're interested specifically in the Context Map Lookup as you mentioned MDC (which is now called ThreadContext in log4j2 by the way).

Here is a simple example:

package example;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;

public class ThreadContextExample {

    private static final Logger log = LogManager.getLogger();

    public static void main(String[] args) {
        ThreadContext.put("myKey", "myValue");
        log.info("Here's a message!");
    }
}

Here is the log4j2.xml configuration:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <JsonLayout compact="false" eventEol="false" stacktraceAsString="true">
                <KeyValuePair key="myJsonKey" value="${ctx:myKey}"/>
            </JsonLayout>
        </Console>

    </Appenders>

    <Loggers>
        <Root level="debug">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

and finally some sample output (shortened for readability):

{
  "thread" : "main",
  "level" : "INFO",
  "loggerName" : "example.ThreadContextExample",
  "message" : "Here's a message!",
  ...
  "myJsonKey" : "myValue"
}
Overarch answered 22/9, 2018 at 5:27 Comment(4)
There is one problem though. Not all of the log messages should contain MyJsonKey. So in that case the log gets printed and it value field comes out to be "{ctx:mykey}", which looks very bad. Is there any way we can add parameters to json log dynamically ? @OverarchPavis
If you don't want the key printed in the log at all you probably want to look at RoutingAppender and use two different appender configurations within the Routes - one with the key, the other without. Also read the log4j2 FAQ page, there is a good example of RoutingAppender in there.Overarch
A better way to use your value field is $${ctx:myKey:-}. The json key will exist even with empty value, however the ctx:myKey will not appears in logs, just an empty string.Plauen
Is it necessary to do a ThreadContext.clearMap(); just like we used to do a MDC.clear() at the end?Aigneis

© 2022 - 2024 — McMap. All rights reserved.