java⽇志框架之logback详解
⼀、logback介绍
Logback是流⾏的log4j项⽬的继承者,Logback的体系结构⾜够通⽤,可以应⽤于不同的环境。⽬前,logback分为三个模块,即logback-core、logback-classic和logback-access。
logback-core模块为其他两个模块奠定了基础。
logback-classic模块可以被同化为log4j的显著改进版本。此外,logback-classic本机实现了SLF4J API,这样您就可以随时在logback 和其他⽇志框架(如log4j或java.util)之间来回切换。
logback-access模块与Servlet容器(如Tomcat和Jetty)集成,以提供HTTP-access⽇志功能。请注意,您可以轻松地在logback-core之上构建⾃⼰的模块。
⼆、logback较log4j的优势
1. 内核重写、测试充分、初始化内存加载更⼩,这使得logback性能相⽐log4j的性能得到了较⼤的提升。
2. logback继承了log4j,并且实现了SLF4JAPI,这使得logback能够和其他⽇志框架相互替换。
3. logback官⽅⽂档⽐较丰富。
4. logback⽀持⾃动扫描重新加载配置⽂件,扫描过程⽐较快,并且安全,它并不需要额外的创建扫描线程。
5. ⾃动移除旧的⽇志⽂件,⽐如那些⽇志⽂件超过很长时间的都会都当成移除的对象,可以控制已经产⽣⽇志⽂件的最⼤数量。
6. ⾃动压缩已经打印出来的⽇志信息,压缩的这个过程是⼀个异步过程,在压缩过中并不受影响。
三、logback加载
简单的分析⼀下logback加载的过程,当我们使⽤logback-classic.jar包时,应⽤启动后,将会按照如下的顺序进⾏扫描⼀些配置⽂件。
log4j2不打印日志在系统配置⽂件System Properties中寻是否有figurationFile对应的value.
如果没有配置以上的属性值,将会在classpath中查vy⽂件。
如果不到⽂件,就继续在classpath中查l⽂件。
如果不到⽂件,就继续在classpath中继续查l⽂件。
如果不到⽂件,将⾃动调⽤ch.qos.logback.classic.BasicConfigurator在控制台输出⽇志。
加载不顺序如下图所⽰:
以上任何⼀项到后,就不会再继续向下查配置⽂件,如果都没有到这些⽂件,就会调⽤ch.qos.logback.classic.BasicConfigurator 的configure⽅法,构造出⼀个ConsoleAppender⽤于向控制台输出默认配置的⽇志信息,输出的⽇志信息为"%d{HH:mm:ss.SSS}
[%thread] %-5level %logger{36} - %msg%n"。
四、logback配置⽂件的⼀些标签及其属性介绍
configuration为l配置⽂件的根标签,主要含有⼀下⼏个属性:
scan:当scan被设置为true时,当配置⽂件发⽣改变,将会被重新加载,默认值为true。
scanPeriod:检测配置⽂件是否有修改的时间间隔,如果没有给出时间单位,默认为毫秒,只有当scan为true时,这个值才默认⽣效,默认时间间隔为1分钟。
debug:当这个值被设置为true时,将会打印出logback内部⽇志信息,实时查看logback内部运⾏的状况,默认为false。
接下来看看<logger>与<root>,他们都是同⼀种元素,都为<logger>元素,但是<root>这个标签只有⼀个level属性,因为它的name属性就是ROOT。<logger>主要有以下⼏个属性:
name:必选属性,⽤来指定此<logger>约束于哪个包或者哪个特定的类。
level:可选属性,⽤来指定打印级别,五个常⽤的打印级别从低到⾼分别为TRACE、DEBUG、INFO、WARN、ERROR,如果没有设置次级别,那么当前logger会继承上级的级别。
additivity:可选属性,⽤来指定是否向上级传递打印信息,默认为true。
接下来通过代码来测试⼏种情况:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="60 seconds" dubug="false">
<appender name="STDOUT" class="ch.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
测试代码为:
public class Main {
public static void main(String[] args) {
Logger logger = Logger(Object.class);
logger.debug("-------debug---------");
logger.info("-------info---------");
logger.warn("-------warn---------");
<("-------error---------");
}
}
打印结果如下:
从l中,分析出,当main⽅法运⾏时,root节点将⽇志级别⼤于等于debug的⽇志信息交给已经配置好的STDOUT的appender 进⾏处理,“STDOUT”将信息打印到控制台上。
再对l进⾏修改,增加⼀个<logger>:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="60 seconds" dubug="false">
<appender name="STDOUT" class="ch.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<logger name="java">
</logger>
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
运⾏⽇志信息的情况如下:
当运⾏的时候,会根据logger的name的属性值到指定包下或者特定的类。
1. 此时的logger没有指定打印级别,将继承root的打印级别,即level=DEBUG.
2. 没有配置additivity的信息,默认为true,表⽰将⽇志信息向⽗<root>传递。
3. 没有配置<appender-ref>,表⽰此logger不会打印任何信息。
再来⼀个例⼦:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds" dubug="false">
<appender name="STDOUT" class="ch.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<logger name="java" level="INFO" />
<logger name="java.lang" level="WARN">
<appender-ref ref="STDOUT"/>
</logger>
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
如果上⾯的例⼦懂了,那么再来理解⼀下这个例⼦:
因为name=java.lang的这个logger没有配置additity,那么additivity=true,默认是将打印信息传递给⽗级,即name="java"这个logger,但是由于name="java"的这个<logger>同样没有设置additivity,默认为true,这个name="java"的<logger>将打印信息继续上传,传递到<root>,将由STDOUT的appender将⽇志信息打印输出。
接下来了解<appender>,<appender>作为<configuration>的⼦节点,有两个必要的属性:name:⽤来指定<appender>的名称,<logger>与<root>标签可以通过<appender-ref ref="名称">来⽤appender打印
⽇志信息。
class:⽤来指定类的权限定名。
对于<appender>有多种,上⾯演⽰的ConsoleAppender类⽤来向控制台打印⽇志信息的。
<appender name="STDOUT" class="ch.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
另⼀种是将⽇志信息输出到⽂件中的FileAppender,其内部的节点主要有以下⼏个:
<file>表⽰写⼊的⽂件名,可以使⽤相对⽬录也可以是绝对⽬录,如果上级⽬录不存在,则可以⾃动创建。
<append>:表⽰⽂件的追加⽅式,如果为true,则表⽰直接在⽂件末尾进⾏⽂件的追加,如果是false,表⽰覆盖的追加⽅式。
<encoder>:表⽰⽇志输出的格式。
<prudent>:默认值为false,如果设置成true,表⽰⽇志安全的写⼊⽂件,效率较低。
以下是FileAppender类型的配置⽂件的情况:
<appender name="STDOUT1" class="ch.FileAppender">
<file>
E:/logback.log
</file>
<append>true</append>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
<prudent>true</prudent> <!--默认为false,如果为true,表⽰⽇志安全的写⼊⽂件-->
</appender>
还有⼀种RollingFileAppender,RollingFileAppender的作⽤是可以滚动记录⽇志⽂件,先将指定的⽇志⽂件提交到指定⽂件,当符合某个条件时再将⽇志记录到其他⽂件,当符合某个条件时再将⽇志记录到其他⽂件,RollingFileAppender配置更加灵活,因此⽤得更多。
<rollingPolicy>:指定了滚动策略,定义RollingFileAppender的⾏为,有以下两个主要节点
<fileNamePattern>:必要节点,包含⽂件名及"%d"转换符,%d可以是时间格式,⽤来设置⽇志⽂件名称
<maxHistory>:可选节点,控制保留的归档⽂件的最⼤数量,如果超出数量就删除旧⽂件,如果设置每个⽉滚动且<maxHistory>是6,则只保存最近6个⽉的⽂件
<appender name="STBOUT2" class="ch.olling.RollingFileAppender">
<rollingPolicy class="ch.olling.TimeBasedRollingPolicy">
<fileNamePattern>rolling-file-%d{yyyy-MM-dd}.log</fileNamePattern><!--⽂件名称-->
<maxHistory>6</maxHistory><!--控制⽂件的最⼤数量,如果超出数量就删除旧⽂件,改配置就表⽰保持最近6个⽉的⽂件-->
</rollingPolicy>
<encoder>
<pattern>
%-4relative [%thread] %-5level %logger{35} - %msg%n
</pattern>
</encoder>
</appender>
<encoder> 节点主要的作⽤有:
把⽇志信息转换为字节数组
把字节数组写到输出流
其内部有⼀个<pattern>节点,⽤来定义输出⽇志的格式,使⽤⽅式"%+转换符"的⽅式,如果要输出%,要⽤\%对%进⾏转义。
<filter>节点
<filter>节点是<appender>的⼀个⼦节点,表⽰在当前⽇志给出的⽇志级别再进⾏⼀次过滤,基本⽤到Filter有
ch.qos.logback.classic.filter.LevelFiler和ch.qos.logback.filter.ThreshouldFilter。
针对LevelFilter这个类,它指的是将指定级别⽇志信息打印输出。来看⼀下下⾯的这个例⼦
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论