it-swarm.com.de

Log4j-Logger programmgesteuert konfigurieren

Ich versuche zum ersten Mal, SLF4J (mit log4j - Bindung) zu verwenden.

Ich möchte 3 verschiedene benannte Logger konfigurieren, die von einer LoggerFactory zurückgegeben werden können, die verschiedene Ebenen protokolliert und die Nachrichten an verschiedene Appender sendet:

  • Logger 1 "FileLogger" protokolliert DEBUG und hängt an DailyRollingFileAppender an
  • Logger 2 "TracingLogger" protokolliert TRACE + und hängt an ein JmsAppender an
  • Logger 3 "ErrorLogger" protokolliert ERROR + und hängt an ein anderes JmsAppender an

Außerdem möchte ich, dass sie programmgesteuert konfiguriert werden (in Java im Gegensatz zu XML oder einer log4j.properties - Datei).

Ich stelle mir vor, dass ich diese Loggers normalerweise irgendwo in einem Bootstrapping-Code wie einer init() -Methode definieren würde. Da ich jedoch slf4j-log4j Verwenden möchte, bin ich verwirrt, wo ich Logger definieren und sie dem Klassenpfad zur Verfügung stellen könnte.

Ich glaube nicht , dass dies eine Verletzung des zugrunde liegenden Zwecks von SLF4J ist (als Fassade), da mein Code, der die SLF4J-API verwendet, nie weiß, dass diese Logger existieren. Mein Code ruft einfach die SLF4J-API normal auf und leitet sie dann an die log4j-Logger weiter, die er im Klassenpfad findet.

Aber wie konfiguriere ich diese log4j-Logger im Klassenpfad ... in Java?!

181
IAmYourFaja

Sie können Appender programmgesteuert zu Log4j hinzufügen/entfernen:

  ConsoleAppender console = new ConsoleAppender(); //create appender
  //configure the appender
  String PATTERN = "%d [%p|%c|%C{1}] %m%n";
  console.setLayout(new PatternLayout(PATTERN)); 
  console.setThreshold(Level.FATAL);
  console.activateOptions();
  //add appender to any Logger (here is root)
  Logger.getRootLogger().addAppender(console);

  FileAppender fa = new FileAppender();
  fa.setName("FileLogger");
  fa.setFile("mylog.log");
  fa.setLayout(new PatternLayout("%d %-5p [%c{1}] %m%n"));
  fa.setThreshold(Level.DEBUG);
  fa.setAppend(true);
  fa.activateOptions();

  //add appender to any Logger (here is root)
  Logger.getRootLogger().addAppender(fa);
  //repeat with all other desired appenders

Ich würde vorschlagen, dass Sie es irgendwo in ein init () einfügen, wo Sie sicher sind, dass dies vor allem anderen ausgeführt wird. Sie können dann alle vorhandenen Appender auf dem Root-Logger mit entfernen

 Logger.getRootLogger().getLoggerRepository().resetConfiguration();

und fange mit dem Hinzufügen deiner eigenen an. Sie benötigen log4j im Klassenpfad, damit dies funktioniert.

Anmerkung:
Sie können eine beliebige Logger.getLogger(...) verwenden, um Anhänge hinzuzufügen. Ich habe gerade den Root-Logger verwendet, weil er am Ende aller Dinge steht und alles behandelt, was durch andere Appender in anderen Kategorien übertragen wird (sofern nicht anders konfiguriert, indem das Additivity-Flag gesetzt wird).

Wenn Sie wissen möchten, wie die Protokollierung funktioniert und wie entschieden wird, wo Protokolle geschrieben werden lesen Sie dieses Handbuch für weitere Informationen dazu.
Zusamenfassend:

  Logger fizz = LoggerFactory.getLogger("com.fizz")

sie erhalten einen Logger für die Kategorie "com.fizz".
Für das obige Beispiel bedeutet dies, dass alles, was damit protokolliert wurde, auf die Konsole und den Dateianhang des Root-Loggers verweist.
Wenn Sie einen Appender zu Logger.getLogger ("com.fizz"). AddAppender (newAppender) hinzufügen, wird die Protokollierung von fizz von allen Appendern aus dem Root-Logger und dem newAppender.
Sie erstellen keine Logger mit der Konfiguration, sondern stellen nur Handler für alle möglichen Kategorien in Ihrem System bereit.

270
oers

Es hört sich so an, als würden Sie versuchen, log4j von "beiden Seiten" (der Consumer-Seite und der Konfigurationsseite) aus zu verwenden.

Wenn Sie gegen die slf4j-API codieren möchten, aber vorab (und programmgesteuert) die Konfiguration der log4j-Protokollierer bestimmen möchten, die der Klassenpfad zurückgibt, müssen Sie unbedingt , um eine Art von Protokollierungsanpassung zu haben, die von faulen Konstruktionen Gebrauch macht.

public class YourLoggingWrapper {
    private static boolean loggingIsInitialized = false;

    public YourLoggingWrapper() {
        // ...blah
    }

    public static void debug(String debugMsg) {
        log(LogLevel.Debug, debugMsg);
    }

    // Same for all other log levels your want to handle.
    // You mentioned TRACE and ERROR.

    private static void log(LogLevel level, String logMsg) {
        if(!loggingIsInitialized)
            initLogging();

        org.slf4j.Logger slf4jLogger = org.slf4j.LoggerFactory.getLogger("DebugLogger");

        switch(level) {
        case: Debug:
            logger.debug(logMsg);
            break;
        default:
            // whatever
        }
    }

    // log4j logging is lazily constructed; it gets initialized
    // the first time the invoking app calls a log method
    private static void initLogging() {
        loggingIsInitialized = true;

        org.Apache.log4j.Logger debugLogger = org.Apache.log4j.LoggerFactory.getLogger("DebugLogger");

        // Now all the same configuration code that @oers suggested applies...
        // configure the logger, configure and add its appenders, etc.
        debugLogger.addAppender(someConfiguredFileAppender);
    }

Mit diesem Ansatz müssen Sie sich keine Gedanken darüber machen, wo/wann Ihre log4j-Logger konfiguriert werden. Wenn der Klassenpfad zum ersten Mal nach ihnen fragt, werden sie faul konstruiert, zurückgegeben und über slf4j verfügbar gemacht. Hoffe das hat geholfen!

45
IAmYourFaja

Wenn Sie einen Appender in den log4j-Eigenschaften definiert haben und ihn programmgesteuert aktualisieren möchten, legen Sie den Namen in den log4j-Eigenschaften fest und rufen Sie ihn nach Namen ab.

Hier ist ein Beispieleintrag für log4j.properties:

log4j.appender.stdout.Name=console
log4j.appender.stdout=org.Apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.Threshold=INFO

Gehen Sie folgendermaßen vor, um es zu aktualisieren:

((ConsoleAppender) Logger.getRootLogger().getAppender("console")).setThreshold(Level.DEBUG);
3
Kyle Shrader