Java日志框架概述

486 阅读10分钟

Java日志框架概述

现有日志框架:

JUL、logback、log4j、log4j2、 JCL、slf4j

日志门面 :JCL、slf4j

日志实现 JUL、logback、log4j、log4j2

日志框架出现的历史顺序: log4j -->JUL-->JCL--> slf4j --> logback --> log4j2

JUL(Java Util logging)

JUL全称Java util Logging是java原生的日志框架,使用时不需要另外引用第三方类库,相对其他日志框 架使用方便,学习简单,能够在小型应用中灵活使用。

JUL组件

image-20220208155622204

  • Logger:被称为记录器,应用程序通过获取Logger对象,抵用其API来发布日志信息。Logger通常被认为是访问日志系统的入口程序。
  • Handler:处理器,每个Logger都会关联一个或者是一组Handler,Logger会将日志交给关联的Handler去做处理,由Handler负责将日志做记录。Handler具体实现了日志的输出位置,比如可以输出到控制台或者是文件中等等。
  • Filter:过滤器,根据需要定制哪些信息会被记录,哪些信息会被略过。
  • Formatter:格式化组件,它负责对日志中的数据和信息进行转换和格式化,所以它决定了我们输出日志最终的形式。
  • Level:日志的on'n级别,每条日志消息都有一个关联的级别。我们根据输出级别的设置,用来展现最终所呈现的日志信息。

总结

用户使用Logger来进行日志记录,Logger持有若干个Handler,日志的输出操作是由Handler完成的。 在Handler在输出日志前,会经过Filter的过滤,判断哪些日志级别过滤放行哪些拦截,Handler会将日 志内容输出到指定位置(日志文件、控制台等)。Handler在输出日志时会使用Layout,将输出内容进 行排版。

JUL Demo

// 测试日志实现
public class JULTest {
@Test
public void testQuick() throws Exception {
// 1.创建日志记录器对象
Logger logger = Logger.getLogger("com.itheima.log.JULTest");
// 2.日志记录输出
logger.info("hello jul");
logger.log(Level.INFO, "info msg");
String name = "jack";
Integer age = 18;
logger.log(Level.INFO, "用户信息:{0},{1}", new Object[]{name, age});
}
}

// 日志级别
public void testLogLevel() throws Exception {
// 1.获取日志对象
Logger logger = Logger.getLogger("com.itheima.log.QuickTest");
// 2.日志记录输出
logger.severe("severe");
logger.warning("warning");
logger.info("info");
logger.config("cofnig");
logger.fine("fine");
logger.finer("finer");
logger.finest("finest");
}

Log4j

​ Log4j主要由oggers(日志记录器)、Appenders(输出控制器)和Layout(日志格式化器)组成。其中Loggers控制日志的输出以及输出级别;Appenders指定日志的输出方式(输出到控制台、文件等);Layout控制日志信息的输出格式。

Log4j组件介绍

Loggers

​ 日志记录器,负责收集处理日志记录,实例的命名就是类的全限定名,如com.bjpowernode.log4j.XX,Logger的名字大小写敏感,其命名有继承机制:例如:name为com.bjpowernode.log4j的logger会继承 name为com.bjpowernode。Log4J中有一个特殊的logger叫做“root”,他是所有logger的根,也就意味着其他所有的logger都会直接或者间接地继承自root。root logger可以用Logger.getRootLogger)方法获取。自log4j1.2版以来,Logger类已经取代了Category类。对于熟悉早期版本的log4j的人来说,Logger类可以被视为Category类的别名。

Appenders (相当于JUL的Handler)

记录日志以及定义日志的级别仅仅是Log4j的基本功能,Log4j日志系统还提供许多强大的功能,比如允许把日志输出到不同的地方,如控制台(Console)、文件(Files)等,可以根据天数或者文件大小产生新的文件,可以以流的形式发送到其它地方等等。 常用Appenders:

  • ConsoleAppender 将日志输出到控制台
  • FileAppender 将日志输出到文件中
  • DailyRollingFileAppender 将日志输出到一个日志文件,并且每天输出到一个新的文件
  • RollingFileAppender将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大小达到指定尺寸时,会自动把文件改名,同时产生一个新的文件
  • JDBCAppender 把日志信息保存到数据库中
#指定日志的输出级别与输出端
log4j.rootLogger=INFO,Console
# 控制台输出配置
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
# 文件输出配置
log4j.appender.A = org.apache.log4j.DailyRollingFileAppender
#指定日志的输出路径
log4j.appender.A.File = D:/log.txt
log4j.appender.A.Append = true
#使用自定义日志格式化器
log4j.appender.A.layout = org.apache.log4j.PatternLayout
#指定日志的输出格式
log4j.appender.A.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [%t:%r] -
[%p] %m%n
#指定日志的文件编码
log4j.appender.A.encoding=UTF-8
#mysql
log4j.appender.logDB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.logDB.layout=org.apache.log4j.PatternLayout
log4j.appender.logDB.Driver=com.mysql.jdbc.Driver
log4j.appender.logDB.URL=jdbc:mysql://localhost:3306/test
log4j.appender.logDB.User=root
log4j.appender.logDB.Password=root
log4j.appender.logDB.Sql=INSERT INTO
log(project_name,create_date,level,category,file_name,thread_name,line,all_categ
ory,message) values('itcast','%d{yyyy-MM-dd
HH:mm:ss}','%p','%c','%F','%t','%L','%l','%m')

Layout(相当于JUL的Formater)

有时用户希望根据自己的喜好格式化自己的日志输出,Log4j可以在Appenders的后面附加Layouts来完成这个功能。Layouts提供四种日志输出样式,如根据HTML样式、自由指定样式、包含日志级别与信息的样式和包含日志时间、线程、类别等信息的样式。 常用Layouts:

HTMLLayout 格式化日志输出为HTML表格形式

SimpleLayout 简单的日志输出格式化,打印的日志格式如默认INFO级别的消息

PatternLayout 最强大的格式化期,可以根据自定义格式输出日志,如果没有指定转换格式,就是用默认的转换格式

日志级别

关于日志级别信息,例如DEBUG、INFO、WARN、ERROR...级别是分大小的,

* 每个Logger都被了一个日志级别(log level),用来控制日志信息的输出。日志级别从高到低分为:
fatal 指出每个严重的错误事件将会导致应用程序的退出。
error 指出虽然发生错误事件,但仍然不影响系统的继续运行。
warn 表明会出现潜在的错误情形。
info 一般和在粗粒度级别上,强调应用程序的运行全程。
debug 一般用于细粒度级别上,对调试应用程序非常有帮助。
trace 是程序追踪,可以用于输出程序运行中的变量,显示执行的流程。
* 还有两个特殊的级别:
OFF 可用来关闭日志记录。
ALL 启用所有消息的日志记录。

日志格式输出说明

使用PatternLayout可以自定义格式输出,是我们最常用的方式这种格式化输出采用类似于C语言的printf函数的打印格式格式化日志信息,具体的占位符及其含义如下:

%m输出代码中指定的日志信息
%p输出优洗级,及DEBUG、INFO等
%n换行符(Windows平台的换行符为"\n",Unix平台为"\n")
%r输出自应用启动到输出该log信息耗费的毫秒数
%c输出打印语句所属的类的全名
%t输出产生该日志的线程全名
%d输出服务器当前时间,默认为ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日HH:mm:ss}

Log4j Demo

  1. 引入依赖

    <dependency>
    	<groupId>log4j</groupId>
    	<artifactId>log4j</artifactId>
    	<version>1.2.17</version>
    </dependency>
    
  2. 使用log4j

    public class Log4jTest {
    @Test
    public void testQuick() throws Exception {
    // 初始化系统配置,不需要配置文件
    BasicConfigurator.configure();
    // 创建日志记录器对象
    Logger logger = Logger.getLogger(Log4jTest.class);
    // 日志记录输出
    logger.info("hello log4j");
    // 日志级别
    logger.fatal("fatal"); // 严重错误,一般会造成系统崩溃和终止运行
    logger.error("error"); // 错误信息,但不会影响系统运行
    logger.warn("warn"); // 警告信息,可能会发生问题
    logger.info("info"); // 程序运行信息,数据库的连接、网络、IO操作等
    logger.debug("debug"); // 调试信息,一般在开发阶段使用,记录程序的变量、参数等
    logger.trace("trace"); // 追踪信息,记录程序的所有流程信息
    }
    }
    

JCL(日志门面)

全称为Jakarta Commons Logging,是Apache提供的一个通用日志API。 它是为 "所有的Java日志实现"提供一个统一的接口,它自身也提供一个日志的实现,但是功能非常常弱 (SimpleLog)。所以一般不会单独使用它。他允许开发人员使用不同的具体日志实现工具: Log4j, Jdk 自带的日志(JUL) JCL 有两个基本的抽象类:Log(基本记录器)和LogFactory(负责创建Log实例)。

JCL存在的必要性

image-20220208165254162

SLF4J

SLF4J简介

简单日志门面(Simple Logging Facade For Java)SLF4主要是为了给Java日志访问提供一套标准、规范的API框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如log4j和logback等。当然slf4j自己也提供了功能较为简单的实现,但是一般很少用到。 对于一般的Java项目而言,日志框架会选择slf4j-api作为门面,配上具体的实现框架(log4j、logback等),中间使用桥接器完成桥接。所以我们可以得出SLF4J最重要的两个功能就是对于日志框架的绑定以及日志框架的桥接。

SLF4J桥接技术

通常,我们依赖的某些组件依赖于SLF4J以外的日志API。我们可能还假设这些组件在不久的将来不会切换到SLF4J。为了处理这种情况,SLF4J附带了几个桥接模块,这些模块会将对log4j,JCL和java.util.loggingAPI的调用重定向为行为,就好像是对SLF4JAPI进行的操作一样。

Logback

Logback是由log4j创始人设计的又一个开源日志组件。 Logback当前分成三个模块:logback-core,logback-classic和logback-access。

  • logback-core是其它两个模块的基础模块。
  • logback-classic是log4j的一个改良版本。此外logback-clasic完整实现SLF4JAPI。使你可以很方便地更换成其它日志系统如log4j或JDK14Logging。
  • logback-access 访问模块与Servlet容器集成提供通过Http来访问日志的功能。

Logback的组件

Logger:日志的记录器,主要用于存放日志对象,也可以定义日志类型、级别。 Appender: 用于指定日志输出的目的地,目的地可以是控制台、文件、数据库等等。 Layout:负责把事件转换成字符串,格式化的日志信息的输出。在Logback中Layout对象被封装在encoder中。也就是说我们未来使用 的encoder 其实就是Layoute

Logback配置文件

Logback提供了3种配置文件 logback.groovy logback-test.xml logback.xml 如果都不存在则采用默认的配置

Logback输出格式

日志输出格式:

%-10level级别案例为设置10个字符,左对齐
%d{yyyy-MM-dd HH:mm:ss.SSS}日期
%c当前类全限定名
%M当前执行日志的方法
%L行号
%thread 线程名称
%m或者%msg信息息
%n换行

LogbackDemo

  1. 引入依赖

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.25</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
    </dependency>
    
  2. Logback配置

    <?xml version="1.0" encoding="UTF-8" ?>
    <configuration>
    
        <!--日志输出格式-->
        <property name="pattern2" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c %M %L %thread %m%n"></property>
        <property name="colorPattern"
                  value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/>
        <property name="filePattern"
                  value="%d{yyyy-MM-dd HH:mm:ss} |%-5level |%thread |%file:%line |%logger |%msg%n"/>
    
    
        <!--日志文件输出路径-->
        <property name="logDir" value="D:\\code\\Java\\deviceOnline\\log"></property>
    
        <!--输出到文件中-->
    <!--    <appender name="fileAppender" class="ch.qos.logback.core.FileAppender" >
    
            <file>${logDir}/deviceOnline.log</file>
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                <pattern>${pattern}</pattern>
            </encoder>
        </appender>-->
    
    
        <!--切割日志文件 -->
        <appender name="rollingFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                <pattern>${filePattern}</pattern>
            </encoder>
            <file>${logDir}/deviceOnline.log</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                <fileNamePattern>${logDir}/deviceOnline.%d{yyyy-MM-dd}.log%i.gz</fileNamePattern>
                <maxFileSize>2MB</maxFileSize>
            </rollingPolicy>
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>INFO</level>
                <!--高于level中设置的级别,则打印日志-->
                <onMatch>ACCEPT</onMatch>
                <!--低于level中设置的级别,则不打印日志-->
                <onMismatch>DENY</onMismatch>
            </filter>
        </appender>
    
    
        <!--配置控制台的过滤器-->
        <appender name="consoleFilterAppender" class="ch.qos.logback.core.ConsoleAppender">
            <target>System.err</target>
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                <pattern>${colorPattern}</pattern>
            </encoder>
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>INFO</level>
                <!--高于level中设置的级别,则打印日志-->
                <onMatch>ACCEPT</onMatch>
                <!--低于level中设置的级别,则打印日志-->
                <onMismatch>DENY</onMismatch>
            </filter>
        </appender>
    
    
        <root level="ALL">
            <appender-ref ref="rollingFileAppender"></appender-ref>
            <appender-ref ref="consoleFilterAppender"></appender-ref>
        </root>
    
    
    
    </configuration>
    
  3. 使用Logback

    //定义日志对象
    public final static Logger LOGGER =
    LoggerFactory.getLogger(LogBackTest.class);
    @Test
    public void testSlf4j(){
    //打印日志信息
    LOGGER.error("error");
    LOGGER.warn("warn");
    LOGGER.info("info");
    LOGGER.debug("debug");
    LOGGER.trace("trace");
      }
    

    Log4j

    Apache Log4j 2是对Log4j的升级版,参考了logback的一些优秀的设计,并且修复了一些问题,因此带 来了一些重大的提升,主要有:

    • 异常处理,在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异 常处理机制。
    • 性能提升, log4j2相较于log4j 和logback都具有很明显的性能提升,后面会有官方测试的数据。
    • 自动重载配置,参考了logback的设计,当然会提供自动刷新参数配置,最实用的就是我们在生产 上可以动态的修改日志的级别而不需要重启应用。
    • 无垃圾机制,log4j2在大部分情况下,都可以使用其设计的一套无垃圾机制,避免频繁的日志收集 导致的jvm gc。