How to Modify Log4J Jsonlayout Field Names

How to customize or remove default attributes in Log4j2 - JSON Layout

If you want to log only level and loggerName than customize like below in your configuration file.

...
<PatternLayout>
<pattern>{"level":"%p","loggerName":"%c"}</pattern>
</PatternLayout>
...

The parameter are described at here. Find Patterns at Pattern Layout.

Adding custom field to log4j json layout breaks spring logging structure

  1. download Jackson Annotations and import it because JsonLayout use Jackson Annotations internal code.

    • in my case, download and import these
jackson-annotations-2.10.3.jar
jackson-core-2.10.3.jar
jackson-databind-2.10.3.jar

  1. add <JsonLayout>...</JsonLayout> in your config(in my case log4j2.xml) like below
<JsonLayout>
<KeyValuePair key="testKey" value="testValue"/>
</JsonLayout>

Replace key and value to what you want to use. In my case key is "testKey" and value is "testValue"


  1. run and check your log!

it it my full sample code and xml configuration info.
code

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

public class LogTest{
private static final Logger logger = LogManager.getLogger(LogTest.class.getName());


public static void main(String[] args) {
ThreadContext.put("logFileName", "testFile1" );
logger.info("log printed! - testFile1");

ThreadContext.put("logFileName", "testFile2" );
logger.info("log printed! - testFile2");

ThreadContext.remove("logFileName");
}

}

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Routing name="RoutingAppender">
<Routes pattern="${ctx:logFileName}">
<Route>
<RollingFile name="Rolling-${ctx:logFileName}"
fileName="./logs/${ctx:logFileName}.log"
filePattern="./logs/${ctx:logFileName}.%i.log.gz">
<JsonLayout>
<KeyValuePair key="testKey" value="testValue"/>
</JsonLayout>
<SizeBasedTriggeringPolicy size="512" />
</RollingFile>
</Route>
</Routes>
</Routing>
</Appenders>

<Loggers>
<Root level="all">
<AppenderRef ref="RoutingAppender" />
</Root>
</Loggers>
</Configuration>

output

{
"instant" : {
"epochSecond" : 1588590944,
"nanoOfSecond" : 469000000
},
"thread" : "main",
"level" : "INFO",
"loggerName" : "com.test.LogTest",
"message" : "log printed! - testFile2",
"endOfBatch" : false,
"loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
"threadId" : 1,
"threadPriority" : 5,
"testKey" : "testValue"
}

Log4J2 JSONLAYOUT How to add custom Parameters

Solution is to explicitly add log4j2’s 2.10.0 version. This version supports custom parameter in JSONLayout!

<Appenders>

<Console name="Console" target="SYSTEM_OUT">
<JSONLayout compact="true" eventEol="true">
<KeyValuePair key="application" value="${sys:com.example.appname}"/>
</JSONLayout>
</Console>
<Async name="AsyncAppender" bufferSize="80">
<AppenderRef ref="Console"/>
</Async>

</Appenders>

Log4j2 JSON Layout: add custom date field in UTC

You can create your own lookup since, as I'm sure you already know, the KeyValuePair supports lookups in its value attribute per the manual page you shared.

For example purposes I created a simple lookup that uses System.currentTimeMillis().

Here is the example code:

First, the lookup class:

package utcTime;

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.lookup.StrLookup;

@Plugin(name = "UtcMillis", category = "Lookup")
public class UtcMillisLookup implements StrLookup{
/**
* Lookup the value for the key.
* @param key the key to be looked up, may be null
* @return The value for the key.
*/
public String lookup(String key) {
return String.valueOf(getUTCMillis());
}

/**
* @return current UTC time in milliseconds
*/
private long getUTCMillis(){
return System.currentTimeMillis();
}

/**
* Lookup the value for the key using the data in the LogEvent.
* @param event The current LogEvent.
* @param key the key to be looked up, may be null
* @return The value associated with the key.
*/
public String lookup(LogEvent event, String key) {
return String.valueOf(getUTCMillis());
}
}

Next, the log4j2.xml configuration file:

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

</Appenders>

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

Note that the lookup has no parameters/keys so you can leave that part empty/blank but you still have to use the colon (:) and this is why you see $${UtcMillis:} in the above configuration.

Finally, a simple class to generate a log event:

package utcTime;

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

public class MainUtcLookup {
private static final Logger log = LogManager.getLogger();
public static void main(String[] args){
log.info("Here's some info!");
}
}

Here is sample output:

{  
"thread":"main",
"level":"INFO",
"loggerName":"utcTime.MainUtcLookup",
"message":"Here's some info!",
"endOfBatch":false,
"loggerFqcn":"org.apache.logging.log4j.spi.AbstractLogger",
"instant":{
"epochSecond":1534642997,
"nanoOfSecond":556000000
},
"threadId":1,
"threadPriority":5,
"@timestamp":"1534642997558"
}

I'm not going to delve into the details of all the different ways you can get the current time in UTC milliseconds as I'm sure you can research the details of that on your own. I just wanted to provide an example of how you could accomplish your primary goal of adding the millisecond timestamp to your log4j2 JSONLayout.

Hope this helps!



Related Topics



Leave a reply



Submit