2010-06-17 13 views
16

Log4j'de, bir FileAppender'ı BufferedIO = true ve BufferSize = xxx özellikleriyle kullanırken (yani, arabelleğe alma etkinleştirilmişse), normal kapatma yordamı sırasında günlüğü temizleyebilmeyi istiyorum. Bunu nasıl yapacağınız hakkında bir fikrin var mı?Tamponlu bir log4j FileAppender'ı nasıl temizlersiniz?

+0

Log4J, normal kapanma sırasında ekleyiciyi otomatik olarak temizlemiyor mu? En azından bunu yapmasını beklerdim. –

+1

Kodu anladığım kadarıyla - BufferedIO'ya karar verirken kızarma yok. Performans kazanıyorsunuz ama bir fiyat ödüyorsunuz: son kayıt girişlerini kaybedersiniz ... –

+0

Kendi ekleyicimi (DB'ye yazdım ama gerçekten önemli değil) yazdığımda, her birkaç saniyede bir otomatik olarak fışkırırken çıktıda tamponlama yaptım. – ripper234

cevap

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

İşi hallediyor gibi görünüyor. Teşekkürler! – Amos

+0

Bu, tüm kaydedicileri temizlemez. Hepsini temizlemek için, her bir kayıt cihazında getParent() öğesini yinelemeli olarak çağırmanız ve bu kaydedicileri de temizlemeniz gerekir. – h22

0

Dene:

LogManager.shutdown(); 

tüm tamponlu günlükleri kızardı olsun:

LogFactory.releaseAll(); 
+1

Bunun çağrılmasının maalesef bir etkisi yoktu. – Amos

35

:-)

LogManager kapatılıyor

kendi soruyu cevaplamak için Yönetilen.

+6

Lütfen bunu cevap olarak seçin - açıkça en güzel seçenek. Kendini hak ettiysen, yeşil bir kene çıkarmaktan çekinme. –

+0

bu en iyi cevap gibi görünüyor ... ama bu "LogManager" nesnesine nasıl erişiyorsunuz? (log4php acemi) –

0

Bir appender yazdım Bunu düzeltir, bkz. GitHub veya name.wramner.log4j: Maven'deki FlushAppender'ı kullanın. Yüksek önem derecesine sahip olayları temizlemek için yapılandırılabilir ve belirli bir mesaj aldığında, örneğin "Kapanıyor" gibi eklerin arabelleğe alınmasını engelleyebilir. Konfigürasyon örnekleri için ünite testlerini kontrol edin. Elbette özgürdü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

Bu kod soruyu yanıtlarken, sorunun nasıl ve/veya neden çözüldüğüne ilişkin ek bağlam sağlayarak yanıtın uzun vadeli değerini artıracaktır. –

+0

Bu kod yalnızca tüm atılabilir ekleri temizlemeyi deniyor (tüm "fışkırtma" yönteminin bildirildiği "AbstractOutputStreamAppender" ifadesini genişleten tüm ekleyiciler). Projemde Log4J2 v2.8.2 ile bunu kullanıyorum. –