赞
踩
我们简单分析一下logback加载过程,当我们使用logback-classic.jar时,应用启动,那么logback会按照如下顺序进行扫描:
在classpath下寻找是否有logback.groovy(即logback支持groovy与xml两种配置方式)
在classpath下寻找是否有logback-test.xml
在classpath下寻找是否有logback.xml
以上任何一项找到了,就不进行后续扫描
当所有以上四项都找不到的情况下,logback会构造一个ConsoleAppender用于向控制台输出日志,默认日志输出格式为"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"。
configuration
root
logger
property
appender
layout
rollingPolicy
Pattern
fileNamePattern
maxFileSize
maxHistory
totalSizeCap
一般有三个属性,分别是scan、scanPeriod和debug。
scan:是否自动加载,默认为true。
scanPeriod:监听修改时间间隔,默认一分钟。
debug: 是否查看logback运行状态,默认true。
那么我们要使用这个的话,可以进行如下配置:
<configuration scan="true" scanPeriod="30 seconds" debug="true">
...
</configuration>
<logger:用来设置某一个包或者具体某一个类的日志打印级别、以及指定<appender。<logger可以包含零个或者多个<appender-ref元素,标识这个appender将会添加到这个logger。<logger仅有一个name属性、一个可选的level属性和一个可选的additivity属性:
name:用来指定受此logger约束的某一个包或者具体的某一个类
level:用来设置打印级别,五个常用打印级别从低至高依次为TRACE、DEBUG、INFO、WARN、ERROR,如果未设置此级别,那么当前logger会继承上级的级别
additivity:是否向上级logger传递打印信息,没有配置additivity,那么additivity=true,表示此的打印信息向父级传递,也就是该logger控制的日志如果自己不输出(没有配置<appender-ref 就是输出日志),交由父目录root输出。如果自己有输出,logger控制的输出部分,root就不会输出。
没有配置<appender-ref,表示此<logger不会打印出任何信息
<root也是<logger元素,但是它是根logger,只有一个level属性,因为它的name就是ROOT
例如:
private static Logger LOG2 = LoggerFactory.getLogger("oneInfo");
他们的用法如下:
<logger name="oneInfo" level="DEBUG" additivity="false">
<appender-ref ref="ONE_INFO" />
</logger>
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE" />
</root>
或者name指定一个包
<logger name="com.yss.henghe.platform.analy.dao" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
一般用来定义变量值。有两个属性name和value。类似Java中Map的key和value。
name: 变量的名称
value: 变量的值
用法如下:
<property name="LOG_HOME" value="logs/pcm"/>
说明:value指定的文件路径,会在项目同级目录下自动生成,无需手动创建。
解决方案:需要通过springProperty标签来引用:
<springProperty scope="context" name="elkLoggerUrl" source="elk.logger.destination"/>
<appender name="logstash"
class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>${elkLoggerUrl}</destination>
name: 自定义名称。
class:对应自定义名称的全路径名,就是使用何种方式进行日志的输出。
这个非常重要,也可以说是logback的核心吧。简单的用法如下:
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
</appender>
说明:定义一个STDOUT名称,在控制台进行输出。
简单的用法如下:
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
说明:Pattern里面格式的%d表示输出的时间格式,%thread 表示输出的线程名称,%-5level 表示字符宽度,%msg 表示输出的信息,%n表示换行。
rollingPolicy: 决定日志滚动行为,一般用于日志切割。
fileNamePattern:必要的节点,一般用于指定日志的文件的路径以及生成格式。
maxFileSize:单个日志文件最大值,达到之后就进行切割。
maxHistory:日志文件最多保留的天数,也就是过期时间。
totalSizeCap : 日志文件总体的最大值,达到之后就不再产生日志。
简单的用法如下:
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
<maxFileSize>10MB</maxFileSize>
<maxHistory>31</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
</appender>
说明:这段的配置意义是,每天产生一个日志文件,如果超出了10M,日志就进行切割,并且在日志文件名称上加一,日志文件最多保持31天,日志文件总共最大为10G。
这里需要注意日志文件中的%d、%i是不可或缺的,如果是换成小时,定时删除是不起作用的,这也是logback的一个bug
ConsoleAppender的作用是将日志输出到控制台,配置示例为:
1 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
2 <encoder>
3 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
4 </encoder>
5 </appender>
FileAppender的作用是将日志写到文件中,配置示例为:
1 <appender name="FILE" class="ch.qos.logback.core.FileAppender">
2 <file>D:/123.log</file>
3 <append>true</append>
4 <encoder>
5 <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
6 </encoder>
7 </appender>
它的几个节点为:
<file>表示写入的文件名,可以使相对目录也可以是绝对目录,如果上级目录不存在则自动创建
<appender>如果为true表示日志被追加到文件结尾,如果是false表示清空文件
<encoder>表示输出格式,后面说
<prudent>如果为true表示日志会被安全地写入文件,即使其他的FileAppender也在向此文件做写入操作,效率低,默认为false
RollingFileAppender的作用是滚动记录文件,先将日志记录到指定文件,当符合某个条件时再将日志记录到其他文件,RollingFileAppender配置比较灵活,因此使用得更多,示例为:
1 <appender name="ROLLING-FILE-1" class="ch.qos.logback.core.rolling.RollingFileAppender">
2 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
3 <fileNamePattern>rolling-file-%d{yyyy-MM-dd}.log</fileNamePattern>
4 <maxHistory>30</maxHistory>
5 </rollingPolicy>
6 <encoder>
7 <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
8 </encoder>
9 </appender>
<fileNamePattern>,必要节点,包含文件名及"%d"转换符,"%d"可以包含一个Java.text.SimpleDateFormat指定的时间格式,如%d{yyyy-MM},如果直接使用%d那么格式为yyyy-MM-dd。RollingFileAppender的file子节点可有可无,通过设置file可以为活动文件和归档文件指定不同的位置
<maxHistory>,可选节点,控制保留的归档文件的最大数量,如果超出数量就删除旧文件,假设设置每个月滚动且<maxHistory>是6,则只保存最近6个月的文件
日志通常来说都以文件形式记录到磁盘,例如使用,这样的话一次写日志就会发生一次磁盘IO,这对于性能是一种损耗,因此更多的,对于每次请求必打的日志(例如请求日志,记录请求API、参数、请求时间),我们会采取异步写日志的方式而不让此次写日志发生磁盘IO,阻塞线程从而造成不必要的性能损耗。
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <configuration scan="false" scanPeriod="60000" debug="false"> 3 4 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 5 <encoder> 6 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> 7 </encoder> 8 </appender> 9 10 <appender name="ROLLING-FILE-1" class="ch.qos.logback.core.rolling.RollingFileAppender"> 11 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 12 <fileNamePattern>D:/rolling-file-%d{yyyy-MM-dd}.log</fileNamePattern> 13 <maxHistory>30</maxHistory> 14 </rollingPolicy> 15 <encoder> 16 <pattern>%-4relative [%thread] %-5level %lo{35} - %msg%n</pattern> 17 </encoder> 18 </appender> 19 20 <!-- 异步输出 --> 21 <appender name ="ASYNC" class= "ch.qos.logback.classic.AsyncAppender"> 22 <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --> 23 <discardingThreshold>0</discardingThreshold> 24 <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --> 25 <queueSize>256</queueSize> 26 <!-- 添加附加的appender,最多只能添加一个 --> 27 <appender-ref ref ="ROLLING-FILE-1"/> 28 </appender> 29 30 <logger name="java" additivity="false" /> 31 <logger name="java.lang" level="DEBUG"> 32 <appender-ref ref="ASYNC" /> 33 </logger> 34 35 <root level="INFO"> 36 <appender-ref ref="STDOUT" /> 37 </root> 38 39 </configuration>
discardingThreshold,假如等于20则表示,表示当还剩20%容量时,将丢弃TRACE、DEBUG、INFO级别的Event,只保留WARN与ERROR级别的Event,为了保留所有的events,可以将这个值设置为0,默认值为queueSize/5
queueSize比较好理解,BlockingQueue的最大容量,默认为256
includeCallerData表示是否提取调用者数据,这个值被设置为true的代价是相当昂贵的,为了提升性能,默认当event被加入BlockingQueue时,event关联的调用者数据不会被提取,只有线程名这些比较简单的数据。通常不去设置。
appender-ref表示AsyncAppender使用哪个具体的<appender>进行日志输出
最后来看一下,是的一个子节点,表示在当前给到的日志级别下再进行一次过滤,最基本的Filter有ch.qos.logback.classic.filter.LevelFilter和ch.qos.logback.classic.filter.ThresholdFilter。
首先看一下LevelFilter:
1 <configuration scan="false" scanPeriod="60000" debug="false"> 2 3 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 4 <encoder> 5 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> 6 </encoder> 7 <filter class="ch.qos.logback.classic.filter.LevelFilter"> 8 <level>WARN</level> 9 <onMatch>ACCEPT</onMatch> 10 <onMismatch>DENY</onMismatch> 11 </filter> 12 </appender> 13 14 <logger name="java" additivity="false" /> 15 <logger name="java.lang" level="DEBUG"> 16 <appender-ref ref="STDOUT" /> 17 </logger> 18 19 <root level="INFO"> 20 <appender-ref ref="STDOUT" /> 21 </root> 22 23 </configuration>
看到尽管<logger配置的是DEBUG,但是输出的只有warn,因为在<filter中对匹配到WARN级别时做了ACCEPT(接受),对未匹配到WARN级别时做了DENY(拒绝),只能打印出WARN级别的日志。
ThresholdFilter
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <configuration scan="false" scanPeriod="60000" debug="false"> 3 4 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 5 <encoder> 6 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> 7 </encoder> 8 <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 9 <level>INFO</level> 10 </filter> 11 </appender> 12 13 <logger name="java" additivity="false" /> 14 <logger name="java.lang" level="DEBUG"> 15 <appender-ref ref="STDOUT" /> 16 </logger> 17 18 <root level="INFO"> 19 <appender-ref ref="STDOUT" /> 20 </root> 21 22 </configuration>
ThresholdFilter的策略是,会将日志级别小于的全部进行过滤,因此虽然指定了DEBUG级别,但是只有INFO及以上级别的才能被打印出来。
logback.xml 使用需要依赖三个 jar 包,分别是 slf4j-api,logback-core,logback-classic。spring boot工程不需要引入依赖,就可以直接使用。
<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> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency>
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="30 seconds" debug="true"> <property name="LOG_HOME" value="logs/pcm"/> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level - %msg%n </Pattern> </layout> </appender> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>${LOG_HOME}/mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern> <maxFileSize>10MB</maxFileSize> <maxHistory>31</maxHistory> <totalSizeCap>10GB</totalSizeCap> </rollingPolicy> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level - %msg%n </Pattern> </layout> </appender> <appender name="ONE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>${LOG_HOME}/oneInfo/%d{yyyy-MM-dd}/oneInfo.%i.txt</fileNamePattern> <maxFileSize>10MB</maxFileSize> <maxHistory>31</maxHistory> <totalSizeCap>10GB</totalSizeCap> </rollingPolicy> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level - %msg%n </Pattern> </layout> </appender> <appender name="TWO_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>${LOG_HOME}/twoInfo/%d{yyyy-MM-dd}/twoInfo.%i.txt</fileNamePattern> <maxFileSize>10MB</maxFileSize> <maxHistory>31</maxHistory> <totalSizeCap>10GB</totalSizeCap> </rollingPolicy> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level - %msg%n </Pattern> </layout> </appender> <logger name="oneInfo" level="DEBUG" additivity="false"> <appender-ref ref="ONE_INFO" /> </logger> <logger name="twoInfo" level="WARN" additivity="true"> <appender-ref ref="TWO_INFO" /> </logger> <root level="INFO"> <appender-ref ref="STDOUT"/> <appender-ref ref="FILE" /> </root> </configuration>
import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * Title: logbackTest * Description: * logback日志测试 * Version:1.0.0 * @author pancm * @date 2018年1月24日 */ public class logbackTest { private static Logger LOG = LoggerFactory.getLogger(logbackTest.class); private static Logger LOG2 = LoggerFactory.getLogger("oneInfo"); private static Logger LOG3 = LoggerFactory.getLogger("twoInfo"); public static void main(String[] args) { test(); } private static void test(){ LOG.debug("主程序的debug"); LOG.info("主程序的info"); LOG.warn("主程序的warn"); LOG.error("主程序的error"); LOG2.debug("oneInfo的debug"); LOG2.info("oneInfo的info"); LOG2.warn("oneInfo的warn"); LOG2.error("oneInfo的error"); LOG3.debug("twoInfo的debug"); LOG3.info("twoInfo的info"); LOG3.warn("twoInfo的warn"); LOG3.error("twoInfo的error"); }
参考链接:
https://www.cnblogs.com/xrq730/p/8628945.html
https://blog.csdn.net/xintonghanchuang/article/details/91348257
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。