Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure log4j2's additivity to respect parent's level?

I think this code explains well enough what I'm trying to do

package us.benanderson;

public class MyClass {

  private static final Logger LOG = LogManager.getLogger(MyClass.class);
  ...
    // within a method
    LOG.debug("only output to appFile");
    LOG.error("output to both appFile and errorFile");

This is what I'd guess should be my config

<Loggers>
    <Logger name="us.benanderson" level="debug" additivity="true">
        <AppenderRef ref="appFile" />
    </Logger>

    <Root level="error">
        <AppenderRef ref="errorFile" />
    </Root>
</Loggers>

However, I'm finding that when additivity="true", debug messages are also output to errorFile. When additivity="false" nothing is output to errorFile. Is there any way to do what I'm trying to do?

like image 453
andersonbd1 Avatar asked Aug 27 '14 16:08

andersonbd1


People also ask

What does additivity mean in log4j?

Additivity is set to true by default, that is children inherit the appenders of their ancestors by default. If this variable is set to false then the appenders found in the ancestors of this logger are not used.

What is configuration status in log4j2?

Configuration: the root element of a log4j2 configuration file; the status attribute represents the level at which internal log4j events should be logged. Appenders: this element contains a list of appenders; in our example, an appender corresponding to the System console is defined.

What is Rootlogger in log4j2?

This concept is known as Logger Hierarchy. Logger Hierarchy is made up of set of LoggerConfig objects with a parent-child relationship. The topmost element in every Logger Hierarchy is the Root Logger. If Log4j2 doesn't find the configuration file, only Root Logger will be used for logging with logging level as ERROR.


2 Answers

I think the simplest way to achieve what you want is to put a level directly on the appender-ref. This eliminates the need to have a named logger in your config, simplifying the configuration a little.

Named loggers are still useful if you want to redirect log events for a certain package to a separate appender.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Appenders>
    <File name="appFile" fileName="logs/appFile.log" append="true">
      <PatternLayout pattern="%-5p %d{ABSOLUTE} [%t] %c - %m%n" />
    </File>
    <File name="errorFile" fileName="logs/errorFile.log" append="true">
      <PatternLayout pattern="%-5p %d{ABSOLUTE} [%t] %c - %m%n" />
    </File>
  </Appenders>
  <Loggers>
    <Root level="trace">
      <AppenderRef ref="appFile" level="debug" />
      <AppenderRef ref="errorFile" level="error" />
    </Root>
  </Loggers>
</Configuration>

Threshold filters and filter combinations can be especially useful if you want to do more unusual filtering. For example, if you want to send only INFO and WARN level events to a certain appender, excluding TRACE/DEBUG, and also excluding ERROR and FATAL level events(!), you could do this:

<Console name="only-info-warn">
    <PatternLayout pattern="%-5p %c %message %n" />
    <Filters>

        <!-- First deny error and fatal messages -->
        <ThresholdFilter level="error" onMatch="DENY"   onMismatch="NEUTRAL"/>
        <ThresholdFilter level="fatal" onMatch="DENY"   onMismatch="NEUTRAL"/>

        <!-- Then accept info, warn, error, fatal and deny debug/trace -->
        <ThresholdFilter level="warn"  onMatch="ACCEPT" onMismatch="NEUTRAL"/>
        <ThresholdFilter level="info"  onMatch="ACCEPT" onMismatch="DENY"/>
    </Filters>
</Console>
like image 169
Remko Popma Avatar answered Sep 21 '22 10:09

Remko Popma


Use a filter.

Here's a configuration that outputs everything to C:/Logs/Log.log, and additionally outputs debug only to C:/Logs/Debug.log:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
    <appender name="general-out" class="org.apache.log4j.FileAppender"> 
        <param name="File" value="C:/Logs/Log.log"/> 
        <layout class="org.apache.log4j.PatternLayout"> 
            <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1} : %m%n"/> 
        </layout> 
    </appender> 

    <appender name="debug-out" class="org.apache.log4j.FileAppender"> 
        <param name="File" value="C:/Logs/Debug.log"/>
        <layout class="org.apache.log4j.PatternLayout"> 
            <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1} : %m%n"/> 
        </layout> 
        <filter class="org.apache.log4j.varia.LevelMatchFilter">
            <param name="LevelToMatch" value="debug"/> 
            <param name="AcceptOnMatch" value="true"/> 
        </filter>     
        <filter class="org.apache.log4j.varia.DenyAllFilter"/> 
    </appender> 

    <root>
        <appender-ref ref="debug-out" />
        <appender-ref ref="general-out" /> 
    </root> 
</log4j:configuration>

The key part here is this:

<filter class="org.apache.log4j.varia.LevelMatchFilter">
    <param name="LevelToMatch" value="debug"/> 
    <param name="AcceptOnMatch" value="true"/> 
</filter>     
<filter class="org.apache.log4j.varia.DenyAllFilter"/> 

This allows things logged with debug, and then denies anything else.

Source: http://wiki.apache.org/logging-log4j/LogByLevel

like image 34
Pokechu22 Avatar answered Sep 25 '22 10:09

Pokechu22