2010-03-22 49 views
41

我想配置logback以執行以下操作。如何在啓動時在logback中滾動日誌文件

  • 記錄到文件中
  • 卷,當它達到50MB
  • 只保留7天值得記錄的
  • 啓動時總是生成一個新文件(做一個卷)
文件

除了最後一個項目,啓動卷以外,我已經完成了所有工作。有誰知道如何實現這一目標?這裏的配置...

<appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender"> 

    <layout class="ch.qos.logback.classic.PatternLayout"> 
     <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg \(%file:%line\)%n</Pattern> 
    </layout> 

    <File>server.log</File> 

    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
     <FileNamePattern>server.%d{yyyy-MM-dd}.log</FileNamePattern> 
     <!-- keep 7 days' worth of history --> 
     <MaxHistory>7</MaxHistory> 

     <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> 
     <MaxFileSize>50MB</MaxFileSize> 
     </TimeBasedFileNamingAndTriggeringPolicy> 

    </rollingPolicy> 
    </appender> 

回答

1

創建的ch.qos.logback.core.rolling.TimeBasedRollingPolicy自己的子類,並覆蓋其start

public class MyPolicy 
    extends ch.qos.logback.core.rolling.TimeBasedRollingPolicy 
{ 

    public void start () 
    { 
     super.start(); 
     rollover(); 
    } 
} 
+0

很遺憾,這不起作用,因爲觸發策略從getElapsedPeriodsFileName()返回null,然後拋出rollover()。 –

3

重寫在ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP的isTriggeringEvent()方法應該工作很好。首次調用isTriggeringEvent()方法時返回'true'。

+0

是否有一種在啓動時進行翻轉的方式 - 不需要觸發事件? 我只有一個文件擴展名的錯誤消息。我希望每次啓動後error-logfile都是空的 - 通常不會發生錯誤。 –

+0

我可以問,用maxFileSize擺弄什麼目的? – Mykro

+0

嘿Ceki,這是否需要線程安全? isTriggeringEvent是否被多個線程調用? –

2

Ceki的解決方案似乎不適用於我,但似乎至少是部分方式。

由於在啓動TimeBasedFileNamingAndTriggeringPolicyBase時無法看到滾動策略,因此爆炸。隨着一些hackery,我得到它做一些日誌記錄,並有一些我得到它觀察觸發器,但然後再次打破,因爲它無法解決其中一個文件名屬性...該軟件包是一個logback之一,所以我可以到達一些內部,複製SizeAndTimeBasedFNATP#isTriggeringEvent中的一些邏輯並調用computeCurrentPeriodsHighestCounterValue。我認爲沿着這些路線可能會發揮作用,但還沒有找到神奇的組合。我真的希望自己做的事很愚蠢,因爲否則我認爲這將意味着要麼開啓一些子類化的細節,要麼將其作爲另一個滾動/觸發策略進行logback。

logback.xml:嘗試triggeringPolicy,TimeBasedFileNamingAndTriggeringPolicy內部和外部rollingPolicy各種排序。

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
    <file>${LOG_DIR}/${LOG_FILE_BASE}.log</file> 
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
     <fileNamePattern>${LOG_DIR}/${LOG_FILE_BASE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> 
     <MaxHistory>7</MaxHistory> 

     <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.RollOnStartupPolicy" /> 
    </rollingPolicy> 

    <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 
     <level>INFO</level> 
    </filter> 

    <encoder> 
     <pattern>%msg%n</pattern> 
    </encoder> 
</appender> 

觸發政策:

​​

例外:

java.lang.NullPointerException 
at at ch.qos.logback.core.rolling.TimeBasedFileNamingAndTriggeringPolicyBase.start(TimeBasedFileNamingAndTriggeringPolicyBase.java:46) 
at at ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP.start(SizeAndTimeBasedFNATP.java:36) 
at at ch.qos.logback.core.joran... [snip joran config] 
7

它的工作對我來說,使用下面的類爲timeBasedFileNamingAndTriggeringPolicy:

import java.io.File; 
import java.util.concurrent.atomic.AtomicBoolean; 

import ch.qos.logback.core.joran.spi.NoAutoStart; 
import ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP; 

@NoAutoStart 
public class Trigger<E> extends SizeAndTimeBasedFNATP<E> 
{ 
    private final AtomicBoolean trigger = new AtomicBoolean(); 

    public boolean isTriggeringEvent(final File activeFile, final E event) { 
     if (trigger.compareAndSet(false, true) && activeFile.length() > 0) { 
      String maxFileSize = getMaxFileSize(); 
      setMaxFileSize("1"); 
      super.isTriggeringEvent(activeFile, event); 
      setMaxFileSize(maxFileSize); 
      return true; 
     } 
     return super.isTriggeringEvent(activeFile, event); 
    } 
} 
1

我得到了繼續工作(結合以前答案的想法)。注意我正在處理基於大小的文件,而不是基於時間,但我猜測同樣的解決方案是有效的。的其他建議

public class StartupSizeBasedTriggeringPolicy<E> extends ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy<E> { 

private final AtomicReference<Boolean> isFirstTime = new AtomicReference<Boolean>(true); 

@Override 
public boolean isTriggeringEvent(final File activeFile, final E event) { 

    //this method appears to have side-effects so always call 
    boolean result = super.isTriggeringEvent(activeFile, event); 

    return isFirstTime.compareAndSet(true, false) || result; 
} 

}

23

都不是適合我的情況。我不想使用基於尺寸和時間的解決方案,因爲它需要配置MaxFileSize,並且我們嚴格使用基於時間的策略。下面是我如何完成滾動在啓動時請用一個TimeBasedRollingPolicy:

@NoAutoStart 
public class StartupTimeBasedTriggeringPolicy<E> 
     extends DefaultTimeBasedFileNamingAndTriggeringPolicy<E> { 

    @Override 
    public void start() { 
     super.start(); 
     nextCheck = 0L; 
     isTriggeringEvent(null, null); 
     try { 
      tbrp.rollover(); 
     } catch (RolloverFailure e) { 
      //Do nothing 
     } 
    } 

} 

關鍵是要設置nextCheck時間0L,使isTriggeringEvent()會認爲它的時間來滾動日誌文件過來。它將因此執行計算文件名所需的代碼,以及方便地重置nextCheck時間值。隨後調用rollover()會導致日誌文件被滾動。由於這隻在啓動時發生,因此它是比在isTriggerEvent()內執行比較的更優化的解決方案。無論如何比較,它在每條日誌消息上執行時都會略微降低性能。這也會在啓動時立即發生翻轉,而不是等待第一個日誌事件。

在所有其他初始化完成之前,@NoAutoStart註釋對於防止Joran執行start()方法非常重要。否則,你會得到一個NullPointerException。

下面是配置:

<!-- Daily rollover appender that also appends timestamp and rolls over on startup --> 
    <appender name="startupDailyRolloverAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
    <file>${LOG_FILE}</file> 
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
     <fileNamePattern>${LOG_FILE}.%d{yyyyMMdd}_%d{HHmmss,aux}</fileNamePattern> 
     <TimeBasedFileNamingAndTriggeringPolicy class="my.package.StartupTimeBasedTriggeringPolicy" /> 
    </rollingPolicy> 
    <encoder> 
     <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> 
    </encoder> 
    </appender> 

希望這有助於!

+1

我很掙扎,這正是我想要的,謝謝! IMO這應該是一個標準功能,並配置是有點不直觀 – vincentlcy

+1

感謝您的解決方案 - 我同意@vincentlcy,也認爲這應該是一個標準功能。 – dcompiled

+0

只是想增加我的感謝一個偉大的解決方案。 我想,如果你已經定義了一個原文件名添加這隻作品(1.0.13的logback): 的event.txt 如果你從你的配置排除這讓你只能得到2.0,.1 .2等索引文件(這實際上是由Windows平臺的Logback文檔推薦的,以避免遇到文件鎖定/重命名問題),那麼這個解決方案不幸實際上不會實現翻轉,因爲在TimeBasedRollingPolicy.rollover()中調用getParentsRawFileProperty( )返回null。 – Mykro

1

我終於弄明白了。我可以按照規模,時間和時間開始。這裏是解決方案:

1日創建您自己的類

@NoAutoStart 
public class StartupSizeTimeBasedTriggeringPolicy<E> extends SizeAndTimeBasedFNATP<E> { 

    private boolean started = false; 

    @Override 
    public boolean isTriggeringEvent(File activeFile, E event) { 
     if (!started) { 
      nextCheck = 0L; 
      return started = true; 
     } 

     return super.isTriggeringEvent(activeFile, event); 
    }; 
} 

第2配置的logback

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
    <file>${LOGS_DIR}/${FILE_NAME}.log</file> 
    <encoder> 
     <pattern>%d [%thread] %-5level %logger{50} - %msg%n</pattern> 
    </encoder> 
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
     <fileNamePattern>${LOGS_DIR}/${FILE_NAME}.%d{yyyy-MM-dd}_%d{HHmmss,aux}.%i.log.zip</fileNamePattern> 
     <maxHistory>30</maxHistory> 
     <TimeBasedFileNamingAndTriggeringPolicy class="my.StartupSizeTimeBasedTriggeringPolicy"> 
      <MaxFileSize>250MB</MaxFileSize> 
     </TimeBasedFileNamingAndTriggeringPolicy> 
    </rollingPolicy> 
</appender> 
1

這個解決方案確實有效,非常感謝。 然而,有一個令人討厭的小故障:當你第一次運行程序時,日誌會在創建後立即滾動,當它是空的或幾乎爲空時。 所以我建議一個解決方案:檢查日誌文件是否存在,並且在調用方法時不是空的。 另外,還有一個整形修正:重命名「已啓動」變量,因爲它隱藏了具有相同名稱的繼承成員。

@NoAutoStart 
public class StartupSizeTimeBasedTriggeringPolicy<E> extends  SizeAndTimeBasedFNATP<E> { 

    private boolean policyStarted; 

    @Override 
    public boolean isTriggeringEvent(File activeFile, E event) { 
     if (!policyStarted) { 
      policyStarted = true; 
      if (activeFile.exists() && activeFile.length() > 0) { 
       nextCheck = 0L; 
       return true; 
      } 
     } 
     return super.isTriggeringEvent(activeFile, event); 
    } 
} 

而且,我相信它的logback與1.1.4版,快照(我得到了源和編譯它自己)正常工作,但它並不完全符合1.1.3版本一起使用。使用1.1.3時,它會使用指定的時區正確命名文件,但在默認時區午夜仍會發生滾動。

+0

我看到版本1.1.7現在已經出來,但這個功能仍然不存在。 有沒有計劃將其添加到標準包?它看起來很簡單。 很明顯,我仍然在使用自己的StartupSizeTimeBasedTriggeringPolicy,但它很煩人,請保持這樣一個小的添加。 –

5

我發現了另一個解決方案,用於在應用程序啓動時滾動logFile一次。

我使用logback的RollingFileAppender與logback的FixedWindowRollingPolicy和我自己實現的TriggeringPolicy<E>

FixedWindowRollingPolicy得到fileNamePattern爲新的日誌文件,其中%1是文件的新號碼。 maxIndex代表我的「歷史」的最大數量。更多信息:FixedWindowRollingPolicy

我實現TriggeringPolicy返回該第一一次真正的,當isTriggeringEvent(...)被調用。所以當第一次調用策略時,WindowRollingPolicy將滾動日誌文件,之後它不會再次滾動。

RollingFileAppender的XML配置:

<configuration> 
    ... 
    <appender name="FILE_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <file>logFile.log</file> 

     <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> 
      <fileNamePattern>logFile.%i.log</fileNamePattern> 
      <minIndex>1</minIndex> 
      <maxIndex>4</maxIndex> 
     </rollingPolicy> 

     <triggeringPolicy class="my.classpath.RollOncePerSessionTriggeringPolicy"/> 
    </appender> 
... 
</configuration> 

TriggeringPolicy

package my.classpath; 

import ch.qos.logback.core.rolling.TriggeringPolicyBase; 

import java.io.File; 

public class RollOncePerSessionTriggeringPolicy<E> extends TriggeringPolicyBase<E> { 
    private static boolean doRolling = true; 

    @Override 
    public boolean isTriggeringEvent(File activeFile, E event) { 
     // roll the first time when the event gets called 
     if (doRolling) { 
      doRolling = false; 
      return true; 
     } 
     return false; 
    } 
} 
3

對於使用已經存在的組件的logback暗示唯一命名的文件溶液:http://logback.qos.ch/manual/appenders.html#uniquelyNamed

在應用程序開發階段或短期應用程序例如 批處理應用程序時,最好在每次新的應用程序啓動時創建一個新的日誌文件 。在<timestamp>元素的幫助下,這很容易做到 。

<?xml version="1.0" encoding="UTF-8"?> 
<configuration> 
    <timestamp key="startTimestamp" datePattern="yyyyMMddHHmmssSSS"/> 
    <appender name="File" 
    class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <layout class="ch.qos.logback.classic.PatternLayout"> 
      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg \(%file:%line\)%n</Pattern> 
     </layout> 

     <file>server-${startTimestamp}.log</file> 

     <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
      <FileNamePattern>server-${startTimestamp}-%d{yyyy-MM-dd}-%i.log</FileNamePattern> 
      <!-- keep 7 days' worth of history --> 
      <MaxHistory>7</MaxHistory> 

      <TimeBasedFileNamingAndTriggeringPolicy 
      class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> 
       <MaxFileSize>1KB</MaxFileSize> 
      </TimeBasedFileNamingAndTriggeringPolicy> 
     </rollingPolicy> 
    </appender> 
    <root level="DEBUG"> 
     <appender-ref ref="File" /> 
    </root> 
</configuration> 

更新的的logback-1.2.1

<?xml version="1.0" encoding="UTF-8"?> 
<configuration> 
    <timestamp key="startTimestamp" datePattern="yyyyMMddHHmmssSSS"/> 
    <appender name="File" 
    class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <layout class="ch.qos.logback.classic.PatternLayout"> 
      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg \(%file:%line\)%n</Pattern> 
     </layout> 

     <file>server-${startTimestamp}.log</file> 

     <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> 
      <fileNamePattern>server-${startTimestamp}-%d{yyyy-MM-dd}-%i.log</fileNamePattern> 
      <maxFileSize>10MB</maxFileSize> 
      <!-- keep 7 days' worth of history --> 
      <maxHistory>7</maxHistory> 
      <totalSizeCap>20GB</totalSizeCap> 
     </rollingPolicy> 
    </appender> 
    <root level="DEBUG"> 
     <appender-ref ref="File" /> 
    </root> 
</configuration> 
0

該API已經改變(例如setMaxFileSize不再存在)和上述一個批次的東西不似乎工作,但我有一些工作對我來說,對logback 1.1.8(最新在這個時候)。

我想在啓動時滾動並滾動大小,但不是時間。這樣做:

public class RollOnStartupAndSizeTriggeringPolicy<E> extends SizeBasedTriggeringPolicy<E> { 
    private final AtomicBoolean firstTime = new AtomicBoolean(); 

    public boolean isTriggeringEvent(final File activeFile, final E event) { 
     if (firstTime.compareAndSet(false, true) && activeFile != null && activeFile.length() > 0) { 
      return true; 
     } 
     return super.isTriggeringEvent(activeFile, event); 
    } 
} 

有了這個,你還需要滾動策略。 FixedWindowRollingPolicy可能會這樣做,但我不喜歡它,因爲我想保留大量文件,而且效率非常低。逐漸增加的數字(而不是像FixedWindow那樣滑動)會起作用,但不存在。只要我寫我自己,我決定用時間而不是數。我想擴展當前的logback代碼,但對於基於時間的東西,滾動和觸發策略經常合併到一個類中,並且有嵌套和循環的東西以及沒有getter的字段的日誌,所以我發現這是不可能的。所以我不得不從頭開始做很多事情。我保持簡單,並沒有實現像壓縮這樣的功能 - 我很想擁有它們,但我只是試圖保持簡單。

public class TimestampRollingPolicy<E> extends RollingPolicyBase { 
    private final RenameUtil renameUtil = new RenameUtil(); 
    private String activeFileName; 
    private String fileNamePatternStr; 
    private FileNamePattern fileNamePattern; 

    @Override 
    public void start() { 
     super.start(); 
     renameUtil.setContext(this.context); 
     activeFileName = getParentsRawFileProperty(); 
     if (activeFileName == null || activeFileName.isEmpty()) { 
      addError("No file set on appender"); 
     } 
     if (fileNamePatternStr == null || fileNamePatternStr.isEmpty()) { 
      addError("fileNamePattern not set"); 
      fileNamePattern = null; 
     } else { 
      fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context); 
     } 
     addInfo("Will use the pattern " + fileNamePattern + " to archive files"); 
    } 

    @Override 
    public void rollover() throws RolloverFailure { 
     File f = new File(activeFileName); 
     if (!f.exists()) { 
      return; 
     } 
     if (f.length() <= 0) { 
      return; 
     } 
     try { 
      String archiveFileName = fileNamePattern.convert(new Date(f.lastModified())); 
      renameUtil.rename(activeFileName, archiveFileName); 
     } catch (RolloverFailure e) { 
      throw e; 
     } catch (Exception e) { 
      throw new RolloverFailure(e.toString(), e); 
     } 
    } 

    @Override 
    public String getActiveFileName() { 
     return activeFileName; 
    } 

    public void setFileNamePattern(String fnp) { 
     fileNamePatternStr = fnp; 
    } 
} 

然後配置看起來像

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
    <encoder> 
    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> 
    </encoder> 
    <file>/tmp/monitor.log</file> 
    <rollingPolicy class="my.log.TimestampRollingPolicy"> 
    <fileNamePattern>/tmp/monitor.%d{yyyyMMdd-HHmmss}.log</fileNamePattern> 
    </rollingPolicy> 
    <triggeringPolicy class="my.log.RollOnStartupAndSizeTriggeringPolicy"> 
    <maxFileSize>1gb</maxFileSize> 
    </triggeringPolicy> 
</appender> 

如果你在

http://jira.qos.ch/browse/LOGBACK-204

http://jira.qos.ch/browse/LOGBACK-215

沮喪,這是本身不解決,它投票(這是已經過去了幾年,對我來說這絕對是關鍵的樂趣ctionality,雖然我知道很多其他框架也失敗了)

相關問題