tomcat日志及logback相關日志框架


一、重點問題整理

1.1 關於logback.xml中的路徑設置問題

准備金系統的logback.xml中設置的路徑是:

<!-- 定義日志文件 輸出位置 -->

<property name="log_dir" value="E:\logs" />

在Windows環境下,會識別E:為系統的E盤,默認在E盤下創建logs文件夾。但是正在Linux環境下,不存在E盤,會將E:\logs識別為E:logs文件夾。此時為相對路徑,而tomcat在創建文件時:會從程序啟動的地方去創建這個文件(Java項目中也是如此),那么web應用是從有tomcat來執行的,tomcat這個程序是從哪里啟動文件是startup.bat?位置是tomcat/bin。會在bin目錄下創建E:logs文件夾,而不是在tomcat的默認根路徑故tomcat文件夾下創建E:logs文件夾。(驗證:若是用sh bin/startup.sh命令,在tomcat目錄下啟動tomcat,則會在tomcat路徑下創建E:logs文件夾。)

所以為了使日志文件在我們指定的目錄下,有兩只方式:

【1】我們可以使用絕對路徑:      /

【2】也可以使用相對路徑:

./ 當前目錄。

../ 父級目錄。

/ 根目錄。

但是並不及建議用E:這種寫死的路徑。可以用以下方式創建日志文件的路徑:

方式一:

value="${catalina.home}/logs":
本地:會在tomcat目錄下創建logs文件。
Linux:Linux上會在tomcat目錄下創建logs文件。

方式二:

value="${catalina.base}/logs":
本地:會在C:\Users\Administrator\.IntelliJIdea2017.2\system\tomcat\Unnamed_reserve_10目錄下創建logs文件。(因為
本地tomcat為每個idea項目在這里創建了一個副本,項目是在這里啟動的)
Linux:會在tomcat目錄下創建logs文件。

方式三:

value="logs":會在tomcat/bin目錄下創建logs文件。

../webapps/工程名:會在工程名目錄下創建logs文件。

注意:我上次本地啟動項目是在E盤創建的logs文件夾,這次可能是改啥東西了?我也不知道,反正本地的logs文件夾又跑tomcat/bin目錄下了。奇怪。

 

 

 這個是用tomcat啟動的web項目。我在這個項目里建了個main主方法,創建的logs文件又跑項目的根路徑下了:

邪了門了,本地啟動項目,好像配置的路徑不起作用了。。。

1.2 查看日志是輸出的格式,及在不同級別文件中都是怎么記錄日志信息的?是否與控制台的輸出內容一致?

答:一致。

本地文件:

 

 

 控制台:

1.3 為什么要用日志框架來進行日志管理?

日志框架對日志的管理能力非常強大,可以根據自定義的日志等級輸出日志到指定位置,還可以對日志文件進行切分。Java自帶的功能滿足不了需要。

1.4 tomcat - catalina.out 日志過大處理方法

解決方案:

1.4.1 修改tomcat的日志配置,配置輸出日志級別

修改conf/logging.properties日志配置文件來屏蔽掉這部分的日志信息。

將level級別設置成WARNING就可以大量減少日志的輸出,當然也可以設置成OFF,直接禁用掉。

1.4.2 修改工程的日志配置:輸出在控制台的級別

刪除log4j中的輸出控制台的日志配置,catalina.out中不再記錄應用的日志。  日志輸出級別:ALL、DEBUG、INFO、WARN、ERROR  這下它不會漲的那么快了。設置工程項目輸出至控制台catalina.out日志的級別: WARN

1.4.3 對catalina.out 啟動定時清空

  編寫清空腳本腳本:(默認目錄tomcat 根目錄) 

1.4.4 tomcat不輸出到catalina.out

由於最近項目需要部署到外網環境,之前在內網測試看日志都是在catalina.out,但是現在修改了一下,不需要看這個了,而且如果項目在外網環境部
署,這個文件一直會增大,浪費空間,所有墨跡了半天,才重網上找到一個比較好的方法,不輸出到catalina.out. 找到tomcat下的   bin
/catalina.sh;  找到下面這一段, 把#CATALINA_OUT="$CATALINA_HOME"/logs/catalina.out 注釋掉,改為CATALINA_OUT=/dev/null, if [ -z "$CATALINA_OUT" ] ; then #CATALINA_OUT="$CATALINA_HOME"/logs/catalina.out CATALINA_OUT=/dev/null fi 對於/dev/null,我在網上了解是,它相當於垃圾桶一樣,輸出什么到它哪里,它直接丟了.所有我們在/dev/null,看到null這個文件,大小是空的,所有並不會占用空間大小了.

1.4.4 禁止日志輸出到catalina.out

1、修改tomcat/conf/logging.properties中的日志輸出級別

把 catalina.org.apache.juli.AsyncFileHandler.level = FINE

更改為 catalina.org.apache.juli.AsyncFileHandler.level = OFF

OFF為禁止

 改后效果如圖:

 

2、關閉localhost_access_log日志

注釋tomcat/conf/server.xml中最下方AccessLogValue

 

3、修改tomcat/bin/catalina.sh中 185行左右

if [ -z "$CATALINA_OUT" ] ; then

  CATALINA_OUT="$CATALINA_BASE"/logs/catalina.out

fi

改為

 

null作為垃圾桶,因此大小為0

原文鏈接:https://blog.csdn.net/su1573/article/details/87883126

1.5 Windows下生成calalina.out 日志文件

之前我們在linux系統下查看日志的時候,總有個習慣,啟動項目后會進入logs/下,敲擊類似

tail -fn500 catalina.out
tail -f catalina.out

 

的命令,便可以進入到catalina.out中實時的顯示出最新的500行信息,但是有個問題,在windows系統中我們卻沒發現這個catalina.out,難道是只有在linux系統下才有catalina.out文件嗎?其實不是這樣的,首先說下為什么在linux下是叫catalina.out,這是由於catalina_home/bin/catalina.sh文件指定的,參看下面部分源碼:

shift

  touch "$CATALINA_BASE"/logs/catalina.out

  if [ "$1" = "-security" ] ; then

    echo "Using Security Manager"

    shift

    "$_RUNJAVA" $JAVA_OPTS "$LOGGING_CONFIG" $CATALINA_OPTS \

      -Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" -classpath "$CLASSPATH" \

      -Djava.security.manager \

      -Djava.security.policy=="$CATALINA_BASE"/conf/catalina.policy \

      -Dcatalina.base="$CATALINA_BASE" \

      -Dcatalina.home="$CATALINA_HOME" \

      -Djava.io.tmpdir="$CATALINA_TMPDIR" \

      org.apache.catalina.startup.Bootstrap "$@" start \

      >> "$CATALINA_BASE"/logs/catalina.out 2>&1 &

      if [ ! -z "$CATALINA_PID" ]; then

        echo $! > $CATALINA_PID

      fi

注:touch命令可以創建一個不存在的文件。

  那么同理可以想象在windows下也可以存在catalina.out文件(只是默認建的文件不叫這個名而已),那么可不可以在windows系統下也看的見,或者說創建出catalina.out呢?答案是肯定的,參考如下:

由於tomcat本身是可以跨平台的,故既然有linux下的catalina.sh,就會對應有windows下的catalina.bat。

問題:windows下的tomcat的日志只輸出在控制台下,且日志文件輸出只有一些基本信息。如何把所有日志都輸出到catalina.out?

解決方案

需要修改兩個地方:

1、修改startup.bat

把call “%EXECUTABLE%” start %CMD_LINE_ARGS%修改為call “%EXECUTABLE%” run %CMD_LINE_ARGS%.   
2、修改catalina.bat
查找catalina.bat含有%ACTION%的4行內容(在文件末),在后面添加 
>> %CATALINA_HOME%\logs\catalina.out 
或者
>> %CATALINA_BASE%\logs\catalina.out
修改之后如下圖(沒有顯示完全):

 重啟tomcat后,發現在logs文件下會生成catalina.out的文件,內容為tomcat的日志。

3、不過有個弊端就是日志在命令行不輸出了。

二、應用實例

2.1、maven依賴

<!-- logback begin-->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.7</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>1.1.3</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-access</artifactId>
      <version>1.1.3</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.1.3</version>
    </dependency>
    <!-- logback end-->

2.2、完整的logback.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!-- 級別從高到低 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 TRACE 、 ALL -->
<!-- 日志輸出規則 根據當前ROOT 級別,日志輸出時,級別高於root默認的級別時 會輸出 -->
<!-- 以下 每個配置的 filter 是過濾掉輸出文件里面,會出現高級別文件,依然出現低級別的日志信息,通過filter 過濾只記錄本級別的日志 -->
<!-- scan 當此屬性設置為true時,配置文件如果發生改變,將會被重新加載,默認值為true。 -->
<!-- scanPeriod 設置監測配置文件是否有修改的時間間隔,如果沒有給出時間單位,默認單位是毫秒。當scan為true時,此屬性生效。默認的時間間隔為1分鍾。 -->
<!-- debug 當此屬性設置為true時,將打印出logback內部日志信息,實時查看logback運行狀態。默認值為false。 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
 
    <!-- 動態日志級別 -->
    <jmxConfigurator />
     
    <!-- 定義日志文件 輸出位置 -->
    <property name="log_dir" value="E:\logs" />
     
    <!-- 日志最大的歷史 30天 -->
    <property name="maxHistory" value="30" /> 
        
    <!-- ConsoleAppender 控制台輸出日志 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                <!-- 設置日志輸出格式 -->
                %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n
            </pattern>
        </encoder>
    </appender>
 
    <!-- ERROR級別日志 -->
    <!-- 滾動記錄文件,先將日志記錄到指定文件,當符合某個條件時,將日志記錄到其他文件 RollingFileAppender -->
    <appender name="ERROR"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 過濾器,只記錄WARN級別的日志 -->
        <!-- 果日志級別等於配置級別,過濾器會根據onMath 和 onMismatch接收或拒絕日志。 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">         
            <!-- 設置過濾級別 -->
            <level>ERROR</level>
            <!-- 用於配置符合過濾條件的操作 -->
            <onMatch>ACCEPT</onMatch>
            <!-- 用於配置不符合過濾條件的操作 -->
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 最常用的滾動策略,它根據時間來制定滾動策略.既負責滾動也負責出發滾動 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志輸出位置 可相對、和絕對路徑 -->
            <fileNamePattern>
            ${log_dir}/error/%d{yyyy-MM-dd}/error-log.log
            </fileNamePattern>
            <!-- 可選節點,控制保留的歸檔文件的最大數量,超出數量就刪除舊文件假設設置每個月滾動,且<maxHistory>是6, 則只保存最近6個月的文件,刪除之前的舊文件。注意,刪除舊文件是,那些為了歸檔而創建的目錄也會被刪除 -->
            <maxHistory>${maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>
                <!-- 設置日志輸出格式 -->
                %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n
            </pattern>
        </encoder>
    </appender>
 
     
    <!-- WARN級別日志 appender -->
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 過濾器,只記錄WARN級別的日志 -->
        <!-- 果日志級別等於配置級別,過濾器會根據onMath 和 onMismatch接收或拒絕日志。 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 設置過濾級別 -->
            <level>WARN</level>
            <!-- 用於配置符合過濾條件的操作 -->
            <onMatch>ACCEPT</onMatch>
            <!-- 用於配置不符合過濾條件的操作 -->
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志輸出位置 可相對、和絕對路徑 -->
            <fileNamePattern>${log_dir}/warn/%d{yyyy-MM-dd}/warn-log.log</fileNamePattern>
            <maxHistory>${maxHistory}</maxHistory> 
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>
     
     
     <!-- INFO級別日志 appender -->
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log_dir}/info/%d{yyyy-MM-dd}/info-log.log</fileNamePattern> 
            <maxHistory>${maxHistory}</maxHistory> 
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>
     
     
    <!-- DEBUG級別日志 appender -->
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log_dir}/debug/%d{yyyy-MM-dd}/debug-log.log</fileNamePattern> 
            <maxHistory>${maxHistory}</maxHistory> 
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>
     
     
    <!-- TRACE級別日志 appender -->
    <appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>TRACE</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log_dir}/trace/%d{yyyy-MM-dd}/trace-log.log</fileNamePattern> 
            <maxHistory>${maxHistory}</maxHistory> 
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>
     
     
    <!-- root級別   DEBUG -->
    <root>
        <!-- 打印info級別日志及以上級別日志 -->
        <level value="INFO" />
        <!-- 控制台輸出 -->
        <appender-ref ref="console" />
        <!-- 文件輸出 -->
        <appender-ref ref="ERROR" />
        <appender-ref ref="INFO" />
        <appender-ref ref="WARN" />
        <appender-ref ref="DEBUG" />
        <appender-ref ref="TRACE" />
    </root>
</configuration>

我這里定義的路徑為:

 <!-- 定義日志文件 輸出位置 -->
    <property name="log_dir" value="E:\logs" />

2.3 自定義異常

package com.asd.common.utils;

public class BusinessException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    public BusinessException(){
    }

    public BusinessException(String message){
        super(message);
    }
}

2.4、應用

2.4.1 main方法

public static final Logger log = LoggerFactory.getLogger(DWSHttpServletServiceImpl.class);
    public static void main(String[] args) {
        int a = 0;
        log.info("驗證logback記錄日志");
        try{
            //
            a = testException();
        } catch (BusinessException be) {
            String exceptionMessge = be.getMessage();
            //在日志里記錄自定義異常信息
            log.error(exceptionMessge);
        } catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(a);
    }

    public static int testException(){

        int a = 0;
        try {
            a = 1/0;
        }
        catch (Exception e){
            throw new BusinessException("除數不能為0");//拋出自定義異常
        }
        return a;
    }

控制台輸出:

 刪除配置文件后:

 說明配置文件是起作用的。

 我這里是直接在一個web項目里(准備金系統)創建的一個main方法進行測試的,可見logback並不需要使用容器。

在web項目中的使用方式也一樣。

三、logback等日志框架

3.1 概念

Log Java日志:(slf4j、log4j、logback、common-logging )

  • slf4j 是規范/接口
  • 日志實現:log4j、logback、common-logging

簡單地說,Logback 是一個 Java 領域的日志框架。它被認為是 Log4J 的繼承人。

Logback 主要由三個模塊組成:

  • logback-core
  • logback-classic
  • logback-access

logback-core 是其它模塊的基礎設施,其它模塊基於它構建,顯然,logback-core 提供了一些關鍵的通用機制。
logback-classic 的地位和作用等同於 Log4J,它也被認為是 Log4J 的一個改進版,並且它實現了簡單日志門面 SLF4J。
logback-access 主要作為一個與 Servlet 容器交互的模塊,比如說 tomcat 或者 jetty,提供一些與 HTTP 訪問相關的功能。


根據不同的日志系統,你可以按如下規則組織配置文件名,就能被正確加載:

  • Logback:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy
  • Log4j:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml
  • Log4j2:log4j2-spring.xml, log4j2.xml
  • JDK (Java Util Logging):logging.properties

Logback 與 Log4J

實際上,這兩個日志框架都出自同一個開發者之手,Logback 相對於 Log4J 有更多的優點:

  • 同樣的代碼路徑,Logback 執行更快
  • 更充分的測試
  • 原生實現了 SLF4J API(Log4J 還需要有一個中間轉換層)
  • 內容更豐富的文檔
  • 支持 XML 或者 Groovy 方式配置
  • 配置文件自動熱加載
  • 從 IO 錯誤中優雅恢復
  • 自動刪除日志歸檔
  • 自動壓縮日志成為歸檔文件
  • 支持 Prudent 模式,使多個 JVM 進程能記錄同一個日志文件
  • 支持配置文件中加入條件判斷來適應不同的環境
  • 更強大的過濾器
  • 支持 SiftingAppender(可篩選 Appender)
  • 異常棧信息帶有包信息

logback是java的日志開源組件,是log4j創始人寫的,性能比log4j要好,目前主要分為3個模塊。

  1. logback-core:核心代碼模塊
  2. logback-classic:log4j的一個改良版本,同時實現了slf4j的接口,這樣你如果之后要切換其他日志組件也是一件很容易的事
  3. logback-access:訪問模塊與Servlet容器集成提供通過Http來訪問日志的功能。

3.2 實現原理:slf4j是什么

slf4j只是一套標准,通俗來講,就是定義了一系列接口,它並不提供任何的具體實現。所以,我們使用這套接口進行開發,可以任意的切換底層的實現框架。比如,一開始項目用的是log4j的實現,后來發現log4j的性能太差了,想換成logback,由於我們代碼中都是面向slf4j接口的,這樣我們只要吧log4j的依賴換成logback就可以了。

3.3 總結

日志組件的使用一般都非常簡單,幾乎所有的項目中都會用到各種各樣的日志組件。但是可能就是由於太簡單了,比較少的人會願意深入系統的去了解。本人也只是對logback的配置以及一些簡單的原理做了一些了解,並沒有很深入的去看logback的具體實現。

因此,本文的內容大部分都是基於官網的文檔以及網上一些其他關於logback的博客,雖然也做了一些簡單的測試,但並不保證全部都是正確的。

參看鏈接:

logback介紹和配置詳解:https://www.jianshu.com/p/04065d8cb2a9

Logback配置使用:https://www.jianshu.com/p/638b4e2c4068

tomcat 日志詳解:https://www.cnblogs.com/operationhome/p/9680040.html

Java日志框架:slf4j作用及其實現原理:https://www.cnblogs.com/xrq730/p/8619156.html

 


免責聲明!

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



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