Search code examples
javalog4jlog4j2

RegexFilter in Log4j2.xml not filtering logs as expected


I can't seem to get the RegexFilter working. I have set up the log4j2.xml file as follows:

<Console name="prodOutput" target="SYSTEM_OUT">
    <PatternLayout pattern="[%d] [Org Utility] -- [ITEM1=%X{ITEM1} ITEM2=%X{ITEM2} ITEM3=%X{ITEM3} USERID=%X{USERID} ENV=%X{ENV}]- [%t] %-5p %c %x - %m%n"/>
    <Filters>
        <RegexFilter regex=".*ENV=local.*" useRawMsg="false" onMatch="DENY" onMismatch="NEUTRAL"/>
    </Filters>
</Console>

<Loggers>

        <!-- switch off log output from these packages -->
        <Logger name="orgName.package1" level="debug" additivity="false">
            <appender-ref ref="prodOutput"/>
        </Logger>

        <!-- retain log output for other packages -->
        <Logger name="orgName" level="trace" additivity="false">
            <appender-ref ref="${sys:logger.out.type}"/>
        </Logger>
        <Root level="info" additivity="false">
            <appender-ref ref="${sys:logger.out.type}"/>
        </Root>

</Loggers>

Here's a sample of our log output, but somehow the log from this package orgName.package1 is not getting picked up the regex, because I can still see the log from this package in the console.

[2023-01-03 12:41:56,353] [Org Utility] -- [ITEM1=XX ITEM2=XX ITEM3=XX USERID=@ADMIN ENV=local]- [ForkJoinPool-1-worker-29] DEBUG orgName.executeRule [] ...

Because when I replace the regex with the trivial .*, the output from the package orgName.package1 is not shown in the console.

The value of ENV in ThreadContextMap is local, so I'm expecting the log output to be ... ENV=local ... & it indeed is, as shown in the console. But this log is somehow not getting detected by the regex.

Is there a setting or configuration I missed out on? Or perhaps I had miswrote the regex? But I had double-checked my regex on regex101.com & the test-cases I wrote passed, here's a sample.


Solution

  • I understand why the RegexFilter doesn't work, it's because I'm trying to apply a regex on the logger & not the message.

    RegexFilter is intended to apply regexes on messages, i.e. ONLY the part that you define in the PatternLayout using the %m Conversion Pattern), and NOT details associated with the logger (type, time, package, class name etc).


    Example

    Here is the pattern definition in log4j2.xml file:

    <PatternLayout pattern="%d{ISO8601} %p %C.%M - %m%n"/>
    

    And here is a sample log:

    2024-03-28T05:40:30,667 INFO com.example.Foo.doSomething - This is a log message
    

    So using the <RegexFilter> you can only target the message which in this case is:

    This is a log message

    ONLY this part will be checked for a match.


    I referenced this StackOverflow post that was very similar to my question.

    Hope this serves as a helpful guide to anyone that comes across this, cheers!