国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Logback源碼賞析-日志按時間滾動(切割)

dance / 1942人閱讀

摘要:引言用過的同學們大多都知道日志框架可以自動按照某個時間點切割日志的功能。而跟日志切割相關(guān)的邏輯就在這里面。第一步判斷是否需要切割日志,需要就執(zhí)行滾動操作。中實現(xiàn)了按照時間切割日志的策略。如果到了應(yīng)該切割日志的時間則會調(diào)用方法。

引言

用過Logback的同學們大多都知道Logback日志框架可以自動按照某個時間點切割日志的功能。但了解其中工作原理的同學可能并不是很多。樓主今天就帶領(lǐng)各位了解一下其中的核心源碼。本文的示例引用了Logback 1.1.7版的源碼。

舉個實際的例子,如果希望某一個Appender按天切割日志,那么我們需要類似如下的配置:

    
        logs/service-log.log
        
            %d{yyyy-MM-dd HH:mm:ss} %level [%class:%line] - %m%n
        
        
            
            logs/service-log.%d{yyyy-MM-dd}.log.zip
        
    

如果需要日志切割功能,首先要選用RollingFileAppender這種Appender,之后要配置TimeBasedRollingPolicy作為該Appender的滾動策略。

源碼解讀

業(yè)務(wù)代碼在調(diào)用Logback的記錄日志的方法時,Logger類會調(diào)用ch.qos.logback.core.Appender#doAppend方法。Appender的doAppend就是Appender記錄日志功能的入口。
我們先來看一下RollingFileAppender的繼承關(guān)系

看起來貌似有些暈。沒關(guān)系,doAppend方法經(jīng)過幾層之后會調(diào)到ch.qos.logback.core.rolling.RollingFileAppender#subAppend 這個方法。而跟日志切割相關(guān)的邏輯就在這里面。因此從doAppend到subAppend之間的調(diào)用鏈路我們在此略過不提,而是從subAppend這個方法切入。

    /**
    * This method differentiates RollingFileAppender from its super class.
    */
    @Override
    protected void subAppend(E event) {
        // The roll-over check must precede actual writing. This is the
        // only correct behavior for time driven triggers.

        // We need to synchronize on triggeringPolicy so that only one rollover
        // occurs at a time
        synchronized (triggeringPolicy) {
            if (triggeringPolicy.isTriggeringEvent(currentlyActiveFile, event)) {
                rollover();
            }
        }

        super.subAppend(event);
    }

第一步判斷是否需要切割日志,需要就執(zhí)行滾動操作。第二步執(zhí)行父類中的寫日志操作。
TimeBasedRollingPolicy中實現(xiàn)了按照時間切割日志的策略。

ch.qos.logback.core.rolling.TimeBasedRollingPolicy#isTriggeringEvent方法

    public boolean isTriggeringEvent(File activeFile, final E event) {
        return timeBasedFileNamingAndTriggeringPolicy.isTriggeringEvent(activeFile, event);
    }

這個timeBasedFileNamingAndTriggeringPolicy是DefaultTimeBasedFileNamingAndTriggeringPolicy類的實例。
ch.qos.logback.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy#isTriggeringEvent方法

    public boolean isTriggeringEvent(File activeFile, final E event) {
        long time = getCurrentTime();//獲得當前時間
        if (time >= nextCheck) {//如果當前時間大于下一次滾動時間點,則執(zhí)行如下邏輯
            Date dateOfElapsedPeriod = dateInCurrentPeriod;//之前時間段的開始時間
            addInfo("Elapsed period: " + dateOfElapsedPeriod);
            elapsedPeriodsFileName = tbrp.fileNamePatternWithoutCompSuffix.convert(dateOfElapsedPeriod);//算出之前一個時間段的文件名字(用于將當前文件重命名)
            setDateInCurrentPeriod(time);//將當前時間保存起來,作為下次滾動時的上一次滾動的時間點
            computeNextCheck();//計算下次滾動時間
            return true;
        } else {
            return false;
        }
    }

ch.qos.logback.core.rolling.helper.FileNamePattern類的convert方法根據(jù)上次滾動執(zhí)行的開始時間計算出了本次操作的文件名。

計算下次滾動執(zhí)行的時間。

    protected void computeNextCheck() {
        nextCheck = rc.getNextTriggeringDate(dateInCurrentPeriod).getTime();
    }

上述方法調(diào)用了ch.qos.logback.core.rolling.helper.RollingCalendar#getNextTriggeringDate
RollingCalendar這個工具類是用來計算每一次觸發(fā)滾動操作的時間的。RollingCalendar的periodicityType成員變量就是滾動時間類型枚舉,可以是天、小時、分鐘等等時間單位。這個值并不是在logback.xml文件中配置的,而是拿到日期格式“%d{yyyy-MM-dd}”之后自動計算出來的。計算原理就是用日期格式創(chuàng)建一個SimpleDateFormat然后按照時間單位從小到大(必須是從小到大)的順序依次試驗。每次試驗的方法就是用SimpleDateFormat生成兩個時間,這兩個時間相差1倍的該時間單位的時間,然后將兩個時間轉(zhuǎn)換成字符串進行對比,如果這兩個字符串不相等就說明該日期格式對應(yīng)的時間單位是當前試驗的時間單位。

看完判斷是否觸發(fā)滾動的邏輯之后我們把視線轉(zhuǎn)回ch.qos.logback.core.rolling.RollingFileAppender#subAppend方法。如果到了應(yīng)該切割日志的時間則會調(diào)用rollover方法。

    /**
     * Implemented by delegating most of the rollover work to a rolling policy.
     */
    public void rollover() {
        lock.lock();
        try {
            // Note: This method needs to be synchronized because it needs exclusive
            // access while it closes and then re-opens the target file.
            //
            // make sure to close the hereto active log file! Renaming under windows
            // does not work for open files.
            this.closeOutputStream();
            attemptRollover();
            attemptOpenFile();
        } finally {
            lock.unlock();
        }
    }

滾動方法里面自己控制了線程同步邏輯,保證多個線程只有一個會執(zhí)行滾動操作。attemptRollover方法調(diào)用了ch.qos.logback.core.rolling.TimeBasedRollingPolicy#rollover方法

    public void rollover() throws RolloverFailure {

        // when rollover is called the elapsed period"s file has
        // been already closed. This is a working assumption of this method.

        String elapsedPeriodsFileName = timeBasedFileNamingAndTriggeringPolicy.getElapsedPeriodsFileName();//獲得上個周期的文件名字

        String elapsedPeriodStem = FileFilterUtil.afterLastSlash(elapsedPeriodsFileName);

        if (compressionMode == CompressionMode.NONE) {
            if (getParentsRawFileProperty() != null) {
                renameUtil.rename(getParentsRawFileProperty(), elapsedPeriodsFileName);//將當前文件重命名
            } // else { nothing to do if CompressionMode == NONE and parentsRawFileProperty == null }
        } else {
            if (getParentsRawFileProperty() == null) {
                compressionFuture = compressor.asyncCompress(elapsedPeriodsFileName, elapsedPeriodsFileName, elapsedPeriodStem);//執(zhí)行異步壓縮,里面用到了java語言的Future
            } else {
                compressionFuture = renameRawAndAsyncCompress(elapsedPeriodsFileName, elapsedPeriodStem);
            }
        }

        if (archiveRemover != null) {
            Date now = new Date(timeBasedFileNamingAndTriggeringPolicy.getCurrentTime());
            cleanUpFuture = archiveRemover.cleanAsynchronously(now);//執(zhí)行清理,清楚過期日志
        }
    }

其中有一些工具類可以供我們在業(yè)務(wù)開發(fā)過程中使用,比如ch.qos.logback.core.rolling.helper.RenameUtil#rename可以將文件重命名,拿來用就可以不用重復(fù)造輪子了。

    private void attemptOpenFile() {
        try {
            // update the currentlyActiveFile LOGBACK-64
            currentlyActiveFile = new File(rollingPolicy.getActiveFileName());//創(chuàng)建一個當前的文件,新的日志輸出到這個文件。因此日志的滾動操作就完成了

            // This will also close the file. This is OK since multiple close operations are safe.
            this.openFile(rollingPolicy.getActiveFileName());
        } catch (IOException e) {
            addError("setFile(" + fileName + ", false) call failed.", e);
        }
    }
結(jié)束語

由于篇幅關(guān)系,一些細節(jié)沒有展開。歡迎大家拍磚。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/66542.html

相關(guān)文章

  • 函數(shù)防抖(debounce)和節(jié)流(throttle)以及l(fā)odash的debounce源碼賞析

    摘要:防抖函數(shù)防抖和節(jié)流是一對常常被放在一起的場景。同時,這里會設(shè)置一個定時器,在等待后會執(zhí)行,的主要作用就是觸發(fā)。最后,如果不再有函數(shù)調(diào)用,就會在定時器結(jié)束時執(zhí)行。 函數(shù)節(jié)流和去抖的出現(xiàn)場景,一般都伴隨著客戶端 DOM 的事件監(jiān)聽。比如scroll resize等事件,這些事件在某些場景觸發(fā)非常頻繁。 比如,實現(xiàn)一個原生的拖拽功能(不能用 H5 Drag&Drop API),需要一路監(jiān)聽...

    Enlightenment 評論0 收藏0
  • logback 配置文件編寫

    摘要:配置本文講的文件的配置,其中主要是在介紹各類。注意,使用必須聲明節(jié)點子節(jié)點指定命名模式注意,必須包含,為窗口索引。并且為單獨拿出來。 Logback 配置 本文講logback的xml文件的配置,其中主要是在介紹各類appender。 logback 的簡單例子 xml文件大概結(jié)構(gòu) 導(dǎo)圖鏈接showImg(https://segmentfault.com/img/bV8gtH?w=27...

    546669204 評論0 收藏0
  • Spring Boot 自定義日志詳解

    摘要:定制日志文件簡單的日志配置不能滿足實際項目需求,那可以通過引用定制日志文件的形式達到目的。能根據(jù)類路徑下的類庫和配置文件自動配置對應(yīng)的日志框架。看到這里,相信你對的日志應(yīng)該有了一個全面的了解。 本節(jié)內(nèi)容基于 Spring Boot 2.0. 你所需具備的基礎(chǔ) 什么是 Spring Boot? Spring Boot 核心配置文件詳解 Spring Boot 開啟的 2 種方式 Spr...

    baishancloud 評論0 收藏0
  • logback的簡單使用

    摘要:的測試完全不同級別的。記錄請求的級別在高于或等于其的有效級別時被稱為被啟用,否則,稱為被禁用。該規(guī)則是的核心。指定名稱,指定的全限定名。對記錄事件進行格式化。查看當前活動文件的大小,如果超過指定大小會告知觸發(fā)當前活動文件滾動。 一、logback的介紹 Logback是由log4j創(chuàng)始人設(shè)計的又一個開源日志組件,官方網(wǎng)站: http://logback.qos.ch。 logback當...

    habren 評論0 收藏0
  • java日志框架

    摘要:一日志概述領(lǐng)域存在多種日志框架,目前常用的日志框架包括,,,,,。開銷更高三與其他日志組件調(diào)用關(guān)系包名說明版本的橋接器,你需要將加入。的橋接器,原生日志框架。 一、Java日志概述 java領(lǐng)域存在多種日志框架,目前常用的日志框架包括Log4j 1,Log4j 2,Commons Logging,Slf4j,Logback,Jul。 Commons Logging和Slf4j是日志...

    dendoink 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<