I am trying figure out JSON logging using log4j2 as documented in https://logging.apache.org/log4j/2.x/manual/layouts.html#JSONLayout
All works fine except when I am trying to log an object as json by setting objectMessageAsJsonObject=true using SLF4J logger object. SLF4j logger simply ignores the object. Whereas when i use an instance of org.apache.logging.log4j.Logger it works.
This feature(Logging an object as json via JSON layout) has been added in Log4j2 with github issue https://github.com/apache/logging-log4j2/pull/141
Tried by creating a new instance of org.apache.logging.log4j.message.ObjectMessage and passing to SLF4J , but looks like it simply ignores it.
//THIS DOES NOT WORK
logger_slf4j.info(MarkerFactory.getMarker("SLF4J_LOGGER"), "SLF4J logger log object as json", om);
//THIS WORKS
logger_log4j2.info(MarkerManager.getMarker("LOG4J2_LOGGER"), om);
More details can be found in code section below.
pom.xml
<properties>
<slf4j.version>1.7.28</slf4j.version>
<log4j2.version>2.12.1</log4j2.version>
<jackson.version>2.9.5</jackson.version>
</properties>
!-- slf4j dependencies -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Log4j2 dependencies -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j2.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j2.version}</version>
<scope>provided</scope>
</dependency>
<!-- This is used by JSONLayout. -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
<scope>provided</scope>
</dependency>
log4j2.xml
<Configuration status="debug" strict="true">
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<JSONLayout compact="true" eventEol="true" objectMessageAsJsonObject="true"/>
</Console>
</Appenders>
<loggers>
<Logger name="com.logging.test" level="all"/>
<root level="all">
<appender-ref ref="STDOUT"/>
</root>
</loggers>
</Configuration>
User object to be logged as json
public class User implements Serializable {
private String firstName;
private String lastName;
}
JUnit
public class SampleLoggingTest {
private static final org.apache.logging.log4j.Logger logger_log4j2 = LogManager.getLogger(SampleLoggingTest.class);
private static final org.slf4j.Logger logger_slf4j = LoggerFactory.getLogger(SampleLoggingTest.class);
private static final Marker TEST_MARKER = MarkerFactory.getMarker("SLF_LOG");
@Test
public void test_logging(){
User user = new User("john","doe");
ObjectMessage om=new ObjectMessage(msg);
logger_slf4j.info(MarkerFactory.getMarker("SLF4J_LOGGER"), "SLF4J logger log object as json", om);
logger_log4j2.info(MarkerManager.getMarker("LOG4J2_LOGGER"), om);
}
}
Expected(Using SLF4J logger):
{"thread":"main","level":"INFO","loggerName":"com.logging.test.SampleLoggingTest","marker":{"name":"SLF4J_LOGGER"},"message":{"firtsName":"john","lastName":"doe"},"endOfBatch":false,"loggerFqcn":"org.apache.logging.slf4j.Log4jLogger","instant":{"epochSecond":1571770198,"nanoOfSecond":746000000},"threadPriority":5,"threadId":1}
Actual(Using SLF4J logger):
{"thread":"main","level":"INFO","loggerName":"com.logging.test.SampleLoggingTest","marker":{"name":"SLF4J_LOGGER"},"message":"Test Message","endOfBatch":false,"loggerFqcn":"org.apache.logging.slf4j.Log4jLogger","instant":{"epochSecond":1571770198,"nanoOfSecond":746000000},"threadPriority":5,"threadId":1}
Expected(Using LOG4J logger):
{"thread":"main","level":"INFO","loggerName":"com.logging.test.SampleLoggingTest","marker":{"name":"LOG42L_LOGGER"},"message":{"firtsName":"john","lastName":"doe"},"endOfBatch":false,"loggerFqcn":"org.apache.logging.slf4j.Log4jLogger","instant":{"epochSecond":1571770198,"nanoOfSecond":746000000},"threadPriority":5,"threadId":1}
Question
- Is it possible to log an object using log4j2 JSON layout by using an SLF4J logger ?? If so any example will be helpful.
- Is there any easier way to change the instant to a human readable date and timestamp format ?