Log4j Additivity flag

Ich müsste meinen Bekannten ein Paar Mal die Funktionalität vom „Additivity“ Flag im Log4J erklären.
Um mir das in der Zukunft zu ersparen, habe ich diese Kleine Anleitung zum Additivity Flag erstellt.

Es wird ein kleines Java Projekt benötigt, mit insgesamt 4 Klassen in 4 Paketen:
foo.additivity
foo.additivity.pckg1
foo.additivity.pckg1.sub
foo.additivity.pckg2

die 4 Java Klassen (eine Klasse pro Package)

package foo.additivity;
import org.apache.log4j.Logger;
import foo.additivity.pckg1.FirstClass;
import foo.additivity.pckg1.sub.FirstSubClass;
import foo.additivity.pckg2.SecondClass;

public class Main {
    private static Logger logger = Logger.getLogger(Main.class);    
    public static void main(final String[] args) {
        logger.debug("main");
        new FirstClass();
        new SecondClass();
        new FirstSubClass();
    }
}
package foo.additivity.pckg1;
import org.apache.log4j.Logger;

public class FirstClass {
    private static Logger logger = Logger.getLogger(FirstClass.class);    
    public FirstClass() { logger.debug("created!"); }
}
package foo.additivity.pckg1.sub;
import org.apache.log4j.Logger;

public class FirstSubClass {
    private static Logger logger = Logger.getLogger(FirstSubClass.class);    
    public FirstSubClass() { logger.debug("created!"); }
}
package foo.additivity.pckg2;
import org.apache.log4j.Logger;

public class SecondClass {
    private static Logger logger = Logger.getLogger(SecondClass.class);
    public SecondClass() { logger.debug("created!");}
}

Das Programm wird gestartet, in dem man die Main Klasse ausführt.
Im Java classpath muss noch eine log4j.xml Datei abgelegt werden, wir werden 3 Konfigurationen davon testen:

Erste Konfiguration:
Minimale Log4J Konfiguration, nur „default“ ROOT Logger, mit einem Console Appender „A1“

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
    <appender name="A1" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout"> 
            <param name="ConversionPattern" value="A1 %5p %c - %m%n"/> 
        </layout> 
    </appender>
    <root>
        <level value="DEBUG" />
        <appender-ref ref="A1" />
    </root>
</log4j:configuration>

Die Ausgabe wird wie folgt aussehen:

A1 DEBUG foo.additivity.Main - main
A1 DEBUG foo.additivity.pckg1.FirstClass - created!
A1 DEBUG foo.additivity.pckg2.SecondClass - created!
A1 DEBUG foo.additivity.pckg1.sub.FirstSubClass - created!

Zweite Konfiguration:
Zusätzlich zum „default“ Logger werden noch zwei weitere Loggers definiert:
1) foo.additivity Logger (default additivity = true)
2) foo.additivity.pckg1 Logger (explizit additivity = true und zusätzlich Appender „A2“)

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
    <appender name="A1" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout"> 
            <param name="ConversionPattern" value="A1 %5p %c - %m%n"/> 
        </layout> 
    </appender>
    <appender name="A2" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="A2 %5p %c - %m%n"/> 
        </layout>
    </appender>
    <logger name="foo.additivity">
        <level value="DEBUG" />
    </logger>
    <logger name="foo.additivity.pckg1" additivity="true">
        <level value="DEBUG" />
        <appender-ref ref="A2" />
    </logger>
    <root>
        <level value="DEBUG" />
        <appender-ref ref="A1" />
    </root>
</log4j:configuration>

Die Ausgabe von der Zweiten Konfiguration wird wie folgt aussehen:

A1 DEBUG foo.additivity.Main - main
A2 DEBUG foo.additivity.pckg1.FirstClass - created!
A1 DEBUG foo.additivity.pckg1.FirstClass - created!
A1 DEBUG foo.additivity.pckg2.SecondClass - created!
A2 DEBUG foo.additivity.pckg1.sub.FirstSubClass - created!
A1 DEBUG foo.additivity.pckg1.sub.FirstSubClass - created!

Man sieht, das alle Logging ausgaben ab dem Package foo.additivity.pckg1 in beide Appenders geschrieben wurden „A1“ und „A2“.

Dritte Konfiguration:
Beim „foo.additivity.pckg1“ Logger setzen wir den Additivity Flag auf „FALSE“

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
    <appender name="A1" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout"> 
            <param name="ConversionPattern" value="A1 %5p %c - %m%n"/> 
        </layout> 
    </appender>
    <appender name="A2" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="A2 %5p %c - %m%n"/> 
        </layout>
    </appender>
    <logger name="foo.additivity">
        <level value="DEBUG" />
    </logger>
    <logger name="foo.additivity.pckg1" additivity="false">
        <level value="DEBUG" />
        <appender-ref ref="A2" />
    </logger>
    <root>
        <level value="DEBUG" />
        <appender-ref ref="A1" />
    </root>
</log4j:configuration>

Output:

A1 DEBUG foo.additivity.Main - main
A2 DEBUG foo.additivity.pckg1.FirstClass - created!
A1 DEBUG foo.additivity.pckg2.SecondClass - created!
A2 DEBUG foo.additivity.pckg1.sub.FirstSubClass - created!

Wie man sieht, falls Additivity Flag auf „FALSE“ gesetzt wird, werden die Appenders von höher liegenden Loggern nicht mehr in diesem Package (und allen sub packages) „addiert“. In unserem Fall, wird im Package „foo.additivity.pckg1“ der „A1“ Appender (vom ROOT Logger) nicht mehr verwendet.

Der Additivity Flag kann nützlich sein um:
1) Ausgabe von einem Package (und allen Subpackages) in ein eigenen Appender (Log File?) umzuleiten. Und zwar nur in diesen Appender!
2) Logging in diesem Java Package komplett unterbinden (kein appender definiert).
Dabei wird eine ganze Reihe von „log4j:WARN Please initialize the log4j system properly.“ Warnungen generiert.
Für Test-Zwecke kann man mit „org.apache.log4j.helpers.LogLog.setQuietMode(true);“ diese Warnungen ausschalten (nur wenn Sie wissen was Sie machen!).

Weitere Informationen über Additivity Flag gibt es hier

Veröffentlicht in Allgemein, Java