Filters
Filters are log4net 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
-
log4net behaves as if the filter was not present. It is evaluated by the next filter in the filter chain.
Any filter along the way can accept the event and stop processing, deny the event and stop processing, or allow the event on to the next filter. If the event gets to the end of the filter chain without being denied it is implicitly accepted and will be logged.
This filter will deny events that have a level that is lower than INFO or higher than FATAL. All events between INFO and FATAL will be logged.
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
If we want to only allow messages through that have a specific substring (e.g. 'database') then we need to specify the following filters:
<filter type="log4net.Filter.StringMatchFilter">
<stringToMatch value="database" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
The first filter will look for the substring 'database' in the message text of the event. If the text is found the filter will accept the message and filter processing will stop, the message will be logged. If the substring is not found the event will be passed to the next filter to process. If there is no next filter the event would be implicitly accepted and would be logged. But because we don’t want the non matching events to be logged we need to use a log4net.Filter.DenyAllFilter that will just deny all events that reach it. This filter is only useful at the end of the filter chain.
If we want to allow events that have either 'database' or 'ldap' in the message text we can use the following filters:
<filter type="log4net.Filter.StringMatchFilter">
<stringToMatch value="database"/>
</filter>
<filter type="log4net.Filter.StringMatchFilter">
<stringToMatch value="ldap"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
List of Filters
The following filters are defined in the log4net package:
| Type | Description |
|---|---|
log4net.Filter.DenyAllFilter |
Drops all logging events unconditionally. |
log4net.Filter.LevelMatchFilter |
Allows only events with an exact level match. |
log4net.Filter.LevelRangeFilter |
Allows events within a specified range of levels. |
log4net.Filter.LoggerMatchFilter |
Matches events from loggers with names starting with a given string. |
log4net.Filter.PropertyFilter |
Matches events based on a specific property’s value. |
log4net.Filter.StringMatchFilter |
Matches events containing a specific substring in the message. |
Matching with a regular expression
StringMatchFilter, PropertyFilter, MdcFilter and NdcFilter accept a regexToMatch instead
of a stringToMatch.
A regular expression that backtracks can take a very long time on some inputs, and the match runs
while the appender lock is held.
The deadline is therefore what bounds how long one event can stall every thread logging through the
appender, and it defaults to 50 milliseconds, configurable with matchTimeoutMillis.
A legitimate match over an event takes a fraction of that; raise it only if a pattern genuinely
needs longer.
Prefer a pattern that cannot backtrack; the deadline is a safety net, not a substitute.
<filter type="log4net.Filter.StringMatchFilter">
<regexToMatch value="user=[a-z0-9._-]+@example\.com" />
<matchTimeoutMillis value="200" />
</filter>
Setting matchTimeoutMillis to 0 lets a match run for as long as it takes and is not recommended.
Deciding an abandoned match
A match that reaches the deadline is abandoned and the filter reports it once.
The event is then decided by timeoutDecision, which defaults to Neutral, leaving the remaining
filters to decide as before.
An abandoned match is not the same as a non-match: the content being matched is what decides whether
the deadline is reached, so treating it as "did not match" lets content choose its own outcome.
In the allowlist arrangement above, where a matching filter accepts and a DenyAllFilter ends the
chain, that means an event can suppress its own record.
Set timeoutDecision to Accept there so the chain fails towards logging:
<filter type="log4net.Filter.StringMatchFilter">
<regexToMatch value="user=[a-z0-9._-]+@example\.com" />
<timeoutDecision value="Accept" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
In a chain that denies on match, Deny is the equivalent choice.
No one direction is right for every chain, which is why it is configured rather than chosen for you.