logback的使用和配置


參考:https://www.cnblogs.com/warking/p/5710303.html

   https://www.cnblogs.com

一.logback簡介

  1.logback:

    Logback是由log4j創始人設計的另一個開源日志組件。(好的日志記錄方式可以提供我們足夠多的定位錯誤的依據)。

  2.主要有三個模塊組成:

    logback-core:其它兩個模塊的基礎模塊。

    logback-classic:它是log4j的一個改良版本,同時它完整實現了slf4j API使你可以很方便地更換成其它日志系統如log4j或JDK14 Logging。()

    logback-access:訪問模塊與Servlet容器集成提供通過Http來訪問日志的功能。(第三方軟件通過該模塊訪問日志)

  3.logback主要標簽:

    logger:日志的記錄器(可以存放日志對象,也可以第一日志的級別,類型等);

    appender:指定日志輸出的媒介,即輸出地(可以是控制台,可以是文件,遠程套接字服務器等);

    layout:用來格式化日志信息的輸出。

二.logback優於log4的原因

  Logback對log4j進行了大量改進,Logback就是更好的log4j,這里參考官方文檔列舉主要部分【官網的翻譯:】。 

  更快的實施:基於我們之前關於log4j的工作,已經重寫了logback內部,以便在某些關鍵執行路徑上執行大約十倍的速度。不僅logback組件更快,而且內存占用更少。

     大量的測試:Logback提供了在幾年和無數小時工作中開發的大量測試。雖然log4j也經過測試,但logback將測試帶到了完全不同的水平。我們認為,這是優先於log4j進行logback的最重要原因。您希望您的日志框架即使在不利條件下也能夠堅如磐石且可靠。

     logback本身就實現了SLF4J:由於Loggerlogback-classic中的類本身實現了SLF4J API,因此在調用帶有logback-classic作為底層實現的SLF4J記錄器時,會產生零開銷。此外,由於logback-classic強烈鼓勵使用SLF4J作為其客戶端API,如果需要切換到log4j或jul,可以通過將一個jar文件替換為另一個來實現。您無需通過SLF4J API觸摸代碼記錄。這可以大大減少切換日志框架所涉及的工作。

   豐富的文檔:Logback附帶詳細且不斷更新的文檔。

   XML或Groovy的中的配置文件:配置logback的傳統方法是通過XML文件。文檔中的大多數示例都使用此XML語法。但是,從logback版本0.9.22開始,也支持用Groovy編寫的配置文件。與XML相比,Groovy風格的配置更直觀,更一致,並且語法更短。還有一個工具可以自動將logback.xml文件遷移到logback.groovy

  自動重新加載配置文件:Logback-classic可以在修改后自動重新加載其配置文件。掃描過程快速,無爭用,並且動態擴展到數百個線程上每秒數百萬次調用。它還可以播放中的應用服務器以及更一般地內的JEE環境,它並沒有涉及掃描一個單獨的線程的創建。

  從I / O故障中恢復正常:Logback FileAppender及其所有子類(包括RollingFileAppender)可以從I / O故障中正常恢復。因此,如果文件服務器暫時失敗,您不再需要重新啟動應用程序只是為了讓日志記錄再次運行。一旦文件服務器恢復,相關的logback appender將從之前的錯誤狀態透明地快速恢復。

  自動刪除舊的日志存檔:通過設置TimeBasedRollingPolicy 或SizeAndTimeBasedFNATPmaxHistory屬性,可以控制最大歸檔文件數。如果您的滾動策略要求每月滾動並且您希望保留一年的日志,只需將maxHistory屬性設置為12.將自動刪除超過12個月的存檔日志文件。 

  自動壓縮存檔的日志文件:RollingFileAppender 可以在翻轉期間自動壓縮歸檔日志文件。壓縮始終以異步方式發生,因此即使對於大型日志文件,您的應用程序也不會在壓縮期間被阻止。

    謹慎模式:謹慎模式下FileAppender在多個JVM上運行的多個實例可以安全地寫入同一個日志文件。由於某些限制,謹慎模式延伸至RollingFileAppender

  莉莉絲:Lilith是一個用於logback的日志記錄和訪問事件查看器。它與log4j的電鋸相當,只不過Lilith設計用於處理大量的測井數據而不會退縮。

  條件處理配置文件:開發人員經常需要在針對不同環境(如開發,測試和生產)的多個logback配置文件之間進行操作。這些配置文件有很多共同點,僅在少數幾個地方有所不同。為了避免重復,支持的logback 的配置文件條件處理的幫助下 <if><then>和 <else>元件,使得一個配置文件能充分瞄准幾個環境。

  過濾器:Logback提供了大量的過濾功能,遠遠超出了log4j所提供的功能。例如,假設您在生產服務器上部署了業務關鍵型應用程序。在處理大量事務的情況下,將日志記錄級別設置為WARN,以便僅記錄警告和錯誤。現在想象一下,您遇到的錯誤可以在生產系統上重現,但由於這兩個環境(生產/測試)之間存在未指定的差異,因此在測試平台上仍然難以捉摸。

使用log4j,您唯一的選擇是將生產系統上的日志記錄級別降低到DEBUG以嘗試識別問題。不幸的是,這將產生大量的記錄數據,使分析變得困難。更重要的是,廣泛的日志記錄會影響應用程序在生產系統上的性能。

使用logback,您可以選擇將所有用戶的日志記錄保持在WARN級別,但負責識別問題的Alice用戶除外。當Alice登錄時,她將以DEBUG級別登錄,而其他用戶可以繼續登錄WARN級別。這一壯舉可以通過在配置文件中添加4行XML來實現。在手冊MDCFilter相關部分搜索 

  SiftingAppender:SiftingAppender 是一個非常多才多藝的appender。它可用於根據任何給定的運行時屬性分離(或篩選)日志記錄。例如,SiftingAppender可以根據用戶會話分離日志記錄事件,以便每個用戶生成的日志進入不同的日志文件,每個用戶一個日志文件。

    堆棧跟蹤包裝數據:當logback打印異常時,堆棧跟蹤將包含打包數據。以下是logback-demo Web應用程序生成的示例堆棧跟蹤。

    14:28:48.835 [btpool0-7] INFO cqldemo.prime.PrimeAction - 99不是有效值 java.lang.Exception:99無效 在ch.qos.logback.demo.prime.PrimeAction.execute(PrimeAction.java:28)[classes /:na] at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431)[struts-1.2.9.jar:1.2.9] 在org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)[struts-1.2.9.jar:1.2.9] at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)[struts-1.2.9.jar:1.2.9] 在javax.servlet.http.HttpServlet.service(HttpServlet.java:820)[servlet-api-2.5-6.1.12.jar:6.1.12] 在org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:502)[jetty-6.1.12.jar:6.1.12] 在ch.qos.logback.demo.UserServletFilter.doFilter(UserServletFilter.java:44)[classes /:na] 在org.mortbay.jetty.servlet.ServletHandler $ CachedChain.doFilter(ServletHandler.java:1115)[jetty-6.1.12.jar:6.1.12] 在org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:361)[jetty-6.1.12.jar:6.1.12] 在org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)[jetty-6.1.12.jar:6.1.12] at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)[jetty-6.1.12.jar:6.1.12]

  從上面可以看出,應用程序正在使用Struts 1.2.9版,並在jetty版本6.1.12下部署。因此,堆棧跟蹤將快速告知讀者介入異常的類以及它們所屬的包和包版本。當您的客戶向您發送堆棧跟蹤時,作為開發人員,您將不再需要讓他們向您發送有關他們正在使用的軟件包版本的信息。該信息將成為堆棧跟蹤的一部分。有關詳細信息,請參閱“%xThrowable”轉換字

  這個功能非常有用,因為有些用戶錯誤地認為它是IDE的一個功能

    Logback-access,即帶有大腦的HTTP訪問日志記錄,是logback的一個組成部分,最后但同樣重要的是,logback-access模塊​​是logback發行版的一部分,它與Servlet容器(如Jetty或Tomcat)集成,以提供豐富而強大的HTTP訪問日志功能。由於logback-access是初始設計的一部分,因此您喜歡的所有logback-classic功能也可用於logback-access。

三.logback配置

  1.Java程序在運行時按照一定的順序加載先關的logback配置文件:

    (1)如果使用Java -Dlogback.configurationFile=xxxx/xxx.xml(指定配置文件),就會優先加載該配置文件;

    (2)如果沒有,就會在classpath下尋找是是否有logback.groovy(即logback支持groovy與xml兩種配置方式);

    (3)在classpath下尋找是否有logback-test.xml;

    (4)在classpath下尋找是否有logback.xm;

    (5)如果上面都沒找到且JDK版本是1.6以上,就會查找ch.qos.logback.classic.spi.Configuraror會自動調用相關類做相關配置;

    (6)如果還沒有,就會自動去找ch.qos.logback.classic.BasicConfigurator的configure這個實現類直接將日志輸入到控制台。

  2.配置介紹:  

    (1)Logger、appender及layout

       Logger作為日志的記錄器,把它關聯到應用的對應的context上后,主要用於存放日志對象,也可以定義日志類型、級別。
       Appender主要用於指定日志輸出的目的地,目的地可以是控制台、文件、遠程套接字服務器、 MySQL、PostreSQL、 Oracle和其他數據庫、 JMS和遠程UNIX Syslog守護進程等。 
       Layout 負責把事件轉換成字符串,格式化的日志信息的輸出。

    (2)logger context

      各個logger 都被關聯到一個 LoggerContext,LoggerContext負責制造logger,也負責以樹結構排列各logger。其他所有logger也通過org.slf4j.LoggerFactory 類的靜態方法getLogger取得。 getLogger方法以 logger名稱為參數。用同一名字調用LoggerFactory.getLogger 方法所得到的永遠都是同一個logger對象的引用。

    (3)有效級別及級別的繼承

      Logger 可以被分配級別。級別包括:TRACE、DEBUG、INFO、WARN 和 ERROR,定義於ch.qos.logback.classic.Level類。如果 logger沒有被分配級別,那么它將從有被分配級別的最近的祖先那里繼承級別。root logger 默認級別是 DEBUG。

    (4)打印方法與基本的選擇規則

      打印方法決定記錄請求的級別。例如,如果 L 是一個 logger 實例,那么,語句 L.info("..")是一條級別為 INFO的記錄語句。記錄請求的級別在高於或等於其 logger 的有效級別時被稱為被啟用,否則,稱為被禁用。記錄請求級別為 p,其 logger的有效級別為 q,只有則當 p>=q時,該請求才會被執行。
該規則是 logback 的核心。級別排序為: TRACE < DEBUG < INFO < WARN < ERROR(常用的為標紅的)

  3.logback.xml配置(我的配置):

<?xml version="1.0" encoding="UTF-8"?>
<!-- scan="true"表示配置文件發生改變時自動更新,scanPeriod表示多久掃描一次配置文件看是否更新 debug="true"會打印logback內部的日志信息,查看運行狀態 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- 定義參數常量 -->
    <!-- TRACE < DEBUG < INFO < WARN < ERROR -->
    <!-- logger.trace("msg") 某個級別的文件只能顯示該級別或者大於該級別的日志 -->
    <property name="log.level" value="debug" />
    <!-- 文件保留多長時間 -->
    <property name="log.maxHistory" value="30" />
    <!-- 日志存儲的根路徑 ${catalina.base}是存儲Tomcat實例的根目錄 -->
    <property name="log.filePath" value="${catalina.base}/logs/webapps" />
    <!-- 日志展示格式 %d表示時間格式,[%thread]線程 ,level級別,logger表示哪一個package下的哪一個類,%msg表示信息 -->
    <property name="log.pattern"
        value="%d{yyyy-MM-dd HH:mm:ss:SSS}[%thread]-5level%logger{50}-%msg%n" />
    <!-- 控制台設置 -->
    <!-- 日志輸出的地方 -->
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 相當於一個layout(將envent事件轉換為byte數組),但是它即負責轉換字符串,也負責輸入到日志文件中 -->
        <encoder>
            <!-- 定義格式 -->
            <pattern>${log.pattern}</pattern>
        </encoder>
    </appender>
    <!-- DEBUG -->
    <appender name="debugAppender"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 文件路徑 -->
        <file>${log.filePath}/debug.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 文件名稱 -->
            <fileNamePattern>${log.filePath}/debug/.%d{yyyy-MM-dd}.log.gz
            </fileNamePattern>
            <!-- 文件最大歷史數量 -->
            <maxHistory>${log.maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <!-- 過濾器 過濾level為DEBUG的日志信息 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMach>ACCEPT</onMach>
            <OnMismath>DENY</OnMismath>

        </filter>
    </appender>
    <!-- INFO -->
    <appender name="infoAppender"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 文件路徑 -->
        <file>${log.filePath}/info.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 文件名稱 -->
            <fileNamePattern>${log.filePath}/info/.%d{yyyy-MM-dd}.log.gz
            </fileNamePattern>
            <!-- 文件最大歷史數量 -->
            <maxHistory>${log.maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <!-- 過濾器 過濾level為INFO的日志信息 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMach>ACCEPT</onMach>
            <OnMismath>DENY</OnMismath>
        </filter>
    </appender>
    <!-- ERROR -->
    <appender name="errorAppender"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 文件路徑 -->
        <file>${log.filePath}/error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 文件名稱 -->
            <fileNamePattern>${log.filePath}/error/.%d{yyyy-MM-dd}.log.gz
            </fileNamePattern>
            <!-- 文件最大歷史數量 -->
            <maxHistory>${log.maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <!-- 過濾器 過濾level為ERROR的日志信息 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMach>ACCEPT</onMach>
            <OnMismath>DENY</OnMismath>
        </filter>
    </appender>
    <!-- 指定記錄的package,${log.level}指定哪個level以上,addtivity默認為true,會將父類root里的appender-ref也會放到自己的logger中 -->
    <!-- 注:一個類只能定義一個logger -->
    <logger name="com.swpu.o2o" level="${log.level}" addtivity="true">
        <!-- 與appender綁定 -->
        <appender-ref ref="debugAppender" />
        <appender-ref ref="infoAppender" />
        <appender-ref ref="errorAppender" />

    </logger>
    <!-- 特殊的logger,如果logger的level沒有指定,默認會繼承root的level -->
    <root level="info">
            <appender-ref ref="consoleAppender" />
    </root>
</configuration>

  4.測試:

  

package com.swpu.o2o.web.superadmin;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.swpu.o2o.entity.Area;
import com.swpu.o2o.service.AreaService;

import ch.qos.logback.classic.Logger;

@Controller
@RequestMapping("/superadmin")
public class AreaController {
 org.slf4j.Logger logger = LoggerFactory.getLogger(AreaController.class);     @Autowired
    private AreaService areaService;

    @RequestMapping(value = "/listarea", method = RequestMethod.GET)
    @ResponseBody
    private Map<String, Object> listArea() {
        logger.info("===start===");
        Long startTime=System.currentTimeMillis();
        Map<String, Object> modelMap = new HashMap<String, Object>();
        List<Area> list = new ArrayList<Area>();
        try {
            list = areaService.getAreaList();
            modelMap.put("rows", list);
            modelMap.put("total", list.size());
        } catch (Exception e) {
            e.printStackTrace();
            modelMap.put("success", false);
            modelMap.put("errMsg", e.toString());
        }
        logger.error("test error");
        Long endTime=System.currentTimeMillis();
        logger.debug("costTime:[{}ms]",endTime-startTime);
        logger.info("===end===");
        return modelMap;
    }

}

 

    在所配置的目錄查看成功

 

 

 

 

    

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM