2010-06-17 18 views
16

En log4j, cuando se utiliza un FileAppender con BufferedIO = true y BufferSize = xxx propiedades (es decir, el almacenamiento en búfer está habilitado), quiero poder vaciar el registro durante el procedimiento de apagado normal. ¿Alguna idea sobre cómo hacer esto?¿Cómo se vacía un archivo log4j FileAppender?

+0

¿No se descarga Log4J el appender automáticamente durante el apagado normal? Al menos, espero que lo haga. –

+1

Como yo entiendo el código, no se sonroja cuando se decide por BufferedIO. Usted gana rendimiento pero paga un precio: perderá las últimas entradas de registro ... –

+0

Cuando escribí mi propio appender (a DB, pero en realidad no importa), hice la salida de buffer mientras se enjuagaba automáticamente cada pocos segundos. – ripper234

Respuesta

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

Parece que hace el trabajo. ¡Gracias! – Amos

+0

Esto no vacía todos los registradores. Para purgar todo, debe llamar a getParent() en cada registrador de manera iterativa y purgar estos registradores también. – h22

0

Probar:

LogFactory.releaseAll(); 
+1

Llamar a esto no tuvo ningún efecto, desafortunadamente. – Amos

35

Managed para responder a mi propia pregunta :-)

Al apagar el LogManager:

LogManager.shutdown(); 

registros almacenados temporalmente todo consiguen enrojecida.

+6

Seleccione esto como la respuesta; es claramente la mejor opción. No te sientas mal por quitarle una garrapata verde a alguien si te la has ganado tú mismo. –

+0

parece la mejor respuesta ... pero, ¿cómo accedes a este objeto "LogManager"? (log4php novato) –

0

He escrito un appender que corrige esto, vea GitHub o use name.wramner.log4j: FlushAppender en Maven. Se puede configurar para nivelar los eventos con una gran severidad y puede hacer que los appenders no sean almacenados cuando recibe un mensaje específico, por ejemplo "Shutting down". Verifique las pruebas unitarias para ver ejemplos de configuración. Es gratis, por supuesto.

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

Si bien este código puede responder a la pregunta, proporcionar un contexto adicional sobre cómo y/o por qué soluciona el problema mejoraría el valor a largo plazo de la respuesta. –

+0

Este código solo intenta vaciar todos los apéndices de enjuague (todos los apéndices que extienden AbstractOutputStreamAppender, donde se declara el método "flush"). Usando esto con Log4J2 v2.8.2 en mi proyecto. –

Cuestiones relacionadas