Java日志框架(第三章)

7 篇文章 0 订阅

3.第三章Log4j

3.1Log4j简介

        Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。

        最令人感兴趣的就是,这些可以通过一个配置文件来灵活的进行配置,而不需要修改应用的代码。

3.2Log4j组件介绍

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

1.Loggers

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

      关于日志级别信息,例如DEBUG、INFO、WARN、ERROR...级别是分大小的,DEBUG<INFO<WARN<ERROR,分别用来指定这条日志信息的重要程度,Log4j输出日志的规则是:只输出级别不低于设定级别的日志信息,假如Loggers级别设定为INFO,则INFO、WARN、ERROR级别的日志信息都会输出,而级别比INFO低的DEBUG则不会输出。

2.Appenders

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

常用Appenders:

ConsoleAppender        将日志输出到控制台

FileAppender        将日志输出到文件

DailyRollingFileAppender        将日志输出到一个日志文件,并且每天输出到一个新的文件

RollingFileAppender        将日志信息输出到一个日志文件,并且指定文件的大小,当文件大小达到指定大小时,会自动把文件改名,同时产生一个新的文件

JDBCAppender        将日志信息保存到数据库中

3.Layouts

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

常用Layouts:

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

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

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

3.3日志输出格式说明

        使用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}

        %l 输出日志时间发生的位置,包括类名、线程、及在代码中的行数。如Test.main(Test.java:10)

        %F 输出日志消息产生时所在的文件名称

        %L 输出代码中行号

        %% 输出一个“%”字符

        可以在%与字符之间加上修饰符来控制最小宽度、最大宽度和文本的对其方式。如下:

        %5c 输出category名称,最小宽度是5,category<5,默认的情况下右对齐

        %-5c 输出category名称,最小宽度是5,category<5,“-”号指定左对齐,会有空格

        %.5c 输出category名称,最大宽度5,category>5,就会将左边多出的字符截掉,<5不会有空格

        %20.30c category名称<20补空格,并且右对齐,>30字符,就从左边交远销出的字符截掉

3.4案例分析

        第一步我们先创建一个maven项目,我们需要引入Log4j日志实现的依赖,并引入JUnit对日志实现进行测试

    <dependencies>
        <!-- 单元测试依赖 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!-- log4j依赖 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        
    </dependencies>

        从执行结果我们可以了解到,程序在执行过程中未发现可以的Appenders ,并且提示需要对log4j系统配置进行初始化,因此我们可以通过以下方式进行初始化信息加载

         在上一章的JUL学习中我们通过Logger的log方法找到了Level类了解到了JUL的日志级别划分,Log4j我们可以使用同样的方法找到Level类了解Log4j的日志级别划分情况,如下:

        Log4j提供了8个级别的日志输出,分别为:

        ALL        最低等级,用于打开所有级别的日志记录

        TRACE        程序推进下的追踪信息,这个追踪信息的日志级别非常低,一般情况下是不会使用的

        DEBUG        指出细粒度信息事件对调试应用程序是非常有帮助的,主要配置开发,在开发过程中打印一些重要的运行信息

        INFO        消息的粗粒度级别的运行信息

        WARN        表示警告,程序在运行过程中会出现的有可能会发生的隐形的错误

        ERROR        系统的错误信息,发生的错误不影响系统的运行

        FATAL        表示严重的错误,它是那种一旦发生,系统就不可能继续运行的严重错误,如果这种级别的错误出现了,表示程序可以停止运行了

        OFF        最高等级的级别,用户关闭所有级别的日志记录

        其中DEBUG是我们在没有设置的情况下,默认的日志级别

         接下来,我们可以对Log4j的源码进行一下分析

        首先我们可以进入到BasicConfigurator初始化配置的方法中,从中我们可以了解到如下两点信息:

        (1)创建了根节点的对象Logger root = Logger.getRootLogger();

        (2)根节点添加了ConsoleAppender对象(表示默认打印到控制台,自定义的格式化输出)

         接下来进一步分析,我们进入到Logger.getLogger(Log4jTest.class);的getLogger()方法里,我们看到LogManager.getLogger(clazz.getName());,Log4j使用了日志管理器

        我们进入LogManager,看一看日志管理器里都实现了什么

        从中我们看到很多常量信息,它们代表的是不同形式(后缀名不同)的配置文件,我们最常用的肯定是log4j.properties属性文件(语法简单,使用方便),由此我们继续分析,log4j.properties属性文件的加载时机,继续观察LogManager

         在 LogManager的static静态代码块中我们找到上图红框中的一行代码,这行代码给我们一个重要提示信息,系统默认要从当前类路径下找到log4j.properties,对于我们当前maven项目,那么理应在resources路径下,找到如何加载属性文件后,我们继续对LogManager进行分析,观察配置文件是如何读取的

         找到上图红框代码,进入方法中继续观察

        作为属性文件的加载,执行相应的properties配置对象:configurator = new PropertyConfigurator();,进入到PropertyConfigurator类中观察里面的常量信息

        这些常量信息就是我们在properties属性文件中的各种属性配置项, 其中,我们看到了如下两项信息,这两项信息是必须要进行配置的

static final String ROOT_LOGGER_PREFIX   = "log4j.rootLogger";
static final String      APPENDER_PREFIX = "log4j.appender."; 

        继续观察PropertyConfigurator类,我们找到

String prefix = APPENDER_PREFIX + appenderName;

         我们需要自定义一个appenderName,我们起名叫做console(起名字也需要见名知意,console那么我们到时候配置应该配置的就是控制台输出)log4j.appender.console,取值就是log4j中为我们提供的appender类,例如:

log4j.appender.console=org.apache.log4j.ConsoleAppender

        通过代码我们还可以发现

String layoutPrefix = prefix + ".layout";

        在appender输出的过程中,还可以同时指定输出的格式,取值就是log4j中为我们提供的Layout类,例如:

log4j.appender.console.layout=org.apache.log4j.SimpleLayout

         通过log4j.rootLogger继续在类中分析,找到configureRootCategory方法,在这个方法中执行了parseCategory方法,观察该方法找到上图红框内代码,第一个表示要以逗号的方法来切割字符串,证明了log4j.rootLogger的取值,其中可以多个值,使用逗号进行分隔,第二个表示切割后的第一个值是日志级别,继续向下分析

        红框内代码表示接下来的值,是可以通过while循环遍历得到的,第2~第n个值,就是我们配置的其他信息,这个信息就是appenderName,证明了我们配置的方式log4j.rootLogger=日志级别,appendName1,appendName2,appendName3... 表示可以同时在根节点上配置多个日志输入的途径,根据上述分析,我们就可以去除原有的配置代码,使用属性文件进行log4j的配置

         下面我们通过log4j.properties属性文件的方式进行log4j配置,首先需要在项目的resources路径下创建log4j.properties属性文件,文件中所有配置内容如下:

#配置根节点logger(日志级别为trace,输出方式为console输出到控制台)
log4j.rootLogger=trace,console

#配置自定义logger(日志级别为info,输出方式为file输出到文件)
log4j.logger.com.lsh.log4j.test=info,file

#配置apache的logger(日志级别为error,输出方式为console输出到控制台)
log4j.logger.org.apache=error,console

#配置appender输出方式 输出到控制台
log4j.appender.console=org.apache.log4j.ConsoleAppender
#配置输出的格式
log4j.appender.console.layout=org.apache.log4j.PatternLayout 
#配置自定义格式
log4j.appender.console.layout.conversionPattern=[%-10p]%r %c%t%d{yyyy-MM-dd HH:mm:ss:SSS} %m%n

#配置appender输出方式 输出到文件
log4j.appender.file=org.apache.log4j.FileAppender
#配置输出的格式
log4j.appender.file.layout=org.apache.log4j.PatternLayout 
#配置自定义格式
log4j.appender.file.layout.conversionPattern=[%-10p]%r %c%t%d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
#第一个file是自己命名的appender名称,第二个file是用来指定文件位置的属性
log4j.appender.file.file=D://my-projects//log-framework-study//logs//log4j.log
log4j.appender.file.encoding=UTF-8

#配置RollingFileAppender,按照文件大小进行拆分
log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout 
log4j.appender.rollingFile.layout.conversionPattern=[%-10p]%r %c%t%d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
#配置日志文件的输出路径
log4j.appender.rollingFile.file=D://my-projects//log-framework-study//logs//log4j.log
#配置文件编码格式
log4j.appender.rollingFile.encoding=UTF-8
#指定日志文件内容大小(文件超出1MB进行拆分)
log4j.appender.rollingFile.maxFileSize=1MB
#指定日志文件的数量(日志超出时,按照时间来进行覆盖,原则就是保留新的,覆盖旧的)
log4j.appender.rollingFile.maxBackupIndex=5

#配置DailyRollingFileAppender,按照时间来进行文件的拆分
log4j.appender.dailyRollingFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyRollingFile.layout=org.apache.log4j.PatternLayout 
log4j.appender.dailyRollingFile.layout.conversionPattern=[%-10p]%r %c%t%d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
log4j.appender.dailyRollingFile.file=D://my-projects//log-framework-study//logs//log4j.log
log4j.appender.dailyRollingFile.encoding=UTF-8
#拆分策略(默认按照天来拆分'.'yyyy-MM-dd)
log4j.appender.dailyRollingFile.datePattern='.'yyyy-MM-dd HH-mm-ss

#配置appender输出方式 输出到数据库表
log4j.appender.logDB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.logDB.layout=org.apache.log4j.PatternLayout 
log4j.appender.logDB.Driver=com.mysql.cj.jdbc.Driver
log4j.appender.logDB.URL=jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&characterEncoding=utf8
log4j.appender.logDB.User=root
log4j.appender.logDB.Password=bjaxt
log4j.appender.logDB.Sql=INSERT INTO log4j_log(name,create_time,level,category,file_name,message) values('project_log','%d{yyyy-MM-dd HH:mm:ss}','%p','%c','%F','%m')


        以上log4j的配置文件中包含了根节点logger,自定义logger以及apache的logger,并且配置了控制台输出appender,文件输出appender,按文件大小拆分appender,按时间拆分appender以及数据库表输出appender,从根节点logger与自定义logger的输出情况我们可以得出,如果根节点logger和自定义父logger配置的输出位置不同时,则取二者的并集,配置的位置都会进行输出操作,如果二者的日志级别不同,主要以自定义父logger的级别输出。

        自定义logger的应用场景
        我们之所以要自定义logger,就是为了针对不同系统信息做更加灵活的输出操作
        例如:
                我们可以在原有案例的基础之上,加上一个apache的日志输出
                #配置apache的logger
                log4j.logger.org.apache=error,console
                我们现在在配置文件中配置的logger有如下3项:
                log4j.rootLogger=trace,console
                log4j.logger.com.lsh.log4j.test=info,file
                log4j.logger.org.apache=error,console

        当前类路径com.lsh.log4j.test.Log4jTest,在配置文件中所找到的能够作用的父logger和根logger
                log4j.rootLogger=trace,console
                log4j.logger.com.lsh.log4j.test=info,file
        我们刚才配置的apache的路径和我们的com.lsh.log4j.test.Log4jTest不相符,不构成父子关系,所以没有执行apache相关的配置

        org.apache.log4j.Logger
        console在根节点中进行了配置,在apache中也进行了配置,由于输出的位置appender取的是并集,所以,既然都配置了,那么就输出了两次

3.5总结

        Log4j日志框架使用方式总结

        1.初始化LogManager,LogManager加载log4j.properties配置,添加Logger到LogManager

        2.配置根节点、自定义logger,参数为=日志级别level,输出位置appender1,输出位置appender2...

        3.配置输出方式appender,控制台输出、文件输出、按大小文件拆分输出、按时间文件拆分输出、数据库表输出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值