Java教程

Java 日志框架

本文主要是介绍Java 日志框架,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • 一、日志框架
    • 1、简介
      • (1)日志门面和日志实现
      • (2)SLF4j的使用
      • (3)SLF4j
    • 2、日志的级别
      • (1)测试
      • (2)日志的配置
    • 3、指定配置
    • 4、日志框架统一
  • 二、log4j2 xml文件配置[^1]
    • 1. Appenders和Loggers简介
      • (1) 根节点Configuration有两个属性:status和monitorinterval,有两个子节点:Appenders(进行日志输出)和Loggers(表明可以定义多个Appender和Logger).
      • (2) Appenders节点,常见的有三种子节点:Console、RollingFile、File.
    • 2. Loggers
      • (1) Loggers节点,常见的有两种:Root和Logger.
    • 3. 日志level
      • (1) 关于日志level.
    • 4. Filters标签
    • 5. 异步日志
    • 6. RollingFile
      • 1. 简介
      • 2. TriggeringPolicy
        • 2.1 SizeBasedTriggeringPolicy
        • 2. 2 TimeBasedTriggeringPolicy
        • 2. 3 CompositeTriggeringPolicy
      • 3. DefaultRolloverStrategy
      • 4. DeleteAction
  • 参考

一、日志框架

1、简介

(1)日志门面和日志实现

  • 日志门面(抽象层):SL4j(Simlple Logging Facade for Java)、JCL、jboss-logging等
  • 日志实现(实现):Log4j、JUL、Log4j2、Logback
  • springboot:底层是spring框架,spring框架默认是用JCL;springboot选用的是SLF4j和logback

(2)SLF4j的使用

  • 以后开发的时候,日志记录方法的调用,不应该直接调用日志的实现类,而是调用抽象层里面的方法
  • 需要给系统里面导入slf4j的jar和logback的实现jar

(3)SLF4j

可以实现统一使用SLF4j,即使依赖于其它框架

  • 将系统中其他日志框架先排除出去
  • 用中间包来替换原有的日志框架
  • 导入slf4j的其他实现

2、日志的级别

(1)测试

  • 日志的级别,由低到高,是trace、debug、info、warn、error
  • 日志的级别可以调整,日志就只会在这个级别以后的高级别生效
  • 调整日志级别后,日志就只会在这个级别以后的高级别生效,上例中默认是debug级别的

(2)日志的配置

logging.level.com.zhb=warn
//在当前磁盘(项目存在的磁盘)创建目录和文件
logging.file.path=s/123.log

3、指定配置

给类路径下放上每个日志框架自己的配置文件即可;SpringBoot就不使用他默认配置的了

Logging SystemCustomization
Logbacklogback-spring.xml, logback-spring.groovy, logback.xml or logback.groovy
Log4j2log4j2-spring.xml or log4j2.xml
JDK (Java Util Logging)logging.properties

logback.xml:直接就被日志框架识别了;

4、日志框架统一

统一slf4j,使用其他包替换原有日志框架,替换的意思就是,例如要把原框架里面对Commons-logging的依赖排除掉

但如果我现在用的Spring框架缺少Commons-logging就运行不起来了,Spring底层记录日志就需要Commons-logging,那怎么办呢?就用jcl-over-slf4j.jar替换这个包,Spring要用的类这个替换包例子还是有的,就不会报错了

但新的包实现怎么办呢?新的包调入slf4j,而slf4j又调到真正的实现中,其他框架不同日志框架同理替换

其他组合方式也是如此

如何让系统中所有的日志都统一到slf4j:

  • 将系统中其他日志框架先排除去;
  • 用中间包来替换原有的日志框架
  • 我们导入slf4j其他的实现

二、log4j2 xml文件配置1

1. Appenders和Loggers简介

(1) 根节点Configuration有两个属性:status和monitorinterval,有两个子节点:Appenders(进行日志输出)和Loggers(表明可以定义多个Appender和Logger).

简单说Appender就是一个管道,定义了日志内容的去向(保存位置)。

简单说Logger就是一个路由器,指定类、包中的日志信息流向哪个管道,以及控制他们的流量(日志级别)

  • status用来指定log4j本身的打印日志的级别.
  • monitorinterval用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s.

(2) Appenders节点,常见的有三种子节点:Console、RollingFile、File.

  • Console

    节点用来定义输出到控制台的Appender.

    • name:指定Appender的名字.

    • target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT.

    • PatternLayout:输出格式,不设置默认为:%m%n.

  • File

    节点用来定义输出到指定位置的文件的Appender.

    • name:指定Appender的名字.

    • fileName:指定输出日志的目的文件带全路径的文件名.

    • PatternLayout:输出格式,不设置默认为:%m%n.

  • RollingFile

    节点用来定义超过指定大小自动删除旧的创建新的的Appender.

    • name:指定Appender的名字.
    • fileName:指定输出日志的目的文件带全路径的文件名.
    • PatternLayout:输出格式,不设置默认为:%m%n.
    • filePattern:指定新建日志文件的名称格式.
    • Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志.
    • TimeBasedTriggeringPolicy:Policies子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am…而不是7am.
    • SizeBasedTriggeringPolicy:Policies子节点,基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小.
    • DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)。

2. Loggers

(1) Loggers节点,常见的有两种:Root和Logger.

  • Root

    节点用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出

    • level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.

    • AppenderRef:Root的子节点,用来指定该日志输出到哪个Appender.

  • Logger

    节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。

    • level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
    • name:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点.
    • AppenderRef:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root.如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity="false"只在自定义的Appender中进行输出。

3. 日志level

(1) 关于日志level.

​ 共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.

    • All:最低等级的,用于打开所有日志记录.
    • Trace:是追踪,就是程序推进以下,你就可以写个trace输出,所以trace应该会特别多,不过没关系,我们可以设置最低日志级别不让他输出.
    • Debug:指出细粒度信息事件对调试应用程序是非常有帮助的.
    • Info:消息在粗粒度级别上突出强调应用程序的运行过程.
    • Warn:输出警告及warn以下级别的日志.
    • Error:输出错误信息日志.
    • Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志.
    • OFF:最高等级的,用于关闭所有日志记录.

​ 程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少。

4. Filters标签

            <Filters>
                <ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL"/>
                <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
  • onMatch=“ACCEPT” 表示匹配该级别及以上
  • onMatch=“DENY” 表示不匹配该级别及以上
  • onMatch=“NEUTRAL” 表示该级别及以上的,由下一个filter处理,如果当前是最后一个,则表示匹配该级别及以上
  • onMismatch=“ACCEPT” 表示匹配该级别以下
  • onMismatch=“NEUTRAL” 表示该级别及以下的,由下一个filter处理,如果当前是最后一个,则不匹配该级别以下的
  • onMismatch=“DENY” 表示不匹配该级别以下的

5. 异步日志

异步日志的实现思路是在单独的线程中执行I/O操作,在调用形如Logger.log的API时,能够更快的返回到主程序中,以提高应用程序的性能。Log4j 2在异步日志领域,做了很多优化和改进。而我们只需要在配置文件中,做一个简单的配置,就可以获得异步日志记录的功能特性。

Log4j 2设计了两种异步日志:

  1. Async Appender。内部使用的一个队列(ArrayBlockingQueue)和一个后台线程,日志先存入队列,后台线程从队列中取出日志。阻塞队列容易受到锁竞争的影响,当更多线程同时记录时性能可能会变差。
  2. Async Logger。内部使用的是LMAX Disruptor技术,Disruptor是一个无锁的线程间通信库,它不是一个队列,不需要排队,从而产生更高的吞吐量和更低的延迟。

我们采用第二种,也是官方推荐的Async Logger的方式,进行异步日志的配置。

6. RollingFile

1. 简介

RollingFileAppender是Log4j2中的一种能够实现日志文件滚动更新(rollover)的Appender。

rollover的意思是当满足一定条件(如文件达到了指定的大小,达到了指定的时间)后,就重命名原日志文件进行归档,并生成新的日志文件用于log写入。如果还设置了一定时间内允许归档的日志文件的最大数量,将对过旧的日志文件进行删除操作。

RollingFile实现日志文件滚动更新,依赖于TriggeringPolicy和RolloverStrategy。

其中,TriggeringPolicy为触发策略,其决定了何时触发日志文件的rollover,即When。

RolloverStrategy为滚动更新策略,其决定了当触发了日志文件的rollover时,如何进行文件的rollover,即How。

Log4j2提供了默认的rollover策略DefaultRolloverStrategy。

下面通过一个log4j2.xml文件配置简单了解RollingFile的配置。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{yyyy-MM-dd HH}.log">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <TimeBasedTriggeringPolicy interval="1"/>
        <SizeBasedTriggeringPolicy size="250MB"/>
      </Policies>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>

上述配置文件中配置了一个RollingFile,日志写入logs/app.log文件中,每经过1小时或者当文件大小到达250M时,按照app-2017-08-01 12.log的格式对app.log进行重命名并归档,并生成新的文件用于写入log。

其中,fileName指定日志文件的位置和文件名称(如果文件或文件所在的目录不存在,会创建文件。)

filePattern指定触发rollover时,文件的重命名规则。filePattern中可以指定类似于SimpleDateFormat中的date/time pattern,如yyyy-MM-dd HH,或者%i指定一个整数计数器。

TimeBasedTriggeringPolicy指定了基于时间的触发策略。
SizeBasedTriggeringPolicy指定了基于文件大小的触发策略。

2. TriggeringPolicy

RollingFile的触发rollover的策略有CronTriggeringPolicy(Cron表达式触发)、OnStartupTriggeringPolicy(JVM启动时触发)、SizeBasedTriggeringPolicy(基于文件大小)、TimeBasedTriggeringPolicy(基于时间)、CompositeTriggeringPolicy(多个触发策略的混合,如同时基于文件大小和时间)。

其中,SizeBasedTriggeringPolicy(基于日志文件大小)、TimeBasedTriggeringPolicy(基于时间)或同时基于文件大小和时间的混合触发策略最常用。

2.1 SizeBasedTriggeringPolicy

SizeBasedTriggeringPolicy规定了当日志文件达到了指定的size时,触发rollover操作。size参数可以用KB、MB、GB等做后缀来指定具体的字节数,如20MB。

<SizeBasedTriggeringPolicy size="250MB"/>

2. 2 TimeBasedTriggeringPolicy

TimeBasedTriggeringPolicy规定了当日志文件名中的date/time pattern不再符合filePattern中的date/time pattern时,触发rollover操作。

比如,filePattern指定文件重命名规则为app-%d{yyyy-MM-dd HH}.log,文件名为app-2017-08-25 11.log,当时间达到2017年8月25日中午12点(2017-08-25 12),将触发rollover操作。

参数名 类型 描述
intervalinteger

此参数需要与filePattern结合使用,规定了触发rollover的频率,默认值为1。假设interval为4,若filePattern的date/time pattern的最小时间粒度为小时(如yyyy-MM-dd HH),则每4小时触发一次rollover;若filePattern的date/time pattern的最小时间粒度为分钟(如yyyy-MM-dd HH-mm),则每4分钟触发一次rollover。

modulateboolean

指明是否对interval进行调节,默认为false。若modulate为true,会以0为开始对interval进行偏移计算。例如,最小时间粒度为小时,当前为3:00,interval为4,则以后触发rollover的时间依次为4:00,8:00,12:00,16:00,...。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{yyyy-MM-dd HH}-%i.log">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="250 MB"/>
      </Policies>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>

上述配置文件中,filePattern中yyyy-MM-dd HH最小时间粒度为小时,TimeBasedTriggeringPolicy中interval使用默认值1,将每1小时触发一次rollover。

若将filePattern改为filePattern=“logs/app-%d{yyyy-MM-dd HH-mm}-%i.log”,yyyy-MM-dd HH-mm最小时间粒度为分钟,将每1分钟触发一次rollover。

2. 3 CompositeTriggeringPolicy

将多个TriggeringPolicy放到Policies中表示使用复合策略

<Policies>
    <TimeBasedTriggeringPolicy />
    <SizeBasedTriggeringPolicy size="250 MB"/>
</Policies>

如上,同时使用了TimeBasedTriggeringPolicy、SizeBasedTriggeringPolicy,有一个条件满足,就会触发rollover。

3. DefaultRolloverStrategy

DefaultRolloverStrategy指定了当触发rollover时的默认策略。

DefaultRolloverStrategy是Log4j2提供的默认的rollover策略,即使在log4j2.xml中没有显式指明,也相当于为RollingFile配置下添加了如下语句。DefaultRolloverStrategy默认的max为7。

<DefaultRolloverStrategy max="7"/>

max参数指定了计数器的最大值。一旦计数器达到了最大值,过旧的文件将被删除。

注意:不要认为max参数是需要保留的日志文件的最大数目。

max参数是与filePattern中的计数器%i配合起作用的,其具体作用方式与filePattern的配置密切相关。

  1. 如果filePattern中仅含有date/time pattern,每次rollover时,将用当前的日期和时间替换文件中的日期格式对文件进行重命名。max参数将不起作用。

如,filePattern=“logs/app-%d{yyyy-MM-dd}.log”

  1. 如果filePattern中仅含有整数计数器(即%i),每次rollover时,文件重命名时的计数器将每次加1(初始值为1),若达到max的值,将删除旧的文件。

如,filePattern=“logs/app-%i.log”

  1. 如果filePattern中既含有date/time pattern,又含有%i,每次rollover时,计数器将每次加1,若达到max的值,将删除旧的文件,直到data/time pattern不再符合,被替换为当前的日期和时间,计数器再从1开始。

如,filePattern=“logs/app-%d{yyyy-MM-dd HH-mm}-%i.log”

总结:

1.max参数是与filePattern中的计数器%i配合起作用的,若filePattern为filePattern=“logs/app-%d{yyyy-MM-dd}.log”>,由于没有设置%i计数器,max参数将不起作用。

2.max参数不是需要保留的文件的最大个数。如情况3,日志文件date/time pattern不再符合filePattern时,计算器将被重置为1,日志总个数超过了max的指定值。

可认为max参数规定了一定时间范围内归档文件的最大个数。

4. DeleteAction

DefaultRolloverStrategy制定了默认的rollover策略,通过max参数可控制一定时间范围内归档的日志文件的最大个数。

Log4j 2.5 引入了DeleteAction,使用户可以自己控制删除哪些文件,而不仅仅是通过DefaultRolloverStrategy的默认策略。

注意:通过DeleteAction可以删除任何文件,而不仅仅像DefaultRolloverStrategy那样,删除最旧的文件,所以使用的时候需要谨慎!

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Properties>
    <Property name="baseDir">logs</Property>
  </Properties>
  <Appenders>
    <RollingFile name="RollingFile" fileName="${baseDir}/app.log"
          filePattern="${baseDir}/app-%d{yyyy-MM-dd}.log.gz">
      <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
      <CronTriggeringPolicy schedule="0 0 0 * * ?"/>
      <DefaultRolloverStrategy>
        <Delete basePath="${baseDir}" maxDepth="2">
          <IfFileName glob="*/app-*.log.gz" />
          <IfLastModified age="60d" />
        </Delete>
      </DefaultRolloverStrategy>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>

上述配置文件中,Delete部分便是配置DeleteAction的删除策略,指定了当触发rollover时,删除baseDir文件夹或其子文件下面的文件名符合app-*.log.gz且距离最后的修改日期超过60天的文件。

其中,basePath指定了扫描开始路径,为baseDir文件夹。maxDepth指定了目录扫描深度,为2表示扫描baseDir文件夹及其子文件夹。

IfFileName指定了文件名需满足的条件,IfLastModified指定了文件修改时间需要满足的条件。

DeleteAction常用参数如下:

参数名类型描述
basePathString必填。目录扫描开始路径。
maxDepthint扫描的最大目录深度。0表示basePath指定的文件自身。Integer.MAX_VALUE表示扫描所有的目录层。默认值为1,表示仅扫描basePath下的文件。
testModeboolean如果为true,实际的文件不会被删除,删除文件的信息会打印到log4j2的INFO级别的log中。可使用此参数测试配置是否符合预测。默认为false。
pathConditionsPathCondition[]删除文件的过滤条件,满足指定条件的文件将会被删除,可以指定一个或多个。
如果指定多个pathCondition,需要同时满足。Conditions可以嵌套,当嵌套配置时,只有当满足了外部的contion时,才能对内部的condition进行判断。
如果Conditions不是嵌套的,会可能以任意顺序进行判断。
Conditions也可以通过使用IfAll,IfAny,IfNot等类似于AND,OR,NOT的condition,实现复杂的condition。
1. IfFileName-判断文件的文件名是否满足正则表达式或glob表达式
2.IfLastModified-判断文件的修改时间是否早于指定的duration
3.IfAccumulatedFileCount-判断在遍历文件树的时候,文件个数是否超过了指定值
4.IfAccumulatedFileSize-判断在遍历文件树的时候,文件的总大小是否超过了指定值
5.IfAll-判断嵌套的condition是否都满足
6.IfAny-判断嵌套的condition是否有一个满足
7.IfNot-判断嵌套的condition是否不满足

参考


  1. 参考 ↩︎

这篇关于Java 日志框架的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!