zabetak
zabetak

Reputation: 457

Configure composite filter for specific logger in Log4j2 via properties file

Log4j2 provides various kind of filters [1] and these can be configured at four levels:

  1. Context-wide
  2. Logger
  3. Appender
  4. Appender Reference

In my use-case, I would like to setup a CompositeFilter at a specified Logger (level 2 from above) using the property file syntax.

For the sake of the example let's assume that we want to setup a composite filter composed from two RegexFilter matching .*SQL.* and .*JPQL.* respectively. Assuming that we have the following events:

logger.info("Messase with no keyword");
logger.info("Messase with SQL keyword");
logger.info("Messase with JPQL keyword");
logger.info("Messase with both SQL and JPQL keywords");

Only the last event should pass from the composite filter.

I made several attempts [2] (also outlined below) to get the desired output but I wasn't able to figure out how to properly setup a CompositeFilter using the property syntax so any help would be greatly appreciated.

Attempt 0

logger.t1.filter.f1.type = RegexFilter
logger.t1.filter.f1.regex = .*SQL.*
logger.t1.filter.f1.onMatch = NEUTRAL
logger.t1.filter.f1.onMismatch = DENY
logger.t1.filter.f2.type = RegexFilter
logger.t1.filter.f2.regex = .*JPQL.*
logger.t1.filter.f2.onMatch = ACCEPT
logger.t1.filter.f2.onMismatch = DENY
logger.t1.appenderRefs = a
logger.t1.appenderRef.a.ref = L0

Attempt 1

logger.t1.filters = f1, f2
logger.t1.filter.f1.type = RegexFilter
logger.t1.filter.f1.regex = .*SQL.*
logger.t1.filter.f1.onMatch = NEUTRAL
logger.t1.filter.f1.onMismatch = DENY
logger.t1.filter.f2.type = RegexFilter
logger.t1.filter.f2.regex = .*JPQL.*
logger.t1.filter.f2.onMatch = ACCEPT
logger.t1.filter.f2.onMismatch = DENY

Attempt 2

logger.t1.filters.f1.type = RegexFilter
logger.t1.filters.f1.regex = .*SQL.*
logger.t1.filters.f1.onMatch = NEUTRAL
logger.t1.filters.f1.onMismatch = DENY
logger.t1.filters.f2.type = RegexFilter
logger.t1.filters.f2.regex = .*JPQL.*
logger.t1.filters.f2.onMatch = ACCEPT
logger.t1.filters.f2.onMismatch = DENY
logger.t1.appenderRefs = a
logger.t1.appenderRef.a.ref = L0

Attempt 3

logger.t1.filter.M.type = Filters
logger.t1.filter.M.f1.type = RegexFilter
logger.t1.filter.M.f1.regex = .*SQL.*
logger.t1.filter.M.f1.onMatch = NEUTRAL
logger.t1.filter.M.f1.onMismatch = DENY
logger.t1.filter.M.f2.type = RegexFilter
logger.t1.filter.M.f2.regex = .*JPQL.*
logger.t1.filter.M.f2.onMatch = ACCEPT
logger.t1.filter.M.f2.onMismatch = DENY
logger.t1.appenderRefs = a
logger.t1.appenderRef.a.ref = L0

Some further clarifications:

[1] https://logging.apache.org/log4j/2.x/manual/filters.html

[2] https://github.com/zabetak/logging-log4j2/commit/a9944885100db42f7e3ba1b3ff81d59b743d0ab7

Upvotes: 1

Views: 1324

Answers (1)

Piotr P. Karwasz
Piotr P. Karwasz

Reputation: 16045

There are two problems with your configuration:

  1. A LoggerConfig accepts only a single filter. If you want to use multiple filters, configure a CompositeFilter explicitly (which has a plugin name "Filters),
  2. The order of filters in a properties configuration file is basically random, since Properties is a Hashtable and does not have a predefined order.

Considering the two facts above a variation of your attempt 3 should work:

logger.t1.filter.M.type = Filters
logger.t1.filter.M.f1.type = RegexFilter
logger.t1.filter.M.f1.regex = .*SQL.*
logger.t1.filter.M.f1.onMatch = NEUTRAL
logger.t1.filter.M.f1.onMismatch = DENY
logger.t1.filter.M.f2.type = RegexFilter
logger.t1.filter.M.f2.regex = .*JPQL.*
logger.t1.filter.M.f2.onMatch = NEUTRAL
logger.t1.filter.M.f2.onMismatch = DENY

Both filters return NEUTRAL, when the pattern matches, which guarantees that an inversion of the order of filters does not break the logic.

Upvotes: 1

Related Questions