24 votes

Comment vider un FileAppender log4j en mémoire tampon ?

Dans log4j, lorsque j'utilise un FileAppender avec les propriétés BufferedIO=true et BufferSize=xxx (c'est-à-dire que la mise en mémoire tampon est activée), je veux pouvoir vider le journal pendant la procédure d'arrêt normale. Avez-vous une idée de la façon de procéder ?

56voto

Lors de l'arrêt du LogManager :

LogManager.shutdown();

tous les journaux mis en mémoire tampon sont vidés.

7voto

Niv Points 36
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);
    }
}

5voto

Andrey Kurilov Points 51
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();
            }
        }
    }
}

1voto

Ondra Žižka Points 8262

Vous pourriez peut-être remplacer WriterAppender#shouldFlush( LoggingEvent ) donc il retournerait true pour une catégorie spéciale d'enregistrement, comme log4j.flush.now et ensuite vous appelez :

LoggerFactory.getLogger("log4j.flush.now").info("Flush")

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/WriterAppender.html#shouldFlush%28org.apache.log4j.spi.LoggingEvent%29

1voto

Je partage mon expérience en utilisant l'exemple de code d'"Andrey Kurilov", ou du moins un exemple similaire.

Ce que je voulais en fait, c'était mettre en place un journal asynchrone avec vidage manuel. (immediateFlush = false) pour s'assurer que le contenu d'un tampon inactif sera vidé avant que le bufferSize ne soit atteint.

Les premiers résultats en termes de performances étaient en fait comparables à ceux obtenus avec le système de gestion de la qualité de l'eau. AsyncAppender - donc je pense que c'est une bonne alternative.

Le site AsyncAppender utilise un fil d'exécution distinct (et une dépendance supplémentaire à l'égard de l'application disruptor jar), ce qui le rend plus performant, mais au prix d'un plus grand nombre de CPU et d'un plus grand nombre de vidages de disque (même si les vidages sont effectués par lots en cas de charge élevée).

Donc, si vous voulez économiser les opérations d'entrée/sortie sur le disque et la charge CPU, mais que vous voulez quand même vous assurer que vos tampons seront vidés de manière asynchrone à un moment donné, c'est la solution.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X