Log4j2 JsonTemplateLayout - log message field as json

Viewed 1663

I have this log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
    <Console name="JsonAppender" target="SYSTEM_OUT">
        <JsonTemplateLayout eventTemplateUri="classpath:EcsLayout.json" />
    </Console>
</Appenders>
<Loggers>
    <Logger name="JsonLogger" level="INFO" additivity="false">
        <AppenderRef ref="JsonAppender"/>
    </Logger>
    <Root level="info">
        <AppenderRef ref="JsonAppender"/>
    </Root>
</Loggers>
</Configuration>

In my code I have a logging statement like:

HashMap logMap = new HashMap<>();
        logMap.put("appId", "123456789");
        logMap.put("action", "Received request");

        logger.info(new ObjectMessage(logMap));

In my log I get this:

 {
        "@timestamp": "2022-02-02T10:52:56.100Z",
        "ecs.version": "1.2.0",
        "log.level": "INFO",
        "message": "{appId=123456789, action=Received request}",
        "process.thread.name": "main",
        "log.logger": "org.xxxx.App" 
}

That's ok but I want the message to be in json, so would like:

"message": {
              "appId": "123456789", 
              "action": "Received request"
}

I know using JsonLayout you had to specify objectMessageAsJsonObject="true", but suspect it's a bit more nuanced when using JsonTemplateLayout.

TIA.

1 Answers

Upon reading the JSON Template Layout docs further, you can modify the event template fields by leveraging the eventTemplateAdditionalField param.

There seems to be a few ways to approach this but the option I went with is to modify the log4j2.xml:

<Appenders>
        <Console name="JsonAppender" target="SYSTEM_OUT">
            <JsonTemplateLayout eventTemplateUri="classpath:LambdaEcsLayout.json">
                <EventTemplateAdditionalField
                        key="message"
                        format="JSON"
                        value='{"$resolver": "message", "field": "name"}'/>/>
            </JsonTemplateLayout>

        </Console>
    </Appenders>

And when logging, have something like this:

var logMap = new HashMap<>();
        logMap.put("id", "123456789");
        logMap.put("action", "Received request");
        var om = new ObjectMessage(logMap);

        log.info(om);

There is probably a much neater way to deal with the latter, some kind of wrapper etc - but you get the idea.

Related