2010-06-17 4 views
16

Dans log4j, lorsque vous utilisez une propriété FileAppender avec BufferedIO = true et BufferSize = xxx (la mise en mémoire tampon est activée), je souhaite pouvoir vider le journal pendant la procédure d'arrêt normal. auriez vous des idées pour faire ça?Comment vider un fichier log4j tamponné FileAppender?

+0

Est-ce que Log4J ne purge pas l'appender automatiquement pendant l'arrêt normal? Je m'attendrais au moins à le faire. –

+1

Comme je comprends le code - pas de rinçage lorsque vous décidez pour BufferedIO. Vous gagnez des performances mais payez un prix: vous perdrez les dernières entrées du journal ... –

+0

Lorsque j'ai écrit mon propre appender (sur DB, mais cela n'a pas vraiment d'importance), j'ai tamponné la sortie tout en rinçant automatiquement toutes les quelques secondes. – ripper234

Répondre

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

Semble faire le travail. Merci! – Amos

+0

Cela ne vide pas tous les enregistreurs. Pour vider tout, vous devez appeler getParent() sur chaque enregistreur de manière itérative et vider ces enregistreurs. – h22

0

Essayez:

LogFactory.releaseAll(); 
+1

Appelant cela n'a eu aucun effet, malheureusement. – Amos

35

Réussi à répondre à ma propre question :-)

Lors de l'arrêt du LogManager:

LogManager.shutdown(); 

tous les journaux tamponnés se rincée.

+6

Veuillez sélectionner ceci comme réponse - c'est clairement la plus belle option. Ne vous sentez pas mal d'enlever une tique verte de quelqu'un si vous l'avez gagné vous-même. –

+0

cela ressemble à la meilleure réponse ... mais comment accéder à cet objet "LogManager"? (log4php novice) –

0

J'ai écrit un appender que corrige cela, voir GitHub ou utilisez name.wramner.log4j: FlushAppender dans Maven. Il peut être configuré pour vider des événements avec une sévérité élevée et il peut rendre les appenders non tamponnés lorsqu'il reçoit un message spécifique, par exemple "Arrêt". Vérifiez les tests unitaires pour les exemples de configuration. C'est gratuit, bien sûr.

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

Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire sur la façon et/ou la raison pour laquelle il résout le problème améliorerait la valeur à long terme de la réponse. –

+0

Ce code essaye juste de vider tous les appenders jetables (tous les appenders étendant AbstractOutputStreamAppender, où la méthode "flush" est déclarée). En utilisant cela avec Log4J2 v2.8.2 dans mon projet. –

Questions connexes