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?
Répondre
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);
}
}
Réussi à répondre à ma propre question :-)
Lors de l'arrêt du LogManager:
LogManager.shutdown();
tous les journaux tamponnés se rincée.
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. –
cela ressemble à la meilleure réponse ... mais comment accéder à cet objet "LogManager"? (log4php novice) –
Peut-être que vous pourriez passer outre WriterAppender#shouldFlush(LoggingEvent)
, il retournerait true
pour une catégorie d'enregistrement spécial, comme log4j.flush.now
, puis vous appelez:
LoggerFactory.getLogger("log4j.flush.now").info("Flush")
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.
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();
}
}
}
}
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. –
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. –
Est-ce que Log4J ne purge pas l'appender automatiquement pendant l'arrêt normal? Je m'attendrais au moins à le faire. –
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 ... –
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