1. 程式人生 > >logback框架使用誤區 如何將所有包的ERROR級別日誌集中列印到一個日誌檔案中

logback框架使用誤區 如何將所有包的ERROR級別日誌集中列印到一個日誌檔案中

早就想寫這個事情了,起因是自己想寫一個東西,其中使用logback日誌框架記錄日誌

打算 將所有包的ERROR及以上級別日誌打到一個檔案中,各個包下的日誌打到對應包的檔案中
起初寫的xml配置類似於這樣:

<!-- 其中一個appender,其他appender與其相同 ,只有name、file和fileNamePattern不同-->
<appender name="ALL-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>all-error.log</file
>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern> ${log_dir}/all-error.%d{yyyy-MM-dd}.%i.log </fileNamePattern> <maxFileSize>100MB</maxFileSize> <maxHistory>60</maxHistory
>
<totalSizeCap>20GB</totalSizeCap> </rollingPolicy> <encoder> <pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n </pattern> </encoder> </appender> <logger name="com.some.package1" level
="INFO" additivty="true">
<appender-ref ref="appender-1"/> </logger> <logger name="com.some.package2" level="INFO" additivty="true"> <appender-ref ref="appender-2"/> </logger> <logger name="com.some" level="ERROR" additivty="true"> <appender-ref ref="ALL-ERROR"/> </logger>

然而執行後卻發現,這樣配置後的,並沒有達到預期目標。
反而,所有INFO及以上的資訊,不僅在appender appender-1appender-2對應的日誌檔案中有,在appender為ALL-ERROR對應的日誌檔案中也都有,這是為何?

追蹤了一下斷點,發現如下程式碼片段:

/**
    * Invoke all the appenders of this logger.
    * 
    * @param event
    *          The event to log
    */
public void callAppenders(ILoggingEvent event) {
    int writes = 0;
    for (Logger l = this; l != null; l = l.parent) {
        writes += l.appendLoopOnAppenders(event);
        if (!l.additive) {
            break;
        }
    }
    // No appenders in hierarchy
    if (writes == 0) {
        loggerContext.noAppenderDefinedWarning(this);
    }
}

這段程式碼來自logback的 ch.qos.logback.classic.Logger檔案,是最終決定日誌內容輸出在哪裡的程式碼。
從這段程式碼我們可以發現:
1. logback會找到第一個符合日誌級別要求的logger,然後將日誌內容輸入到這個logger下配置的appender中。舉例來說:如果有一個com.some.package1內的類的INFO級別日誌,那麼首先會找到logger com.some.package1,然後找到logger下配置的appender appender-1;最後根據appender-1的配置,將日誌內容輸出到appender-1配置的檔案中。
2. 之後,logback根據additivty檢查logger是否允許繼承,如果配置為true(預設為true),則查詢上一級logger(實際是按照以包名為name查詢上一層包的logger),找到logger後,不再判斷logger配置是否符合日誌級別要求,直接找到對應的appender,將日誌內容輸出。

這就帶來了一個問題,位於低層次包的logger,在接收到日誌後,不僅會把它輸出到自身的appender中,還會將其傳遞給位於高層次包logger的appender中,無論高層次包logger配置的日誌級別是什麼。正因為如此,所以我打算將所有包的ERROR級別 日誌輸出到一個檔案的目的沒有實現,反而所有INFO及以上級別的日誌都輸出了。

按照這個思路,如果logger com.some.package1com.some.package2日記級別為ERROR,而logger com.some日誌級別為INFO的話,是否所有INFO及以上級別的日誌都可以記入logger com.some對應的appender下,而ERROR及以上級別的日誌會記入logger com.some.package1com.some.package2呢?測試證明,是這樣。

知道了為什麼上面的配置達不到目的,接下來要考慮的是,藉助什麼方式實現這個需求呢?

logback提供了實現需求的方式:藉助Filter來做:
既然logger無法判斷日誌級別,那我們可以在對應的appender裡判斷日誌級別。

logback的過濾器使用起來可以達到對每一條日誌的DENY、ACCEPT和NEUTRAL。
根據文章開始提出的需求,我們需要的是一個繫結appender的,過濾日誌等級的filter,那麼ch.qos.logback.classic.filter.ThresholdFilter正好是我們需要的。通過加入如下配置,appender ALL-ERROR將只能接受ERROR及以上的日誌:

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

完整的xml配置如下,僅改變了filter的部分,就實現了需求:

<!-- 其中一個appender,其他appender與其相同 ,只有name、file和fileNamePattern不同,並且沒有filter的標籤-->
<appender name="ALL-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>all-error.log</file>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">  
        <level>ERROR</level>  
    </filter> 
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <fileNamePattern>
            ${log_dir}/all-error.%d{yyyy-MM-dd}.%i.log
        </fileNamePattern>
        <maxFileSize>100MB</maxFileSize>
        <maxHistory>60</maxHistory>
        <totalSizeCap>20GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
        <pattern>
            %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
        </pattern>
    </encoder>
</appender>
<logger name="com.some.package1" level="INFO" additivty="true">
    <appender-ref ref="appender-1"/>
</logger>
<logger name="com.some.package2" level="INFO" additivty="true">
    <appender-ref ref="appender-2"/>
</logger>

<logger name="com.some" level="ERROR" additivty="true">
    <appender-ref ref="ALL-ERROR"/>
</logger>

相關推薦

Windows/Ubuntu下,所有檔名字列舉出來並儲存到txt檔案

Windows 使用如下的DOS命令來實現: dir /s /b > lists.txt 可以將當前路徑下的所有檔案的“檔案路徑+檔名”儲存在lists.txt中。 其中,/s表示的是“列

logback框架使用誤區 如何所有ERROR級別日誌集中列印一個日誌檔案

早就想寫這個事情了,起因是自己想寫一個東西,其中使用logback日誌框架記錄日誌 打算 將所有包的ERROR及以上級別日誌打到一個檔案中,各個包下的日誌打到對應包的檔案中。 起初寫的xml配置類似於這樣: <!-- 其中一個appender,

Java 尋找一個目下的所有“.Java”檔案,並他們的絕對路徑存到一個文字檔案

import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOExce

linux下一個目錄下的所有檔案拷貝到另一個檔案,並把大檔案拆分成原來的小檔案,大小,內容,名字不變

經過四五天的編寫與除錯,初步完成了檔案操作工具的內容,以下是程式碼說明: 首先,我測試用的檔案在/home/xudong/mywork下,我的最終生成檔案是在這個路徑下,/home/xudong/work/resultfile.txt,分開後生成的小檔案在/home/xud

springBoot 框架打成jar,讀取不到webapp下的靜態檔案

問題:使用springboot寫一個微服務,將pdf以模板形式匯出,pdf模板放在webapp下,在eclipse中執行沒有問題;以maven打成jar包,匯出pdf時,提示找不到該模板; 開啟jar包

Python所有輸出資訊同時輸出到控制檯和制定檔案

import sys class Logger(object): def __init__(self, fileN="Default.log"): self.terminal = sys.stdout self.log = open(

SHELL腳本:新增的行添加到另一個文件

shell#!/bin/bashcd /usr/local/logstash/nginxlog[ -f num.txt ] || count=0[ -f num.txt ] && count=cat num.txtncount=wc -l /var/log/nginx/access-app.l

node陣列寫到一個js檔案

const fs = require('fs'); let arr = [ 1, 2, 3, 'abc' ] fs.writeFile("url.js",'let articleUrlList = ' + JSON.stringify(arr), er

怎麼快速提取一個excel檔案所有工作表名

1.首先,我分享第一個方法,這個方法可是非常簡單的哦。開啟一個含有多個工作表的excel工作薄,然後新建一個工作表,此處命名為“彙總表”,如下圖所示。 2.找到“檢視程式碼”並開啟,查詢方法如下圖所示,有以下兩個方法:1.滑鼠右鍵點選“彙總表”,在下拉選單

C小程式—一個磁碟檔案的資訊複製到另一個磁碟檔案

#include <stdio.h>#include <stdlib.h>#include <string.h>int main(){FILE *fp1, *fp2;      //定義指向FILE型別檔案的指標變數char ch, fil

ios NSLog日誌重定向輸出到檔案儲存(3)

#pragma mark - app 日誌檔案記錄,用於測試; - (void)redirectNSLogToDocumentFolder { //如果已經連線Xcode除錯則不輸出到檔案 /* if(isatty(STDOUT_FILENO)) {

log4j詳解 指定日誌輸出到不同的檔案

import org.apache.log4j.Logger; <span style="font-family: Arial, Helvetica, sans-serif;">public class HelloWorld {</span> <span style="whit

如何用java讀取csv檔案指定行列的資料,並csv資料元素隨機置零後儲存到另一個csv檔案

這個流程可以大致分為兩步驟:1.讀取csv檔案中的資料2.生成隨機數,將csv的資料隨機置零,將新生成的檔案儲存到新的csv中一、首先我們進行第一步:讀取csv中的檔案:讀取函式格式為public static double readin(int row,int col)

假設一個文字檔案儲存著100個整數,請這100個整數按從小到大的順序寫到另一個檔案

假設一個文字檔案中儲存著100個整數,請將這100個整數按從小到大的順序寫到另個文字檔案中去,並且在新檔案中每十個整數佔一行,原始檔名和目標檔名通過命令列引數獲取。程式如下: #include <stdio.h> void main(int argc, char

Matlab 多個子函式寫到一個m檔案

一般來講,在matlab中定義多個函式,需要存成多個m檔案,每一個檔案是一個函式 但是當我們的函式過於簡單,沒有必要存成多個檔案時,我們可以將多個子函式存在一個主函式下,這樣就可以存在一個m檔案中了。 例子 新建m檔案'makefuns.m' function fun

SpringBoot所有依賴(包括本地jar)打包到專案

Maven 新增本地依賴包 在專案根目錄新增lib資料夾,存放不在maven倉庫中存在的jar包 如下兩個推送包,(名字可以自定義) //華為推送服務端jar包 HwPush_SDK_Server_0_3_12.jar //小米推送服務端jar包 MiPush_SDK_Server_2_2_

springboot程式logback日誌基本配置,多個不同日誌級別輸入到檔案

日誌是程式中必不可少的內容。依據日誌我們可以有效診斷程式bug,統計使用者訪問和各主要功能的使用頻率時間段等資訊。因此我們會需要不同package使用不同的日誌級別,以及不同業務的日誌輸出到不同的檔案。下面本文簡要概述如何使用logback將不同包的不同級別日誌輸出到info1.txt中

java使用slf4j+log4j進行日誌記錄並ERROR級別資訊入庫

1.maven 座標   <!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>lo

logback日誌的使用,每天生成一個日誌檔案,以及error和其他級別日誌的分離

springboot會自動幫我們讀取logback的配置檔案,我們實現只需要新增即可在application中配置日誌檔案的位置logging: config: classpath:conf/logback-dev.xml配置檔案的內容如下:<?xml versio

Maven所有依賴打成一個jar

需求 將專案依賴的jar包打成一個jar包 程式碼 <build> <finalName>${project.artifactId}</finalName> <defaultGoal>package</d