Filters

Filters are Log4j plugins that evaluate the parameters of a logging call or a log event and return one of three results:

ACCEPT

The filter accepts the log event. This effectively causes other filters in the same filtering stage to be skipped.

DENY

The filter drops the log event.

NEUTRAL

Log4j behaves as if the filter was not present. It is evaluated by the next filter in the filter chain.

Filters can be used at each level of the logging pipeline:

Additionally, the following configuration attributes take part in the filtering process:

Filtering process

Due to the interaction of many elements, the filtering process in Log4j is quite complex and can be divided in four stages:

For performance reasons, log events should be filtered at the earliest possible stage. This reduces the cost of disabled log events: e.g., log event creation, population of context data, formatting, transfer through an asynchronous barrier.

1. Logger stage

Diagram

The parameters of the logging call are passed to the global filter. If the global filter returns:

DENY

The log message is immediately discarded.

NEUTRAL

If the level of the log message is less severe than the configured logger threshold, the message is discarded. Otherwise, a LogEvent is created and processing continues.

ACCEPT

A LogEvent is created and processing continues in the next stage.

This is the only stage, which differentiates between an ACCEPT and NEUTRAL filter result.

Filtering logging calls at this stage provides the best performance:

2. LoggerConfig stage

Diagram

In this stage, log events are evaluated by all the logger filters that stand on the path from the logger to an appender. Due to the additivity of logger configurations, this means that a log event must also pass the filters of all the parent loggers, until it reaches the logger that references the chosen appender.

3. AppenderControl stage

Diagram

To pass this stage, log events must satisfy both conditions:

4. Appender stage (optional)

Diagram

If the appender implements Filterable an additional filtering stage is available. When log events reach such an appender, the filter attached to an appender is evaluated and if the result is DENY, the log event is discarded.

All standard appenders implement Filterable.

Some appenders like the asynchronous appender use appender references to transfer log events to other appenders. In such a case, the filtering process goes back to the AppenderControl stage.

Users migrating from Log4j 1 often replace the threshold property of a Log4j 1 appender with a ThresholdFilter on the equivalent Log4j 2 appender.

Using the level property of appender references will give a better performance.

Configuring filters at this stage is a measure of last resort, since it adds a large overhead to disabled log events. You should rather configure the filtering in one of the previous stages.

Example configuration file

The following example configuration file employs filters at all possible stages to explain their evaluation order:

  • XML

  • JSON

  • YAML

  • Properties

<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns="https://logging.apache.org/xml/ns"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="
                   https://logging.apache.org/xml/ns
                   https://logging.apache.org/xml/ns/log4j-config-2.xsd">
  <Appenders>
    <Console name="CONSOLE">
      <ThresholdFilter level="FATAL"/> (7)
    </Console>
  </Appenders>
  <Loggers>
    <Root level="OFF">
      <ThresholdFilter level="WARN"/> (4)
      <AppenderRef ref="CONSOLE" level="ERROR"> (5)
        <MarkerFilter marker="SECURITY_ALERT"/> (6)
      </AppenderRef>
    </Root>
    <Logger name="org.example" level="DEBUG"> (2)
      <ThresholdFilter level="INFO"/> (3)
    </Logger>
  </Loggers>
  <MarkerFilter marker="ALERT"
                onMatch="ACCEPT"
                onMismatch="NEUTRAL"/> (1)
</Configuration>
{
  "Configuration": {
    "Appenders": {
      "Console": {
        "name": "CONSOLE",
        "ThresholdFilter": {
          "level": "FATAL" (6)
        }
      }
    },
    "Loggers": {
      "Root": {
        "level": "OFF",
        "ThresholdFilter": { (3)
          "level": "WARN"
        },
        "AppenderRef": {
          "ref": "CONSOLE",
          "level": "ERROR", (4)
          "MarkerFilter": { (5)
            "marker": "SECURITY_ALERT"
          }
        }
      },
      "Logger": {
        "name": "org.example",
        "level": "DEBUG", (2)
        "ThresholdFilter": { (3)
          "level": "INFO"
        }
      }
    }
  },
  "MarkerFilter": { (1)
    "marker": "ALERT",
    "onMatch": "ACCEPT",
    "onMismatch": "NEUTRAL"
  }
}
Configuration:
  Appenders:
    Console:
      name: "CONSOLE"
      ThresholdFilter: (7)
        level: "FATAL"
  Loggers:
    Root:
      level: "OFF"
      ThresholdFilter: (4)
        level: "WARN"
      AppenderRef:
        ref: "CONSOLE"
        level: "ERROR" (5)
        MarkerFilter: (6)
          marker: "SECURITY_ALERT"
      Logger:
        name: "org.example"
        level: "DEBUG" (2)
        ThresholdFilter: (3)
          level: "INFO"
  MarkerFilter: (1)
    marker: "ALERT"
    onMatch: "ACCEPT"
    onMismatch: "NEUTRAL"
appender.0.type = Console
appender.0.name = CONSOLE
(7)
appender.0.filter.type = ThresholdFilter
appender.0.filter.level = FATAL

rootLogger.level = OFF
(4)
rootLogger.filter.type = ThresholdFilter
rootLogger.filter.level = WARN
rootLogger.appenderRef.0.ref = CONSOLE
(5)
rootLogger.appenderRef.0.level = ERROR
(6)
rootLogger.appenderRef.0.filter.type = MarkerFilter
rootLogger.appenderRef.0.filter.marker = SECURITY_ALERT

logger.0.name = org.example
(2)
logger.0.level = DEBUG
(3)
logger.0.filter.type = ThresholdFilter
logger.0.filter.level = INFO

(1)
filter.0.type = MarkerFilter
filter.0.marker = ALERT
filter.0.onMatch = ACCEPT
filter.0.onMismatch = NEUTRAL
1 Global filter
2 Logger level attribute. This setting is ignored unless the global filter returns NEUTRAL.
3 Filter of the org.example logger
4 Filter of the root logger (it is the parent of the org.example logger)
5 Appender reference level attribute
6 Filter of the appender reference
7 Filter of the appender

Common configuration

Common configuration attributes

The default behavior of filters is in line with the filter() methods of functional interfaces, such as Optional.filter() or Stream.filter(): filters pass matching events to the next filter and drop those that do not match.

To allow for a larger spectrum of behaviors, all standard filters, except CompositeFilter and DenyAllFilter, accept the following configuration attributes:

Table 1. Common filter configuration attributes
Attribute Type Default value Description

onMatch

Result

NEUTRAL

Result returned if the condition matches.

onMismatch

Result

DENY

Result returned if the condition does not match.

Composing filters

Filters usually test for a single condition. To express a more complex filtering logic, Log4j provides a Filters plugin. This plugin can contain a sequence of filters and has no other configuration option.

The Filters plugin sequentially evaluates each sub-filter and:

  • if the sub-filter returns ACCEPT (resp. DENY), the Filters plugin returns ACCEPT (resp. DENY).

  • if the sub-filter return NEUTRAL, the Filters plugin evaluates the next sub-filter in the chain.

  • if the last sub-filter returns NEUTRAL, the Filters plugin returns NEUTRAL.

The Filters plugin together with the ternary logic of filters, can be used to express most boolean operators. In the following examples A and B are two filters.

NOT A

You can invert the functionality of filter A by swapping the onMatch and onMismatch:

<A onMatch="DENY" onMismatch="NEUTRAL"/>
A AND B

To select the events that match both A and B you can use:

<Filters>
  <A/>
  <B/>
</Filters>
A OR B

To select the events that match A or B we can replace NEUTRAL with ACCEPT in the onMatch attribute:

<Filters>
  <A onMatch="ACCEPT"/>
  <B onMatch="ACCEPT"/>
</Filters>

Collection

Log4j Core provides the following filters out-of-the-box.

Timestamp filters

Timestamp filters use the timestamp of log events to decide whether to accept them or not.

BurstFilter

The BurstFilter limits the rate of log events. The rate limit is only applied to log events less severe than a configured log level.

Besides the common configuration attributes, the BurstFilter supports the following parameters:

Table 2. BurstFilter — configuration attributes
Attribute Type Default value Description

level

Level

WARN

The rate limit only applies to log events less severe than this level. Events at least as severe as this level will always match.

rate

float

10

The average number of events per second to allow.

maxBurst

long

10 × rate

The maximum number of events that can be logged at once, without incurring in rate limiting.

The BurstFilter uses the sliding window log algorithm with a window window of maxBurst / rate seconds.

The filter maintains a list of recently logged events. If in the interval of time of duration window preceding the current log event, more than maxBurst events have already been logged, rate limiting is applied.

To control the size of the log files only the rate attribute needs to be taken into account. The maxBurst attribute controls the temporal spacing between log events: lower values of maxBurst will give more evenly spaced log events, while higher values will allow for peaks of activity followed by an absence of log events.

TimeFilter

The TimeFilter only matches log events emitted during a certain time of the day.

Besides the common configuration attributes, the TimeFilter supports the following parameters:

Table 3. TimeFilter — configuration attributes
Attribute Type Default value Description

start

LocalTime in HH:mm:ss format

LocalTime.MIN

The beginning of the time slot.

start

LocalTime in HH:mm:ss format

LocalTime.MAX

The end of the time slot.

timezone

ZoneId

ZoneId.systemDefault()

The timezone to use when comparing start and end to the event timestamp.

As a simple application of this filter, if you want to forward messages to your console during work hours and to your e-mail account after work hours, you can use a configuration snippet like:

  • XML

  • JSON

  • YAML

  • Properties

Snippet from an example log4j2.xml
<AppenderRef ref="CONSOLE">
  <TimeFilter start="08:00:00" end="16:00:00"/>
</AppenderRef>
<AppenderRef ref="SMTP">
  <TimeFilter start="16:00:00" end="08:00:00"/>
</AppenderRef>
Snippet from an example log4j2.json
"AppenderRef": [
  {
    "ref": "CONSOLE",
    "TimeFilter": {
      "start": "08:00:00",
      "end": "16:00:00"
    }
  },
  {
    "ref": "SMTP",
    "TimeFilter": {
      "start": "16:00:00",
      "end": "08:00:00"
    }
  }
]
Snippet from an example log4j2.yaml
AppenderRef:
  - ref: "CONSOLE"
    TimeFilter:
      start: "08:00:00"
      end: "16:00:00"
  - ref: "SMTP"
    TimeFilter:
      start: "16:00:00"
      end: "08:00:00"
Snippet from an example log4j2.properties
rootLogger.appenderRef.0.ref = CONSOLE
rootLogger.appenderRef.0.filter.0.type = TimeFilter
rootLogger.appenderRef.0.filter.0.start = 08:00:00
rootLogger.appenderRef.0.filter.0.end = 16:00:00

rootLogger.appenderRef.1.ref = SMTP
rootLogger.appenderRef.1.filter.0.type = TimeFilter
rootLogger.appenderRef.1.filter.0.start = 16:00:00
rootLogger.appenderRef.1.filter.0.end = 08:00:00

Level filters

The following filters allow you to filter log events based on their levels.

LevelMatchFilter

The LevelMatchFilter matches log events that have exactly a certain log level.

Besides the common configuration attributes, the LevelMatchFilter supports the following parameter:

Table 4. LevelMatchFilter — configuration attributes
Attribute Type Default value Description

level

Level

ERROR

The filter only matches log events of this level.

If you wish to use a different log file for each log level, you should also use a Routing appender together with the ${event:Level} lookup. Such a solution will ensure that:

  • you don’t forget any log level (Log4j supports custom levels).

  • you don’t need to configure an appender for each level separately.

LevelRangeFilter

The LevelRangeFilter matches log events with a log level within a configured range.

Besides the common configuration attributes, the LevelRangeFilter supports the following parameter:

Table 5. LevelRangeFilter — configuration attributes
Attribute Type Default value Description

minLevel

Level

OFF

The filter only matches log events at most as severe as this level.

maxLevel

Level

ALL

The filter only matches log events at least as severe as this level.

Make sure not to invert the bounds of the range. Starting from the smallest level, the Log4j API defines: OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE and ALL.

ThresholdFilter

The ThresholdFilter matches log events at least as severe as a configured level.

Besides the common configuration attributes, the ThresholdFilter supports the following parameter:

Table 6. ThresholdFilter—configuration attributes
Attribute Type Default value Description

level

Level

OFF

The filter only matches log events at least as severe as this level.

DynamicThresholdFilter

The DynamicThresholdFilter is a variant of ThresholdFilter, which uses a different threshold for each log event. The effective threshold to use is determined by querying the context data of the log event. For each log event:

  1. The filter retrieves the value of key in the context data map.

  2. The filter checks the list of nested KeyValuePair configuration elements to decide which level to apply.

Besides the common configuration attributes, the DynamicThresholdFilter supports the following parameters:

Table 7. DynamicThresholdFilter—configuration attributes
Attribute Type Default value Description

key

String

The key to a value in the context map of the log event.

Required

defaultThreshold

Level

ERROR

Threshold to apply to log events that don’t have a corresponding KeyValuePair.

Table 8. DynamicThresholdFilter—nested elements
Type Multiplicity Description

KeyValuePair

One or more

Associates a log level with the context map value associated with key.

For example, if loginId contains the login of the current user, you can use this configuration to apply different thresholds to different users:

  • XML

  • JSON

  • YAML

  • Properties

Snippet from an example log4j2.xml
<DynamicThresholdFilter key="loginId"
                        defaultThreshold="ERROR"> (3)
  <KeyValuePair key="alice" value="DEBUG"/> (1)
  <KeyValuePair key="bob" value="INFO"/> (2)
</DynamicThresholdFilter>
Snippet from an example log4j2.json
"DynamicThresholdFilter": {
  "key": "loginId", (3)
  "defaultThreshold": "ERROR",
  "KeyValuePair": [
    { (1)
      "key": "alice",
      "value": "DEBUG"
    },
    { (2)
      "key": "bob",
      "value": "INFO"
    }
  ]
}
Snippet from an example log4j2.yaml
DynamicThresholdFilter:
  key: "loginId"
  defaultThreshold: "ERROR" (3)
  KeyValuePair:
    - key: "alice" (1)
      value: "DEBUG"
    - key: "bob" (2)
      value: "INFO"
Snippet from an example log4j2.properties
filter.0.type = DynamicThresholdFilter
filter.0.key = loginId
(3)
filter.0.defaultThreshold = ERROR
(1)
filter.0.kv0.type = KeyValuePair
filter.0.kv0.key = alice
filter.0.kv0.value = DEBUG
(2)
filter.0.kv1.type = KeyValuePair
filter.0.kv1.key = bob
filter.0.kv1.value = INFO
1 If the loginId is alice a threshold level of DEBUG will be used.
2 If the loginId is bob a threshold level of INFO will be used.
3 For all the other values of loginId a threshold level of ERROR will be used.

You can use Log4j Core’s automatic reconfiguration feature to modify the KeyValuePairs without restarting your application.

Marker filters

The following filters use the log event marker to filter log events.

NoMarkerFilter

The NoMarkerFilter matches log events that do not have any markers.

This filter does not have any additional configuration attribute, except the common configuration attributes.

MarkerFilter

The MarkerFilter matches log events marked with a specific marker or any of its descendants.

Besides the common configuration attributes, the MarkerFilter supports the following parameter:

Table 9. MarkerFilter—configuration attributes
Attribute Type Default value Description

marker

Marker

The filter only matches log events of marker with the given marker or one of its descendants.

Required

Message filters

Message filters allow filtering log events based on the Message contained in the log event.

Log messages are often used interchangeably with log events. While this simplification holds for several cases, it is not technically correct. A log event, capturing the logging context (level, logger name, instant, etc.) along with the log message, is generated by the logging implementation (e.g., Log4j Core) when a user issues a log using a logger, e.g., LOGGER.info("Hello, world!"). Hence, log events are compound objects containing log messages.

Click for an introduction to log event fields

Log events contain fields that can be classified into three categories:

  1. Some fields are provided explicitly, in a Logger method call. The most important are the log level and the log message, which is a description of what happened, and it is addressed to humans.

  2. Some fields are contextual (e.g., Thread Context) and are either provided explicitly by developers of other parts of the application, or is injected by Java instrumentation.

  3. The last category of fields is those that are computed automatically by the logging implementation employed.

For clarity’s sake let us look at a log event formatted as JSON:

{
  (1)
  "log.level": "INFO",
  "message": "Unable to insert data into my_table.",
  "error.type": "java.lang.RuntimeException",
  "error.message": null,
  "error.stack_trace": [
    {
      "class": "com.example.Main",
      "method": "doQuery",
      "file.name": "Main.java",
      "file.line": 36
    },
    {
      "class": "com.example.Main",
      "method": "main",
      "file.name": "Main.java",
      "file.line": 25
    }
  ],
  "marker": "SQL",
  "log.logger": "com.example.Main",
  (2)
  "tags": [
    "SQL query"
  ],
  "labels": {
    "span_id": "3df85580-f001-4fb2-9e6e-3066ed6ddbb1",
    "trace_id": "1b1f8fc9-1a0c-47b0-a06f-af3c1dd1edf9"
  },
  (3)
  "@timestamp": "2024-05-23T09:32:24.163Z",
  "log.origin.class": "com.example.Main",
  "log.origin.method": "doQuery",
  "log.origin.file.name": "Main.java",
  "log.origin.file.line": 36,
  "process.thread.id": 1,
  "process.thread.name": "main",
  "process.thread.priority": 5
}
1 Explicitly supplied fields:
log.level

level of the event, either explicitly provided as an argument to the logger call, or implied by the name of the logger method

message

The log message that describes what happened

error.*

An optional Throwable explicitly passed as an argument to the logger call

marker

An optional marker explicitly passed as an argument to the logger call

log.logger

The logger name provided explicitly to LogManager.getLogger() or inferred by Log4j API

2 Contextual fields:
tags

The Thread Context stack

labels

The Thread Context map

3 Logging backend specific fields. In case you are using Log4j Core, the following fields can be automatically generated:
@timestamp

The instant of the logger call

log.origin.*

The location of the logger call in the source code

process.thread.*

The name of the Java thread, where the logger is called

RegexFilter

The RegexFilter matches a regular expression against messages. Besides the common configuration attributes, the RegexFilter supports the following parameters:

Table 10. RegexFilter configuration attributes
Attribute Type Default value Description

regex

Pattern

The regular expression used to match log messages.

Required

useRawMsg

boolean

false

If true, for ParameterizedMessage, StringFormattedMessage, and MessageFormatMessage, the message format pattern; for StructuredDataMessage, the message field will be used as the match target.

  • This filter only matches if the whole log message matches the regular expression.

  • Setting useRawMsg to false decreases performance, since it forces the formatting of all log messages, including the disabled ones.

StringMatchFilter

The StringMatchFilter matches a log event, if its message contains the given string.

Besides the common configuration attributes, the StringMatchFilter supports the following parameters:

Table 11. StringMatchFilter—configuration attributes
Attribute Type Default value Description

text

String

The text to look for.

Required

This filter decreases performance, since it forces the formatting of all log messages, including the disabled ones.

Map filters

The following filters match log events based on the content of one of these map structures:

Configuration map

These filters are configured with a configuration map of type Map<String, String[]>, which, depending on the filter, is encoded as either JSON:

{
  "configs": {
    "clientId": [
      "1234"
    ],
    "userId": [
      "alice",
      "bob"
    ]
  }
}

or as a sequence of KeyValuePair plugins:

<KeyValuePair key="clientId" value="1234"/>
<KeyValuePair key="userId" value="alice"/>
<KeyValuePair key="userId" value="bob"/>

The configuration map associates to each key a list of allowed values for that key. In the example above the allowed values for the loginId key are either alice or bob. The only allowed value for the clientId key is 1234.

The map filters can work in two matching modes:

AND

A map structure matches if the value associated with each key that appears in the configuration map is one of the allowed values.

OR

A map structure matches if the value associated with at least one key that appears in the configuration map is one of the allowed values.

MapFilter

The MapFilter allows filtering based on the contents of all structured Messages.

This filter encodes the Configuration map introduced above as a list of KeyValuePair elements.

Besides the common configuration attributes, the MapFilter supports the following parameters:

Table 12. MapFilter — configuration attributes
Attribute Type Default value Description

operator

enumeration

AND

Determines the matching mode of the filter. Can be:

Table 13. MapFilter — nested elements
Type Multiplicity Description

KeyValuePair

One or more

Adds a value as allowed value for a key. See Configuration map for more details.

For example, if you want to filter all MapMessages that have an eventType key with value authentication and an eventId key with value either login or logout, you can use the following configuration:

  • XML

  • JSON

  • YAML

  • Properties

Snippet from an example log4j2.xml
<MapFilter operator="AND">
  <KeyValuePair key="eventType" value="authentication"/>
  <KeyValuePair key="eventId" value="login"/>
  <KeyValuePair key="eventId" value="logout"/>
</MapFilter>
Snippet from an example log4j2.json
"MapFilter": {
  "operator": "AND",
  "KeyValuePair": [
    {
      "key": "eventType",
      "value": "authentication"
    },
    {
      "key": "eventId",
      "value": "login"
    },
    {
      "key": "eventId",
      "value": "logout"
    }
  ]
}
Snippet from an example log4j2.yaml
MapFilter:
  operator: "AND"
  KeyValuePair:
    - key: "eventType"
      value: "authentication"
    - key: "eventId"
      value: "login"
    - key: "eventId"
      value: "logout"
Snippet from an example log4j2.properties
filter.0.type = MapFilter
filter.0.operator = AND

filter.0.kv0.type = KeyValuePair
filter.0.kv0.key = eventType
filter.0.kv0.value = authentication

filter.0.kv1.type = KeyValuePair
filter.0.kv1.key = eventId
filter.0.kv1.value = login

filter.0.kv2.type = KeyValuePair
filter.0.kv2.key = eventId
filter.0.kv2.value = logout

You can use Log4j Core’s automatic reconfiguration feature to modify the KeyValuePairs without restarting your application.

StructuredDataFilter

The StructuredDataFilter is a variant of MapFilter that only matches StructureDataMessages.

In addition to matching the map structure contained in a StructuredDataMessage (which corresponds to RFC 5424 SD-PARAM elements) it provides the following virtual keys:

Table 14. StructuredDataFilter — virtual keys
Key RFC5424 field Description

id

SD-ID

The id field of the StructuredDataMessage.

id.name

The name field of the StructuredDataId element.

type

MSGID

The type field of a StructuredDataMessage.

message

MSG

The result of a Message.getFormat() method call.

The StructuredDataFilter encodes the Configuration map introduced above as a list of KeyValuePair and supports the following parameters, besides the common configuration attributes:

Table 15. StructuredDataFilter—configuration attributes
Attribute Type Default value Description

operator

enumeration

AND

Determines the matching mode of the filter. Can be:

Table 16. StructuredDataFilter — nested elements
Type Multiplicity Description

KeyValuePair

One or more

Adds a value as allowed value for a key. See Configuration map for more details.

If you want to match all log messages with an SD-ID equal to authentication and the value of the userId SD-PARAM equal to either alice or bob, you can use the following configuration:

  • XML

  • JSON

  • YAML

  • Properties

Snippet from an example log4j2.xml
<StructuredDataFilter operator="AND">
  <KeyValuePair key="id" value="authentication"/>
  <KeyValuePair key="userId" value="alice"/>
  <KeyValuePair key="userId" value="bob"/>
</StructuredDataFilter>
Snippet from an example log4j2.json
"StructuredDataFilter": {
  "operator": "AND",
  "KeyValuePair": [
    {
      "key": "id",
      "value": "authentication"
    },
    {
      "key": "userId",
      "value": "alice"
    },
    {
      "key": "userId",
      "value": "bob"
    }
  ]
}
Snippet from an example log4j2.yaml
StructuredDataFilter:
  operator: "AND"
  KeyValuePair:
    - key: "id"
      value: "authentication"
    - key: "userId"
      value: "alice"
    - key: "userId"
      value: "bob"
Snippet from an example log4j2.properties
filter.0.type = StructuredDataFilter
filter.0.operator = AND

filter.0.kv0.type = KeyValuePair
filter.0.kv0.key = id
filter.0.kv0.value = authentication

filter.0.kv1.type = KeyValuePair
filter.0.kv1.key = userId
filter.0.kv1.value = alice

filter.0.kv2.type = KeyValuePair
filter.0.kv2.key = userId
filter.0.kv2.value = bob

You can use Log4j Core’s automatic reconfiguration feature to modify the KeyValuePairs without restarting your application.

ContextMapFilter

The ContextMapFilter works in the same way as the MapFilter above, except it checks the context map data of the log event instead of the log message.

This filter also encodes the Configuration map introduced above as a list of KeyValuePair elements.

Besides the common configuration attributes, the ContextMapFilter supports the following parameters:

Table 17. ContextMapFilter — configuration attributes
Attribute Type Default value Description

operator

enumeration

AND

Determines the matching mode of the filter. Can be:

Table 18. ContextMapFilter — nested elements
Type Multiplicity Description

KeyValuePair

One or more

Adds a value as allowed value for a key. See Configuration map for more details.

For example, if the clientId and userId keys in the context data map identify your client and his end users, you can filter the log events generated by users alice and bob of client 1234 using this configuration:

  • XML

  • JSON

  • YAML

  • Properties

Snippet from an example log4j2.xml
<ContextMapFilter operator="AND">
  <KeyValuePair key="clientId" value="1234"/>
  <KeyValuePair key="userId" value="alice"/>
  <KeyValuePair key="userId" value="bob"/>
</ContextMapFilter>
Snippet from an example log4j2.json
"ContextMapFilter": {
  "operator": "AND",
  "KeyValuePair": [
    {
      "key": "clientId",
      "value": "1234"
    },
    {
      "key": "userId",
      "value": "alice"
    },
    {
      "key": "userId",
      "value": "bob"
    }
  ]
}
Snippet from an example log4j2.yaml
ContextMapFilter:
  operator: "AND"
  KeyValuePair:
    - key: "clientId"
      value: "1234"
    - key: "userId"
      value: "alice"
    - key: "userId"
      value: "bob"
Snippet from an example log4j2.properties
filter.0.type = ContextMapFilter
filter.0.operator = AND

filter.0.kv0.type = KeyValuePair
filter.0.kv0.key = clientId
filter.0.kv0.value = 1234

filter.0.kv1.type = KeyValuePair
filter.0.kv1.key = userId
filter.0.kv1.value = alice

filter.0.kv2.type = KeyValuePair
filter.0.kv2.key = userId
filter.0.kv2.value = bob

You can use Log4j Core’s automatic reconfiguration feature to modify the KeyValuePairs without restarting your application.

MutableContextMapFilter

The MutableContextMapFilter is an alternative version of ContextMapFilter that also uses the context data map to filter messages, but externalizes the Configuration map, so it can be kept in a separate location.

This filter encodes the Configuration map as JSON. The configuration map must be stored in an external location and will be regularly polled for changes.

Besides the common configuration attributes, the MutableContextMapFilter supports the following parameters:

Table 19. MutableContextMapFilter — configuration attributes
Attribute Type Default value Description

configLocation

Path or URI

The location of the JSON Configuration map.

Required

pollInterval

long

0

Determines the polling interval used by Log4j to check for changes to the configuration map.

If set to 0, polling is disabled.

Unlike other map filters that have a configurable matching mode, this filter always uses the OR matching mode.

To use this filter, you need to:

  1. Create a JSON configuration map and place it at a known location (e.g. https://server.example/configs.json):

    {
      "configs": {
        "clientId": [
          "1234" (1)
        ],
        "userId": [
          "root" (2)
        ]
      }
    }
    1 The filter will match all events for client 1234 regardless of the userId.
    2 The filter will match all events for the root account regardless of the clientId.
  2. Reference the configuration map location in your configuration file:

    • XML

    • JSON

    • YAML

    • Properties

    Snippet from an example log4j2.xml
    <MutableContextMapFilter
        configLocation="https://server.example/configs.json"
        pollInterval="10"/>
    Snippet from an example log4j2.json
    "MutableContextMapFilter": {
      "configLocation": "https://server.example/configs.json",
      "pollInterval": 10
    }
    Snippet from an example log4j2.yaml
    MutableContextMapFilter:
      configLocation: "https://server.example/configs.json"
      pollInterval: 10
    Snippet from an example log4j2.properties
    filter.0.type = MutableContextMapFilter
    filter.0.configLocation = https://server.example/configs.json
    filter.0.pollInterval = 10

Other filters

DenyFilter

The DenyFilter always returns DENY. It does not support any configuration attribute, even the common configuration attributes.

ScriptFilter

The ScriptFilter executes a script that must return true if the event matches and false otherwise.

Besides the common configuration attributes, it accepts a single nested element:

Table 20. ScriptFilter — nested elements
Type Multiplicity Description

Script, ScriptFile or ScriptRef

one

A reference to the script to execute.

See Scripts for more details about scripting.

Additional runtime dependencies are required to use ScripFilter
  • Maven

  • Gradle

We assume you use log4j-bom for dependency management.

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-script</artifactId>
  <scope>runtime</scope>
</dependency>

We assume you use log4j-bom for dependency management.

runtimeOnly 'org.apache.logging.log4j:log4j-script'

The bindings available to the script depend on whether the ScriptFilter is used as a global filter in the Logger stage or in the remaining stages. For global filters, the following bindings are available:

Table 21. Script Bindings — global filter
Binding name Type Description

logger

Logger

The logger used in the log statement.

level

Level

The level used in the log statement.

marker

Marker

The marker used in the log statement.

message

Message

The message used in the log event if the user directly supplied one. Otherwise:

  • If the logging statement contained an Object argument, it is wrapped in a ObjectMessage.

  • If the logging statement contained a format String, it is wrapped in a SimpleMessage.

parameters

Object[]

The parameters passed to the logging call. Some logging calls include the parameters as part of message.

throwable

Throwable

The Throwable passed to the logging call, if any. Some logging calls include the Throwable as part of message.

substitutor

StrSubstitutor

The StrSubstitutor used to replace lookup variables.

For the remaining filters, only these bindings are available:

Table 22. Script Bindings — internal filter
Binding name Type Description

logEvent

LogEvent

The log event being processed.

substitutor

StrSubstitutor

The StrSubstitutor used to replace lookup variables.

As an example, if you wish to match only log events that contain a certain exception, you can use a simple Groovy script:

scripts/local.groovy
return logEvent.throwable instanceof DataAccessException;

You can then integrate the script in a Log4j configuration:

  • XML

  • JSON

  • YAML

  • Properties

Snippet from an example log4j2.xml
<Root level="ALL">
  <ScriptFilter>
    <ScriptFile language="groovy" path="scripts/local.groovy"/>
  </ScriptFilter>
  <AppenderRef ref="CONSOLE"/>
</Root>
Snippet from an example log4j2.json
"Root": {
  "level": "ALL",
  "ScriptFilter": {
    "ScriptFile": {
      "language": "groovy",
      "path": "scripts/local.groovy"
    }
  },
  "AppenderRef": {
    "ref": "CONSOLE"
  }
}
Snippet from an example log4j2.yaml
Root:
  level: "ALL"
  ScriptFilter:
    ScriptFile:
      language: "groovy"
      path: "scripts/local.groovy"
  AppenderRef:
    ref: "CONSOLE"
Snippet from an example log4j2.properties
rootLogger.level = ALL

rootLogger.filter.0.type = ScriptFilter
rootLogger.filter.0.script.type = ScriptFile
rootLogger.filter.0.script.language = groovy
rootLogger.filter.0.script.path = scripts/local.groovy

rootLogger.appenderRef.0.ref = CONSOLE

Writing an equivalent global script is a little bit more complex, since you need to take into account all the places where a throwable can be passed as a parameter. The script becomes:

scripts/global.groovy
Throwable lastParam = parameters?.last() instanceof Throwable ? parameters.last() : null
Throwable actualThrowable = throwable ?: message?.throwable ?: lastParam
return actualThrowable instanceof DataAccessException

You can use it as a global filter:

  • XML

  • JSON

  • YAML

  • Properties

Snippet from an example log4j2.xml
<ScriptFilter>
  <ScriptFile language="groovy" path="scripts/global.groovy"/>
</ScriptFilter>
Snippet from an example log4j2.json
"ScriptFilter": {
  "ScriptFile": {
    "language": "groovy",
    "path": "scripts/global.groovy"
  }
}
Snippet from an example log4j2.yaml
ScriptFilter:
  ScriptFile:
    language: "groovy"
    path: "scripts/global.groovy"
Snippet from an example log4j2.properties
filter.0.type = ScriptFilter
filter.0.script.type = ScriptFile
filter.0.script.language = groovy
filter.0.script.path = scripts/global.groovy

Extending

Filters are plugins implementing the Filter interface. This section will guide you on how to create custom ones.

While the predefined filter collection should address most common use cases, you might find yourself needing to implement a custom one. If this is the case, we really appreciate it if you can share your use case in a user support channel.

Plugin preliminaries

Log4j plugin system is the de facto extension mechanism embraced by various Log4j components. Plugins make it possible for extensible components to receive feature implementations without any explicit links in between. It is analogous to a dependency injection framework, but curated for Log4j-specific needs.

In a nutshell, you annotate your classes with @Plugin and their (static) factory methods with @PluginFactory. Last, you inform the Log4j plugin system to discover these custom classes. This is done using running the PluginProcessor annotation processor while building your project. Refer to Plugins for details.

Extending filters

Filters are plugins implementing the Filter interface. We recommend users to extend from AbstractFilter, which provides implementation convenience. While annotating your filter with @Plugin, you need to make sure that

  • It has a unique name attribute across all available Filter plugins

  • The category attribute is set to Node.CATEGORY

You can check out the following files for examples: