apache / logging-log4j2

Apache Log4j 2 is a versatile, feature-rich, efficient logging API and backend for Java.
https://logging.apache.org/log4j/2.x/
Apache License 2.0
3.39k stars 1.62k forks source link

NPE while using custom Log Levels with JsonTemplateLayout #1805

Closed srangara123 closed 1 year ago

srangara123 commented 1 year ago

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

vy commented 1 year ago

@srangara123, thanks so much for the report! Fixed for both 2.x and main.

chandrabol commented 1 month ago

@vy - Is this fixed? I'm using log4j2 version 2.19.0 and still getting the same issue.

at java.base/java.util.Objects.requireNonNull(Objects.java:235) 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:302) at org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.encode(JsonTemplateLayout.java:58) 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.async.AsyncLoggerConfig.callAppenders(AsyncLoggerConfig.java:149) 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.async.AsyncLoggerConfig.log(AsyncLoggerConfig.java:143) at org.apache.logging.log4j.core.async.AsyncLoggerConfig.logToAsyncLoggerConfigsOnCurrentThread(AsyncLoggerConfig.java:191) at org.apache.logging.log4j.core.async.AsyncLoggerConfigDisruptor$Log4jEventWrapperHandler.onEvent(AsyncLoggerConfigDisruptor.java:112) at org.apache.logging.log4j.core.async.AsyncLoggerConfigDisruptor$Log4jEventWrapperHandler.onEvent(AsyncLoggerConfigDisruptor.java:98) at com.lmax.disruptor.BatchEventProcessor.processEvents(BatchEventProcessor.java:168) at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:125) at java.base/java.lang.Thread.run(Thread.java:840)

vy commented 1 month ago

@chandrabol as both the release notes and the milestone this issue is labeled with, the fix was delivered with version 2.21.0. Though note that the most recent Log4j version as of date is 2.24.0, which you should be using.