2010-06-17 12 views
16

In log4j, quando si utilizza un FileAppender con BufferedIO = true e BufferSize = proprietà xxx (ovvero il buffering è abilitato), voglio essere in grado di svuotare il log durante la normale procedura di spegnimento. Qualche idea su come fare questo?Come svuotare un file di registro log4j FileAppender?

+0

Log4J non scarica automaticamente l'appender durante l'arresto normale? Almeno mi aspetto che lo faccia. –

+1

Come ho capito il codice - nessun lavaggio quando si decide per BufferedIO. Guadagni prestazioni, ma paghi un prezzo: perderai le ultime voci del registro ... –

+0

Quando ho scritto il mio appender (in DB, ma non ha molta importanza), ho eseguito il buffering dell'output durante il flush automatico ogni pochi secondi. – ripper234

risposta

6
public static void flushAllLogs() 
{ 
    try 
    { 
     Set<FileAppender> flushedFileAppenders = new HashSet<FileAppender>(); 
     Enumeration currentLoggers = LogManager.getLoggerRepository().getCurrentLoggers(); 
     while(currentLoggers.hasMoreElements()) 
     { 
      Object nextLogger = currentLoggers.nextElement(); 
      if(nextLogger instanceof Logger) 
      { 
       Logger currentLogger = (Logger) nextLogger; 
       Enumeration allAppenders = currentLogger.getAllAppenders(); 
       while(allAppenders.hasMoreElements()) 
       { 
        Object nextElement = allAppenders.nextElement(); 
        if(nextElement instanceof FileAppender) 
        { 
         FileAppender fileAppender = (FileAppender) nextElement; 
         if(!flushedFileAppenders.contains(fileAppender) && !fileAppender.getImmediateFlush()) 
         { 
          flushedFileAppenders.add(fileAppender); 
          //log.info("Appender "+fileAppender.getName()+" is not doing immediateFlush "); 
          fileAppender.setImmediateFlush(true); 
          currentLogger.info("FLUSH"); 
          fileAppender.setImmediateFlush(false); 
         } 
         else 
         { 
          //log.info("fileAppender"+fileAppender.getName()+" is doing immediateFlush"); 
         } 
        } 
       } 
      } 
     } 
    } 
    catch(RuntimeException e) 
    { 
     log.error("Failed flushing logs",e); 
    } 
} 
+0

Sembra aver fatto il lavoro. Grazie! – Amos

+0

Questo non scarica tutti i logger. Per eseguire il flush di tutti, è necessario chiamare getParent() su ogni logger in modo iterativo e svuotare anche questi logger. – h22

0

Prova:

LogFactory.releaseAll(); 
+1

La chiamata non ha avuto alcun effetto, sfortunatamente. – Amos

35

Siamo riusciti a rispondere alla mia domanda :-)

Quando spegnere il LogManager:

LogManager.shutdown(); 

log tutte buffered ottenere arrossato.

+6

Si prega di selezionare questo come la risposta - è chiaramente l'opzione più bella. Non ti preoccupare di rimuovere un segno di spunta verde da qualcuno se lo hai guadagnato tu stesso. –

+0

sembra la migliore risposta ... ma come si accede a questo oggetto "LogManager"? (log4php novice) –

0

Ho scritto un appender che corregge questo, vedi GitHub o usa name.wramner.log4j: FlushAppender in Maven. Può essere configurato per eseguire il flushing degli eventi con severità elevata e può rendere gli appender non bufferizzati quando riceve un messaggio specifico, ad esempio "Arresto". Controllare i test dell'unità per gli esempi di configurazione. È gratuito, ovviamente.

3
public static void flushAll() { 
    final LoggerContext logCtx = ((LoggerContext) LogManager.getContext()); 
    for(final org.apache.logging.log4j.core.Logger logger : logCtx.getLoggers()) { 
     for(final Appender appender : logger.getAppenders().values()) { 
      if(appender instanceof AbstractOutputStreamAppender) { 
       ((AbstractOutputStreamAppender) appender).getManager().flush(); 
      } 
     } 
    } 
} 
+0

Sebbene questo codice possa rispondere alla domanda, fornire un contesto aggiuntivo riguardo a come e/o perché risolve il problema migliorerebbe il valore a lungo termine della risposta. –

+0

Questo codice cerca semplicemente di svuotare tutte le appendici flusibili (tutte le appendici che estendono AbstractOutputStreamAppender, dove viene dichiarato il metodo "flush"). Usando questo con Log4J2 v2.8.2 nel mio progetto. –

Problemi correlati