Closed
Description
Description
We have an application that defines custom Log Levels.
When we use the JsonTemplateLayout
(https://logging.apache.org/log4j/2.x/manual/json-template-layout.html)
we sometimes get a Null pointer Exception
This is due to the LevelResolver caching the Levels before we create our custom Log Levels
Please refer to the main method below.
Configuration
Version: 2.20.0
Operating system: Windows
JDK: JDK 1.8
Logs
{"@timestamp":"2023-09-19T18:46:34.239Z","ecs.version":"1.2.0","log.level":"INFO","message":"{foo=bar, foo_1=bar_1}","process.thread.name":"main","log.logger":"com.simple.log4j.LoggerTest"}
ERROR StatusConsoleListener An exception occurred processing Appender Console
java.lang.NullPointerException: seq
at java.util.Objects.requireNonNull(Objects.java:228)
at org.apache.logging.log4j.layout.template.json.util.JsonWriter.writeRawString(JsonWriter.java:800)
at org.apache.logging.log4j.layout.template.json.resolver.LevelResolver.lambda$createNameResolver$3(LevelResolver.java:144)
at org.apache.logging.log4j.layout.template.json.resolver.LevelResolver.resolve(LevelResolver.java:172)
at org.apache.logging.log4j.layout.template.json.resolver.LevelResolver.resolve(LevelResolver.java:75)
at org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver.resolve(TemplateResolver.java:66)
at org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers$PrefixedFieldResolverMethod.resolve(TemplateResolvers.java:353)
at org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers$MapResolver.resolve(TemplateResolvers.java:409)
at org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.encode(JsonTemplateLayout.java:304)
at org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.encode(JsonTemplateLayout.java:60)
at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.directEncodeEvent(AbstractOutputStreamAppender.java:215)
at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.tryAppend(AbstractOutputStreamAppender.java:208)
at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:199)
at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:161)
at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:134)
at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:125)
at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:89)
at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:683)
at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:641)
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:624)
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:560)
at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:82)
at org.apache.logging.log4j.core.Logger.log(Logger.java:163)
at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2168)
at org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2122)
at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2105)
at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1799)
at org.apache.logging.log4j.spi.AbstractLogger.log(AbstractLogger.java:1585)
at com.simple.log4j.LoggerTest.main(LoggerTest.java:20)
Reproduction
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<JsonTemplateLayout eventTemplateUri="classpath:EcsLayout.json" />
</Console>
</Appenders>
<Loggers>
<Root level="ALL">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>
Log4j2.xml file
public static void main(String[] args) {
Logger logger = LogManager.getLogger("json-logger");
Map<String, String> logMap = new HashMap<>();
logMap.put("foo", "bar");
logMap.put("foo_1", "bar_1");
logger.info(new ObjectMessage(logMap));
logger.log(org.apache.logging.log4j.Level.forName("MY_CUSTOM_LEVEL", 250), new ObjectMessage(logMap));
}
This last line produces a NPE