Logback

Logback

1,什么是Logback

Logback是由log4j(先)创始人设计的又一个开源日志组件。

日志:程序记录在某个地方的一些信息。

2,为什么要记录日志

开发的程序上线之后一般要做两个事情:

  • 用来跟踪定位程序的运行状态
  • 用来快速的定位bug

日志框架有很多,比如log4j,log4j2等,logback是springboot默认自带的日志框架。以后使用springboot时会经常使用到。

3,Logback的主要组成部分

logback主要由三个模块组成:

  • logback-access:logback-access模块与Servlet容器(如tomcat)集成,以提供http访问日志功能。可以使用这个模块来替换tomcat的访问日志。
  • logback-classic:log4j的一个改良版本,同时它提供了完整的slf4j API,可以很方便的更换成其他日志系统如log4j。
  • logback-core:其他两个模块的基础模块

ps:slf4j可以称之为门面日志接口,它提供了一套标准的日志功能的接口,没有任何的实现。而log4j和logback都是属于slf4j的具体实现。

4,Logback主要标签

logback主要用到的标签有三个:

  • logger:日志记录器,用于存放日志对象,定义日志的类型和级别等。
  • appender:用于指定日志输出的目的地,也就是日志存放的媒介,这个媒介可以是控制台,可以是文件,也可以是远程套接字服务器。
  • layout:用来格式化日志信息的输出

对于日志框架来说,日志是有级别的,logback的日志级别:

trace(追踪) < debug(调试) < info(记录信息) < warn(警告) < error(错误)

在记录日志时,一般需要用到一个Logger类的对象,然后可以调用:logger.debug("xxx")、logger.info("xxx")...等方法。

如果记录的日志级别是info的话,info是大于debug和trace的,这个时候调用debug和trace方法记录的日志是无法显示的,而调用warn和error是可以显示的。

一般情况下,只需要记录debug、info和error的日志就行了,而这三个级别的日志需要放在不同的文件中。

5,Logback的具体配置

1,首先引入对应的包:

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.30</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>

上面是直接在对应工程里引入。

如果有父工程的话可以先在父工程引入:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

然后在子工程里具体的引入,这个时候就不需要写版本号和有效范围了:

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
    </dependency>
</dependencies>

2,创建logback的配置文件,文件名就叫做logback.xml:

首先,我们的logback的配置文件可以在我们运行java程序的时候就指定好:

java -Dlogback.configurationFile=xxxxx/xxxx.xml

但是如果没有指定,那么logback会自动去加载classpath下面logback.grovvy文件。如果这个文件找不到,那么它会自动的加载classpath下面的logback-test.xml文件。如果文件也没有,那会自动加载classpath下面的logback.xml文件,所以就直接取名logback.xml。

对应的配置文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!--
    configuration:logback的根标签
    scan="true":表示配置文件发生了改变会自动加载
    scanPeriod="60 seconds":检测配置文件修改的时间间隔,默认单位是毫秒
    debug:这个属性如果为TRUE,表示会打印出logback自身实时的运行信息。因为logback自身运行是非常稳定的,所以这里就设置为FALSE,相信logback就好了
-->
<configuration
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="logback.xsd"
        scan="true"
        scanPeriod="60 seconds"
        debug="false">

    <!--定义一些参数常量-->
    <property name="log.filepath" value="E:\\softdata\\logback\\logTest"/><!--定义日志的输出位置(文件)-->
    <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{100} %msg%n"/><!--定义日志展示的格式-->


    <!--定义日志输出的媒介-->
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"><!--定义控制台输出,class指定具体输出位置要使用的类-->
        <!--appender是负责统一调度日志的输出工作,具体的日志格式化和输出工作会交给encoder-->
        <encoder>
            <pattern>${log.pattern}</pattern><!--定义日志输出的格式-->
        </encoder>
    </appender>


    <!--定义不同级别的日志的输出的媒介-->
    <!--定义debug级别的日志输出-->
    <appender name="debugAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--RollingFileAppender:表示滚动日志,可以按天或月来生成不同的日志文件-->
        <file>${log.filepath}/debug.log</file><!--文件存放路径-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--设置按每分钟的方式生成文件,如果文件结尾是.gz,那么logback会自动把日志文件压缩,压缩前后的日志文件大小差异还是很大的-->
            <fileNamePattern>${log.filepath}/debug-%d{yyyy-MM-dd_HH_mm}.log.gz</fileNamePattern><!-- 要设置按天的方式生成文件的话,把_HH_mm删掉就好   -->
            <maxHistory>31</maxHistory><!--设置文件最大保存的历史数据-->
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern><!--定义日志输出的格式-->
        </encoder>
        <!--debugAppender只需要记录debug级别的日志,所以对于其他级别的日志直接过滤,要设置一个过滤器-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch><!--对于debug级别日志,同意记录-->
            <onMismatch>DENY</onMismatch><!--对于其他级别日志,直接略过-->
        </filter>
    </appender>


    <!--定义info级别的日志输出-->
    <appender name="infoAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--RollingFileAppender:表示滚动日志,可以按天或月来生成不同的日志文件-->
        <file>${log.filepath}/info.log</file><!--文件存放路径-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--设置按每分钟的方式生成文件,如果文件结尾是.gz,那么logback会自动把日志文件压缩,压缩前后的日志文件大小差异还是很大的-->
            <fileNamePattern>${log.filepath}/info-%d{yyyy-MM-dd_HH_mm}.log.gz</fileNamePattern>
            <maxHistory>31</maxHistory><!--设置文件最大保存的历史数据-->
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern><!--定义日志输出的格式-->
        </encoder>
        <!--debugAppender只需要记录info级别的日志,所以对于其他级别的日志直接过滤,要设置一个过滤器-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch><!--对于info级别日志,同意记录-->
            <onMismatch>DENY</onMismatch><!--对于其他级别日志,直接略过-->
        </filter>
    </appender>


    <!--定义error级别的日志输出-->
    <appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--RollingFileAppender:表示滚动日志,可以按天或月来生成不同的日志文件-->
        <file>${log.filepath}/error.log</file><!--文件存放路径-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--设置按每分钟的方式生成文件,如果文件结尾是.gz,那么logback会自动把日志文件压缩,压缩前后的日志文件大小差异还是很大的-->
            <fileNamePattern>${log.filepath}/error-%d{yyyy-MM-dd_HH_mm}.log.gz</fileNamePattern>
            <maxHistory>31</maxHistory><!--设置文件最大保存的历史数据-->
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern><!--定义日志输出的格式-->
        </encoder>
        <!--debugAppender只需要记录error级别的日志,所以对于其他级别的日志直接过滤,要设置一个过滤器-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch><!--对于error级别日志,同意记录-->
            <onMismatch>DENY</onMismatch><!--对于其他级别日志,直接略过-->
        </filter>
    </appender>


    <!--配置根日志记录器,所有包下面的日志都会被记录-->
    <root level="DEBUG">
        <appender-ref ref="consoleAppender"/>
    </root>


    <!--配置代码的日志记录器-->
    <logger name="com.xl.logback.TestLog" level="DEBUG" additivity="true">
        <!-- name="com.xl.logback":表示对应包里的类里面(包含子包)的代码产生的日志才会被下面的记录器记录,否则不会
             additivity="true":表示自定义的记录器日志输出
             level="DEBUG" :日志级别,如果不设置,则自动继承根记录器
         -->
        <appender-ref ref="debugAppender"/>
        <appender-ref ref="infoAppender"/>
        <appender-ref ref="errorAppender"/>
    </logger>

</configuration>

以上。

6,Logback程序中使用

package com.xl.logback;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Random;

public class TestLog {
    public static void main(String[] args) throws InterruptedException {
        Logger logger = LoggerFactory.getLogger(TestLog.class);
        Random r = new Random();
        while (true) {
            int a = r.nextInt();
            if (a % 5 == 0) {
                logger.trace("trace: num is " + a);
            } else if (a %5 == 1) {
                logger.debug("debug: num is " + a);
            } else if (a %5 == 2) {
                logger.info("info: num is " + a);
            } else if (a %5 == 3) {
                logger.warn("warn: num is " + a);
            } else if (a %4 == 3) {
                logger.error("error: num is " + a);
            }
            Thread.sleep(100);
        }
    }
}

使用比较简单,重点还是在配置部分。

7,root标签日志级别设置无效问题

1,首先把root的级别设置为info:

<root level="INFO"> <appender-ref ref="consoleAppender"/> </root>

2,然后在程序里面全部用debug来记录日志:

logger.debug("debug a = "+a);

此时,按理来说是不应该再输出的。但是结果:

Logback

还是全部输出了...

这种情况是因为底层的日志记录器会自动的向上层抛出日志。比如说我自定义了一个记录器,级别是debug,它会自动抛给上层root记录器,而不去管root的级别。

这个时候,如果不想要debug的日志,可以直接在consoleAppender里配置一个filter:

<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"><!--定义控制台输出,class指定具体输出位置要使用的类-->
    <!--appender是负责统一调度日志的输出工作,具体的日志格式化和输出工作会交给encoder-->
    <encoder>
        <pattern>${log.pattern}</pattern><!--定义日志输出的格式-->
    </encoder>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>INFO</level>
    </filter>
</appender>

Logback

上一篇:Nginx 的优化


下一篇:Windows Service 访问远程共享权限设置