javaregexlog4jlog4j2mdc

Is it possible to filter key-value pairs of a ThreadContextMap with a Regex?


I wish to filter certain logs if the "env" key in the ThreadContextMap has a value of prod1 or qa1.

I already have something like the following set up:

<Console name="prodOutput" target="SYSTEM_OUT">
    <PatternLayout pattern="..."/>
    <Filters>
        <ThreadContextMapFilter onMatch="DENY" onMismatch="NEUTRAL" operator="or">
            <KeyValuePair key="ENV" value="qa1"/>
            <KeyValuePair key="ENV" value="prod1"/>
        </ThreadContextMapFilter>
    </Filters>
</Console>

But this code "hardcodes" the values prod1 & qa1. In the spirit of making the code extensible, I want to filter out those logs if they match the regex of "prod\d+" or "qa\d+".

Values that would match these regex's include "prod1", "qa2".

This is because we don't want those certain logs to appear on production & qa environments.

In the ThreadContextMap, the key-value pairs we're checking for is ENV-prod1 or ENV-qa1.

I searched StackOverflow as well as the log4j2 documentation but there doesn't seem to be any mention of how such a thing can be done.

Any ideas on how I can approach this or alternatives?


Solution

  • I managed to find a workaround solution, where I instead apply the regex to the value being inserted into the ThreadContextMap

    This way, I only ever have to check for 2 values in the ThreadContextMapFilter, prod & qa

    This solution is satisfactory enough as it works & meets the requirements we had. For those curious, it looks something like this:

    @Value("${env}")
    private String environment;
    ...
    // check environment against regex
    boolean matchesProdRegex = Pattern.matches(".*prod.*", this.environment);
    boolean matchesQaRegex = Pattern.matches(".*qa.*", this.environment);
    if (matchesProdRegex ) {
      ThreadContext.put("ENV", "prod");
    } else if (matchesQaRegex ) {
      ThreadContext.put("ENV", "qa");
    } else {
      ThreadContext.put("ENV", this.environment);
    }
    

    Consequently in log4j2.xml, the ThreadContextMapFilter looks something like:

    <Console name="prodOutput" target="SYSTEM_OUT">
        <PatternLayout pattern="..."/>
        <Filters>
            <ThreadContextMapFilter onMatch="DENY" onMismatch="NEUTRAL" operator="or">
                <KeyValuePair key="ENV" value="qa"/>
                <KeyValuePair key="ENV" value="prod"/>
            </ThreadContextMapFilter>
        </Filters>
    </Console>
    

    Thanks to anyone that took the time to read my post & hope this can be a useful reference for anyone in the future, cheers!