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?
risposta
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);
}
}
Siamo riusciti a rispondere alla mia domanda :-)
Quando spegnere il LogManager:
LogManager.shutdown();
log tutte buffered ottenere arrossato.
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. –
sembra la migliore risposta ... ma come si accede a questo oggetto "LogManager"? (log4php novice) –
Forse si potrebbe ignorare WriterAppender#shouldFlush(LoggingEvent)
, quindi sarebbe tornare true
per una speciale categoria di registrazione, come log4j.flush.now
, e quindi si chiama:
LoggerFactory.getLogger("log4j.flush.now").info("Flush")
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.
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();
}
}
}
}
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. –
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. –
Log4J non scarica automaticamente l'appender durante l'arresto normale? Almeno mi aspetto che lo faccia. –
Come ho capito il codice - nessun lavaggio quando si decide per BufferedIO. Guadagni prestazioni, ma paghi un prezzo: perderai le ultime voci del registro ... –
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