2012-01-23 13 views
163

Si sta tentando di utilizzare SLF4J (con associazione log4j) per la prima volta.Configurazione dei logger Log4j a livello di programmazione

Vorrei configurare 3 diversi logger nome che possono essere restituiti da una LoggerFactory, che registrerà diversi livelli e spingere i messaggi a diversi appenders:

  • Logger 1 logs "FileLogger" Debug e aggiunge a DailyRollingFileAppender
  • Logger 2 "TracingLogger" registri di traccia + e aggiunge ad un Logger JmsAppender
  • 3 logs "ErrorLogger" ERRORE + e aggiunge a un diverso JmsAppender

Inoltre li voglio configurati in modo programmatico (in Java, al contrario di XML o in un file log4j.properties).

Immagino che, normalmente, definirei questi Logger da qualche parte in un codice di avvio, come un metodo init(). Tuttavia, poiché voglio utilizzare slf4j-log4j, sono confuso su dove potrei definire i logger e renderli disponibili al classpath.

Io non credo questa è una violazione dello scopo sottostante di SLF4J (come facciata), perché il mio codice che utilizza l'API SLF4J non saprà mai che questi logger esistono. Il mio codice effettua solo normali chiamate all'API SLF4J, che poi li inoltra ai logger log4j che trova sul classpath.

Ma come configurare i logger log4j sul classpath ... in Java ?!

+0

http://stackoverflow.com/questions/1666121/programmatically-creating-different -log-files-using-log4j – skaffman

+2

Per log4j 1.x usa la risposta accettata sotto per 2.x vedi https://logging.apache.org/log4j/2.x/manual/customconfig.html – earcam

risposta

242

È possibile aggiungere/rimuovere Appender programmazione per Log4j:

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 

io suggerirei lo metti in un init() da qualche parte, in cui si è sicuri, che questo sarà eseguito prima di ogni altra cosa. È quindi possibile rimuovere tutti i appenders esistenti sul logger principale con

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

e iniziare con l'aggiunta di vostro. È necessario log4j nel classpath per farlo funzionare correttamente.

Nota:
È possibile utilizzare qualsiasi Logger.getLogger(...) per aggiungere appendici. Ho appena preso il root logger perché è in fondo a tutte le cose e gestirà tutto ciò che viene passato attraverso altri appender in altre categorie (se non diversamente configurato impostando il flag di additività).

Se è necessario sapere come funziona la registrazione e come viene deciso dove vengono scritti i registri read this manual per ulteriori informazioni.
In breve:

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

vi darà un logger per il "com.fizz" categoria.
Per l'esempio precedente questo significa che tutto ciò che viene registrato con esso verrà riferito alla console e al file appender nel logger principale.
Se si aggiunge un appender a Logger.getLogger ("com.fizz").addAppender (newAppender) quindi la registrazione da fizz verrà gestita dagli allegati dal root logger e dallo newAppender.
Non si creano Logger con la configurazione, si forniscono solo gestori per tutte le possibili categorie nel proprio sistema.

+2

Grazie! Domanda veloce: ho notato che stai aggiungendo gli appendici al root logger. C'è una ragione per questo? – IAmYourFaja

+0

E, cosa più importante, dovrò specificare quale Logger recuperare da LoggerFactory di SLF4J. È possibile chiedere a SLF4J il root logger di log4j? – IAmYourFaja

+3

@AdamTannon Puoi prendere qualsiasi Logger.getLogger (...) che ti piace. Ho appena preso il root logger perché è in fondo a tutte le cose e gestirà tutto ciò che viene passato attraverso altri appenders in altre categorie (se non diversamente configurato). [Vedi la gerarchia del logger] (https://logging.apache.org/log4j/1.2/manual.html) – oers

39

Sembra che tu stia cercando di utilizzare log4j da "entrambe le estremità" (la fine del consumatore e la fine della configurazione).

Se si vuole codice contro l'API slf4j ma stabilire prima del tempo (e di programmazione) la configurazione dei log4j logger che il percorso di classe tornerà, si assolutamente avere avere una sorta di adattamento di registrazione, che si avvale di costruzione pigra.

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); 
    } 

Con questo approccio, non è necessario preoccuparsi di dove/quando i logger log4j vengono configurati. La prima volta che il classpath le richiede, vengono costruite pigramente, restituite e rese disponibili tramite slf4j. Spero che questo ha aiutato!

+1

Inchiodato! Grazie mille per un utile [email protected] - grazie per aver cercato di guidarmi nella giusta direzione - ho intenzione di darti il ​​verdetto per la tua dedizione, ma devo dare a zharvey la taglia perché era esattamente quello che stavo cercando. Grazie ancora a tutti! – IAmYourFaja

0

Nel caso in cui sia stato definito un appender nelle proprietà log4j e si desideri aggiornarlo a livello di codice, impostare il nome nelle proprietà log4j e scaricarlo per nome.

Ecco un esempio di voce 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 

di aggiornarlo, effettuare le seguenti operazioni:

((ConsoleAppender) Logger.getRootLogger().getAppender("console")).setThreshold(Level.DEBUG); 
Problemi correlati