【日志技术】8 - 2 Logback

§8-2 Logback

8-2.2 Logback

本小节使用介绍 Logback 的日志使用方法。

8-2.2.1 配置 Logback

Logback 主要分为三个技术模块:

  • logback-core:该模块为其他两个模块提供基础代码,必需项;
  • logback-classic:完整实现了 SLF4j API 的模块;
  • logback-access:与 Tomcat 和 Jetty 等 Servlet 容器集成,以提供 HTTP 访问日志功能。

本节使用的是前两个模块,使用时,除了要导入上述两个 jar 包外,还需要导入 slf4j 的 jar 包。

导入包后,需要在项目源码根目录(src)下放入 Logback 的核心配置文件。Logback 会依次读取以下类型配置文件:

  • logback.groovy
  • logback-test.xml
  • logback.xml

若上述文件不存在,则会采用默认配置。配置文件表明了日志输出需要使用到 Logback 当中的组件,组件之间的关系为:

  • Logger:日志记录器。将它关联到应用对应的 Context 上后,主要用于存放日志对象,也可定义日志类型、级别。
  • Appender:日志追加器。用于指定日志输出目的地,可以是控制台、文件、数据库等。
  • Layout:日志布局。负责将事件转换为字符串,格式化日志信息输出。Logback 将 Layout 对象封装在 Encoder 中。

因此,当不确定 appender 标签内应当存储哪些标签时,可以查看对应类的源码以确定。

配置文件应当放入项目源码根目录(src)下,配置文件 logback.xml 内容:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <!-- 配置集中管理的属性,可在此处修改属性值 -->
    <!-- 格式:${name) -->
    <property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread]: %msg%n"/>
    <property name="html_pattern" value="%-5level%d{yyyy-MM-dd HH:mm:ss.SSS}%c%M%L%thread%msg"/>
    <property name="log_dir" value="C:/code logs/Logback logs"/>

    <!-- 日志输出到控制台 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 输出流对象:默认 System.out,可改为 System.err -->
        <target>System.err</target>

        <!-- 日志消息格式配置 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!-- 格式化输出:
			%d 表示日期,%thread 表示线程名,%-5level 级别从左显示 5 个字符宽度
 			%msg 或 $m:日志信息,%n:换行符,%c:类的完整名称
			%M:方法,%L:行号
 			-->
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>

    <!-- 日志输出到文件 -->
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <!-- 日志输出路径 -->
        <file>${log_dir}/com-zebt-data.log</file>

        <!-- 日志消息格式配置 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>>${pattern}</pattern>
            <charset>utf-8</charset>
        </encoder>
    </appender>

    <!-- 日志输出为 HTML 文件 -->
    <appender name="HTML" class="ch.qos.logback.core.FileAppender">
        <!-- 文件保存路径 -->
        <file>${log_dir}/com-zebt-data.html</file>

        <!-- 需要自定义编码器 -->
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <!-- 声明使用的布局 -->
            <layout class="ch.qos.logback.classic.html.HTMLLayout">
                <!-- 声明日志格式 -->
                <pattern>${html_pattern}</pattern>
            </layout>
        </encoder>
    </appender>

    <!-- 日志拆分和归档压缩的 Appender -->
    <appender name="ROLL" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 文件保存路径 -->
        <file>${log_dir}/com-zebt-data-roll.log</file>

        <!-- 日志消息格式配置 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>

        <!-- 指定拆分规则 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 按时间和压缩格式声明拆分的文件名 -->
            <fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-hh-ss}.log%i.gz</fileNamePattern>

            <!-- 最大文件大小 -->
            <maxFileSize>1MB</maxFileSize>
        </rollingPolicy>

        <!-- 可选:日志过滤 -->
        <!-- LevelFilter:级别过滤 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>                 <!-- 日志级别 -->
            <onMatch>ACCEPT</onMatch>           <!-- 不低于此级别日志的过滤行为 -->
            <onMismatch>DENY</onMismatch>       <!-- 低于此级别日志的过滤行为 -->
        </filter>
    </appender>

    <!-- 使用异步日志提高并发性能 -->
    <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 指定某个具体的 Appender -->
        <appender-ref ref="HTML"/>
        <appender-ref ref="ROLL"/>
    </appender>

    <!-- level:设置打印级别,大小写无关,有 TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默认为 DEBUG-->
    <!-- root 可包含零个或多个 <appender-ref> 元素,标识这个输出位置会被本日志级别控制 -->
    <!-- 日志级别从低到高分别为:TRACE < DEBUG < INFO < WARN < ERROR -->
    <!-- 输出时,会将不低于所设计别的日志输出到指定位置 -->
    <root level="ALL">
        <appender-ref ref="ASYNC"/>
    </root>

    <!-- 使用自定义 Logger 灵活控制日志输出的目的地 -->
    <!--
        name:指定项目中哪个包下的日志由此 Logger 控制
        level:指定控制的日志级别
        additivity:自定义 Logger 是否继承 rootLogger(即 root 标签下的 Appender)
    -->
    <logger name="com.logging" level="info" additivity="false">
        <!-- additivity 设为 false,该自定义 Logger 独立控制指定包下的日志输出 -->
        <appender-ref ref="CONSOLE"/>
    </logger>
</configuration>

8-2.2.2 Logback 输出日志

在代码中获取日志的对象

public static final Logger LOGGER = LoggerFactory.getLogger("Class 对象");

和 JUL 一样,日志记录器也需要一个唯一标识名唯一标识该记录器,通常为所在类的 Class 对象。这样,日志记录器所记录的日志就会携带对应的全限定名信息,有利于在查看日志时,定位产生日志的类与包。

此外,同一个全限定名所返回的日志记录器实例都是唯一的(单例模式),这种设计保证了资源的有效管理,并允许为每个命名的日志记录器共享和维护相同的日志级别、输出目的地等配置信息。

示例

package com.logging;

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

import java.util.Date;

public class LoggerDemo {
    // 获取日志对象
    public static final Logger LOGGER = LoggerFactory.getLogger("LoggerDemo.class");
    public static void main(String[] args) {
        // 性能测试
        for (int i = 0; i < 10000; i++) {
            LOGGER.error("error");		// 输出 ERROR 级别日志
            LOGGER.warn("warn");		// 输出 WARN 级别日志
            LOGGER.info("info");		// 输出 INFO 级别日志
            LOGGER.debug("debug");		// 输出 DEBUG 级别日志
            LOGGER.trace("trace");		// 输出 TRACE 级别日志
        }
    }
}

注意

  1. 确保导入的包是正确的包,而不是 JUL 的 Logger 所在包;
  2. 日志对象应当是公共的静态常量,以供程序可在任意地方调用;
posted @ 2024-01-31 17:42  Zebt  阅读(18)  评论(0)    收藏  举报