springboot+logback日誌規範

當前問題

項目採用springboot的框架集成了logback的日誌配置方式,但是在使用中遇到了很多問題,同時也基於“立刻方能用好”的原則,對於logback與springboot的配置做了一些瞭解和其它項目的配置對比,結合當前項目的需求,及需要解決的問題的方案,記錄於此。

  1. logback的日誌配置統一採用/home/logs目錄,但是基於本地測試時,Mac電腦沒有權限寫文件到/home目錄,同時也不想寫日誌文件到本機
  2. 本地調試項目,需要將日誌輸出到終端查看接口執行流程,但是其它環境不能將日誌輸出到終端,頻繁更改配置容易上線時疏漏
  3. 線上日誌輸出需要採用info級別,但是其他環境(dohko,pre)可能需要做debug輸出,獲取更多的日誌信息,頻繁更改日誌級別容易導致上線時疏忽檢查導致線上日誌文件很大
  4. mybatis的sql輸出只有在debug模式下才能輸出,但是線上日誌都是info級別,如何做到info級別的日誌也能輸出mybatis的sql日誌
  5. 同一日誌級別下,需要過濾項目依賴其它包的日誌輸出,或將其日誌級別調低,甚至不輸出

配置示例

logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 
    <!--
       說明:
       1、日誌級別及文件
           日誌記錄採用分級記錄,級別與日誌文件名相對應,不同級別的日誌信息記錄到不同的日誌文件中
           例如:error級別記錄到{log.context.name}_error.log(該文件爲當前記錄的日誌文件),而{log.context.name}__error.log爲歸檔日誌,
           日誌文件按日期記錄,每天的日誌不再拆分
           例如log-level-2013-12-21.log
           其它級別的日誌也是如此。
       2、文件路徑
           統一輸出到/home/logs
       3、Appender
           FILEERROR對應error級別,文件名以{log.context.name}_xxx_error.log形式命名
           FILEWARN對應warn級別,文件名以{log.context.name}_xxx_error.log形式命名
           FILEINFO對應info級別,文件名以{log.context.name}_xxx_error.log形式命名
           FILEDEBUG對應debug級別,文件名以{log.context.name}_xxx_error.log形式命名
           默認輸出級別爲debug,不明確指定情況下文件名以{log.context.name}.log形式命名
           stdout將日誌信息輸出到控制上,爲方便開發測試使用
    -->
 
    <!--定義日誌文件的存儲地址 勿在 LogBack 的配置中使用相對路徑-->
    <property name="log.directory" value="/home/logs/" />
    <!--項目名稱,也是存儲日誌的具體目錄-->
    <property name="log.context.name" value="shop-crm-service21" />
    <!--日誌的字符編碼-->
    <property name="log.charset" value="UTF-8" />
    <!--歷史記錄最大保存天數-->
    <property name="log.maxHistory" value="30" />
    <!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符-->
    <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}$$[%thread]$$%-5level{}$$shop-crm-service$$%msg%n" />
    <!--日誌Error級別名稱配置-->
    <property name="log.error.log.level" value="ERROR" />
    <!--異步寫日誌的隊列大小配置,默認爲256-->
    <property name="log.async.queue.size" value="1024" />
 
    <!--配置日誌的上下文名稱-->
    <contextName>${log.context.name}</contextName>
 
    <!--對應spring環境變量爲local的日誌配置,只做控制檯輸出配置-->
    <springProfile name="local">
        <!--控制檯日誌輸出配置,可以匹配色彩和高亮-->
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}) - %yellow([%file:%line]) - %msg%n</pattern>
                <!--<pattern>${log.pattern}</pattern>-->
                <charset>${log.charset}</charset>
            </encoder>
        </appender>
    </springProfile>
 
    <springProfile name="mu,dohko,pre,production">
        <!-- 服務器上使用的appender start -->
        <!-- 默認的file appender,按天切分日誌 -->
        <appender name="ROLLING_FILE_DEFAULT" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${log.directory}${log.context.name}/${HOSTNAME}.log</file>
            <append>true</append>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${log.directory}${log.context.name}/${HOSTNAME}.%d{yyyy-MM-dd}.log</fileNamePattern>
                <maxHistory>${log.maxHistory}</maxHistory>
            </rollingPolicy>
            <encoder>
                <pattern>${log.pattern}</pattern>
                <charset>${log.charset}</charset>
            </encoder>
        </appender>
 
        <!-- 錯誤日誌,按天切分 -->
        <appender name="ROLLING_FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>${log.error.log.level}</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
            <file>${log.directory}${log.context.name}/${HOSTNAME}_error.log</file>
            <!-- 日誌追加配置 -->
            <append>true</append>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${log.directory}${log.context.name}/${HOSTNAME}_error.%d{yyyy-MM-dd}.log</fileNamePattern>
                <maxHistory>${log.maxHistory}</maxHistory>
            </rollingPolicy>
            <!-- 此日誌文件只記錄error級別的 -->
            <encoder>
                <pattern>${log.pattern}</pattern>
                <charset>${log.charset}</charset>
            </encoder>
        </appender>
 
        <!-- 異步寫日誌文件的配置 -->
        <appender name ="ASYNC_FILE" class"ch.qos.logback.classic.AsyncAppender">
            <!-- 當隊列達到配置隊列大小的80%時,不將日誌丟失 -->
            <discardingThreshold >0</discardingThreshold>
            <queueSize>${log.async.queue.size}</queueSize>
            <appender-ref ref "ROLLING_FILE_DEFAULT"/>
        </appender>
    </springProfile>
 
    <!-- rabbitmq的日誌專屬配置 -->
    <logger name "org.springframework.amqp.rabbit.listener.BlockingQueueConsumer" level ="WARN"/>
    <!-- zookeeper 的日誌專屬配置 -->
    <logger name "org.apache.zookeeper.ClientCnxn" level ="WARN"/>
    <!-- 多數據源 的日誌專屬配置 -->
    <logger name "com.hualala.commons.multidatasource.curator.CuratorClient" level ="WARN"/>
    <logger name "com.hualala.commons.multidatasource.datasource.DynamicDataSource" level ="WARN"/>
    <!-- 設置falcon監控的日誌輸出格式 -->
    <logger name "com.hualala.infrastructure.falcon.FalconMonitor" level ="WARN"/>
 
    <!--mybatis的日誌專屬配置 -->
    <logger name="jdbc.sqltiming" level="debug"/>
    <logger name="com.ibatis" level="debug" />
    <logger name="com.ibatis.common.jdbc.SimpleDataSource" level="debug" />
    <logger name="com.ibatis.common.jdbc.ScriptRunner" level="debug" />
    <logger name="com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate" level="debug" />
    <logger name="java.sql.Connection" level="debug" />
    <logger name="java.sql.Statement" level="debug" />
    <logger name="java.sql.PreparedStatement" level="debug" />
    <logger name="java.sql.ResultSet" level="debug" />
 
    <logger name="org.springframework" level="WARN" />
 
    <!-- 當前項目 的不同環境的日誌級別配置 -->
    <logger name="com.hualala" level="debug" additivity="false">
        <springProfile name="local">
            <appender-ref ref="STDOUT" />
        </springProfile>
 
        <springProfile name="mu,dohko,pre">
            <appender-ref ref="ASYNC_FILE" />
            <appender-ref ref="ROLLING_FILE_ERROR" />
        </springProfile>
 
        <springProfile name="production">
            <appender-ref ref="ASYNC_FILE" />
            <appender-ref ref="ROLLING_FILE_ERROR" />
        </springProfile>
    </logger>
 
    <root>
        <springProfile name="local">
            <level value="info"/>
            <appender-ref ref="STDOUT" />
        </springProfile>
 
        <!-- dohko環境用來測試,日誌級別儘量可以設置的低,便於定位問題 -->
        <springProfile name="mu,dohko,pre">
            <level value="info"/>
 
            <appender-ref ref="ASYNC_FILE" />
            <appender-ref ref="ROLLING_FILE_ERROR" />
        </springProfile>
 
        <!-- pre環境用來做壓測,避免對測試環境的日誌服務產生壓力,日誌級別設置爲warn -->
        <springProfile name="pre">
            <level value="warn"/>
 
            <appender-ref ref="ASYNC_FILE" />
            <appender-ref ref="ROLLING_FILE_ERROR" />
        </springProfile>
 
        <!-- production爲生產環境,需要記錄能夠定位問題或流程流轉的日誌,但是非必要的日誌無須記錄 -->
        <springProfile name="production">
            <level value="info"/>
            <appender-ref ref="ASYNC_FILE" />
            <appender-ref ref="ROLLING_FILE_ERROR" />
        </springProfile>
    </root>
</configuration>

 

配置解析

property:將配置中引用的公共的常量做全局設置,便於修改及維護
springProfile:配置spring的環境變量名稱(對應application.yml中的profilename,name可以爲單個或多個,多個名稱用“,”隔開,還可取反,比如!local,代表非local環境的其它所有環境),appender節點的日誌級別在未明確指定的情況下,繼承自root根結點指定等級及其父等級
root:root根結點配置,內部配置多個環境變量對應的日誌引用,爲每個環境變量設置對應等級,在local本地環境變量下配置終端輸出日誌,其它環境則配置寫入文件
logger:直接指定第三方服務的根目錄報名,設置日誌級別高於其默認輸出的日誌級別,將限制其日誌輸入;
如果將其日誌級別設置爲小於等於其日誌輸出級別,且小於root根節點的日誌級別,此時需要輸出logger指定日誌,則需要配置當前項目的的日誌級別爲logger中指定的日誌級別,

參考資料

github項目配置參考

springboot+logback日誌配置

logback官方文檔

logback 異步日誌配置

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章