Search code examples
javaspring-bootlog4jlog4j2

Why does log4j filter not works inside appender


I've create a custom filter that looks like this:

@Plugin(name = "EmptyMessageFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
public class EmptyMessageFilter extends AbstractFilter {

  @PluginFactory
  public static EmptyMessageFilter createFilter() {
    return new EmptyMessageFilter();
  }
...
}

The log4j config file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Properties>
        <Property name="LOG_PATTERN">
            %d{yyyy-MM-dd HH:mm:ss.SSS}
        </Property>
    </Properties>
    <!-- When filter is here it works -->
    <Filters>
        <EmptyMessageFilter/>
    </Filters>
    <Appenders>
        <Console name="ConsoleAppender" target="SYSTEM_OUT" follow="true">
            <PatternLayout pattern="${LOG_PATTERN}"/>
        <!-- When filter is here it does not work -->
        <Filters>
            <EmptyMessageFilter/>
        </Filters>  
        </Console>
  
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="ConsoleAppender"/>
        </Root>
    </Loggers>
</Configuration>

When the filter is configured inside the Console appender it does not work but when it's outside the appenders it works. According to this https://logging.apache.org/log4j/2.x/manual/configuration.html#Loggers both should work. Any hints whats wrong?

The predefined filters like RegexFilter or BurstFilter works as well inside the appender but i don't see a difference between my custom filter and the predifined filters....


Solution

  • Unlike Logback, which defines a separate Filter and TurboFilter interface, Log4j Core has a single Filter interface that has a double purpose:

    • the filter(LogEvent) method is used when the filter is:

      1. attached to an appender,
      2. attached to an appender reference,
      3. attached to a logger configuration (as in your case).
    • the remaining filter methods are only used when your filter is a global filter (directly attached to a configuration).

    Your filter(LogEvent) method must work incorrectly, hence the issue. Remark that in this case you always have a message (usually of type ObjectMessage, SimpleMessage or ParameterizedMessage), although this message might be a mutable one.