一、先打印几行日志试试
创建web project,引入jar包:
在classpath路径下创建logback.xml配置文件,启动后logback默认自动读取:
logback.xml配置文件的简单配置内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- logback默认开启每60秒扫描加载logback.xml配置文件的变化,下面做了修改 -->
<configuration debug="false" scan="true" scanPeriod="30 seconds">
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level : %msg%n%caller{1}</pattern>
</encoder>
</appender>
<!-- 把STDOUT添加到root Logger -->
<root>
<level value="info" />
<appender-ref ref="STDOUT"/>
</root>
</configuration>
上面配置内容解析:
(1)<configuration>标签是整个配置文件的根标签
(2)可以配置多个<appender>日志输出位置,每个appender内部可以配置一个<encoder>,encoder的class属性不写默认就是PatternLayoutEncoder,encoder内部可以配置一个<pattern>,pattern用于规定日志的格式。
(3)pattern格式:具体可以参考logback的PatternLayout 参数解析
简单说下,一般是appender包含encoder包含layout包含pattern,由于PatternLayout太过常用,所以直接提供个PatternLayoutEncoder,这个encoder内部已经封装了layout,所以它可以直接装配pattern。
下面是使用slf4j的API通过logback打印日志:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogbackTest {
private static Logger logger = LoggerFactory.getLogger(LogbackTest.class);
public void infoMethod() {
logger.info("this is a info message");
}
public void errorMethod() {
try {
int i=0;
i=1/i;
} catch (Exception e) {
logger.error("attention, error!",e);
}
}
}
输出结果如下:
2019-03-31 15:50:41 INFO : this is a info message
Caller+0 at com.lwr.LogbackTest.infoMethod(LogbackTest.java:10)
2019-03-31 15:50:41 INFO : this is a info message
Caller+0 at com.lwr.LogbackTest.infoMethod(LogbackTest.java:10)
2019-03-31 15:50:41 ERROR : attention, error!
Caller+0 at com.lwr.LogbackTest.errorMethod(LogbackTest.java:17)
java.lang.ArithmeticException: / by zero
at com.lwr.LogbackTest.errorMethod(LogbackTest.java:15)
at com.lwr.TestServlet.doGet(TestServlet.java:22)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
。。。
二、logback的日志级别
1、logback会根据包的路径依次创建logger对象,整个路径下来形成一条logger父子链。
比如创建logger1(com.lwr.Test)的同时会创建logger2(com.lwr)和logger3(com),同时logger3是logger2的父logger,logger2是logger1的父logger,以此递推,而logger(root)是最顶层的logger也就是logger3的父logger。
2、logger的有效级别。比如有三个logger(和级别):爷爷com.logger(warn)>父com.lwr.logger(debug)>子com.lwr.Test.logger(无),那么“子logger”的有效级别是依次往上找到的第一logger级别,也就是父logger的debug级别,低于该级别的日志将无法通过“子logger”打印出来。而爷爷logger的warn级别传递到父logger就被置换了,只影响自己的级别。
3、控制日志打印级别
(1)根据package包路径控制哪个包路径下的所有logger打印什么级别以上的日志:
在logback.xml文件的<configuration>标签下添加<logger>标签:
<!-- com.lwr包路径下的所有logger打印的信息都是warn级别以上 -->
<!-- 除非com.lwr包路径下的路径又设置了自己的级别,或者logger设置了自己的级别 -->
<logger name="com.lwr" level="warn"/>
(2)在(1)中,限定死了warn以下日志都不会打印。实际上更加常用的是根据输出位置来决定日志打印的级别,比如控制台可以打印info级别,而error.log只需要error级别的日志,而不管error日志来自于哪个类。
所以,通常把级别的控制权给到输出目的地appender,在logback中可以通过给appender添加一个过滤器Filter,专门用于级别的判断过滤。级别过滤器又主要分两种:
第一种,门槛级别过滤器ThresholdFilter,如下:
<appender>
<!-- 只要日志级别高于等于门槛级别,此过滤器就放行 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
...
</appender>
源码判断过程如下:
public FilterReply decide(ILoggingEvent event) {
//
if (event.getLevel().isGreaterOrEqual(level)) {
return FilterReply.NEUTRAL;//NEUTRAL表示走下一个过滤器,如果没有则最终通行了
} else {
return FilterReply.DENY;//如果下面还有过滤器也不再判断,直接不通行
}
}
第二种,相应等级级别过滤器LevelFilter,xml中配置如下:
<appender>
<!-- 当日志级别等于设定的level,返回onMatch,否则返回onMismatch -->
<!-- onMatch也可以设定为DENY拒绝;match结果可以对应以下三个动作之一:
accept:整个过滤链不再向下走,直接返回通过操作
deny:整个过滤链不再向下走,直接返回不通过操作
neutral:不返回操作,继续沿过滤链走下一个过滤器-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
...
</appender>
源码判断过程如下:
public FilterReply decide(ILoggingEvent event) {
//
if (event.getLevel().equals(level)) {
return onMatch;
} else {
return onMismatch;
}
}
LevelFilter可以指定比如我只要warn级别的日志。
三、按天以及按文件大小的策略滚动日志文件
logback支持按时间段(月、天、小时等)分割日志文件,同时支持按每个文件大小来分割日志文件。
1、按天生成日志文件
logback.xml配置文件加上一个输出到file的appender,通过include标签包含进来:
logback.xml:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="5 seconds">
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level : %msg%n%caller{1}</pattern>
</encoder>
</appender>
<!-- 引入输出到文件的appender-->
<include resource="timeBasedFileAppender.xml"/>
<!-- 日志输出级别 -->
<root>
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
timeBasedFileAppender.xml:
<included>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件存放在tomcat/logs目录中 -->
<file>${CATALINA_BASE}\logs\console.log</file>
<!-- TimeBasedRollingPolicy是按时间生成日志文件策略的类 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- yyyy-MM-dd格式表示按天滚动日志文件 -->
<FileNamePattern>${CATALINA_BASE}\logs\console.%d{yyyy-MM-dd}.log</FileNamePattern>
<!-- 保存30份日志文件 -->
<maxHistory>30</maxHistory>
<!-- 总日志文件大小不超过3GB -->
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level : %msg%n%caller{1}</pattern>
</encoder>
</appender>
</included>
根据上面配置之后,调用打印日志方法后,会在tomcat/logs目录中生成每天的console.log日志文件并保存日志信息。
2、按文件大小分割日志文件
把logback.xml中的<include resource="timeBasedFileAppender.xml"/>
改为<include resource="sizeBasedFileAppender.xml"/>
sizeBasedFileAppender.xml内容如下:
<included>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${CATALINA_BASE}\logs\console.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${CATALINA_BASE}\logs\console%i.log</fileNamePattern>
<!-- %i参数的取值从1到3,表示只保存3份历史日志文件 -->
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<!-- 因为测试,每个文件10KB大小 -->
<maxFileSize>10KB</maxFileSize>
</triggeringPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level : %msg%n%caller{1}</pattern>
</encoder>
</appender>
</included>
最终只有三份历史日志文件和一份当前的日志文件:
3、按时间和大小一起来分割日志文件
在logback.xml文件中有如下配置:
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- SizeAndTimeBasedRollingPolicy是同时结合时间和文件大小来滚动的策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--注意!!标注aux的%d参数只做使用,与按天滚动策略无任何关系,这里按天分目录保存-->
<FileNamePattern>${CATALINA_BASE}\logs\%d{yyyy-MM-dd, aux}\console.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<maxFileSize>10KB</maxFileSize>
<!--貌似是保存近4天的日志文件-->
<maxHistory>4</maxHistory>
<!--所有文件总共2GB封顶-->
<totalSizeCap>2GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level : %msg%n%caller{1}</pattern>
</encoder>
</appender>
启动之后,自动按天,同时按文件大小分割日志文件,注意到\logs%d{yyyy-MM-dd, aux}代表每天生成一个目录存放当天的所有日志文件。