一、logback、log4j、slf4j
slf4j
(Simple logging Facade for Java) 简单日志门面,日志系统的实现进行了具体的抽象化,只提供了统一的日志使用接口,没有任何日志实现,只有一个jar包(slf4j-api.jar)。log4j
和logback
是具体的日志框架。这两个日志框是同一个作者开发,后者性能更高。 logbak直接实现slf4j接口,性能更高。springboot默认日志框架为logback
二、logback
logback
是由log4j
创始人设计的另一个开源日志组件。
官方网站: http://logback.qos.ch。
1、logback 模块
logback-core
:其它两个模块的基础模块logback-classic
:它是log4j的一个改良版本,同时它完整实现了slf4j API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logginglogback-access
:访问模块与Servlet容器集成提供通过Http来访问日志的功能
2、日志级别
共有:trace、debug、info、warn、error
5个级别。
排序为: TRACE < DEBUG < INFO < WARN < ERROR。
如果设置为WARN,则低于WARN的信息都不会输出
3、springboot加载步骤
(1)LogBack
在类路径下优先查找 logback.groovy
的文件。如果 logback.groovy
没有找到,则继续查找 logback-test.xml
文件。
(2)若 logback-test.xml
文件没有找到,则会类路径下查找 logback.xml
或 logback-spring.xml
文件。
(3) 如果没有任何配置文件,LogBack
使用 BasicConfigurator
启动默认配置,配置会将日志输出控制台上不会写进日志文件,它提供了默认的最基础的日志功能。
如果配置文件 logback-test.xml
和 logback.xml
都不存在,那么 logback
默认地会调用BasicConfigurator
,创建一个最小化配置。最小化配置由一个关联到根 logger
的 ConsoleAppender
组成。输出用模式为 %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
的 PatternLayoutEncoder
进行格式化。root logger
默认级别是 DEBUG。
logback-spring.xml
logback-spring.xml
只有在Spring应用程序运行的时候才生效,即带有@SpringBootApplication
注解的类启动的时候才会生效。logback-spring.xml
使用方法基本和 logback.xml
等同,但是2者的加载顺序是不一样的。
logback.xml—>application.properties—>logback-spring.xml
logback.xml
加载早于 application.properties
,所以如果你在 logback.xml
使用了变量时,而恰好这个变量是写在 application.properties
时,那么就会获取不到,只要改成 logback-spring.xml
就可以解决。
使用方式
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTest {
private static Logger logger = LoggerFactory.getLogger(MyTest.class);
@Test
public void test() {
logger.info("日志");
}
}
4、常用配置如下
(1)根节点 <configuration>
根节点 <configuration>
,包含下面三个属性:
scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!--其他配置省略-->
</configuration>
(2)<contextName>
上下文名称
<configuration>
的子节点 <contextName>
:用来设置上下文名称,每个logger都关联到logger上下文,默认上下文名称为default。但可以使用 <contextName>
设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改。
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>myAppName</contextName>
<!--其他配置省略-->
</configuration>
(3)<property>
定义变量
<configuration>
的子节点 <property>
:用来定义变量值,它有两个属性name和value,通过<property>
定义的值会被插入到 logger上下文中,可以使“${}”来使用变量。
name: 变量的名称
value: 变量定义的值
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<property name="APP_Name" value="myAppName" />
<contextName>${APP_Name}</contextName>
<!--其他配置省略-->
</configuration>
(4)<timestamp>
获取时间戳
<configuration>
子节点 <timestamp>
:获取时间戳字符串,他有两个属性key和datePattern
key: 标识此
<timestamp>
的名字;datePattern: 设置将当前时间(解析配置文件的时间)转换为字符串的模式,遵循java.txt.SimpleDateFormat的格式。
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>
<contextName>${bySecond}</contextName>
<!-- 其他配置省略-->
</configuration>
(5)<conversionRule>
自定义字符
自定义字符类,继承自 ClassicConverter,重写 convert ,返回值即为自定字符串
public class MySampleConverter extends ClassicConverter {
long start = System.nanoTime();
@Override
public String convert(ILoggingEvent event) {
long nowInNanos = System.nanoTime();
return Long.toString(nowInNanos-start);
}
}
在 <conversionRule>
标签中定义自定义字符串
- 属性 conversionWord:变量名,后续引用时使用
- 属性 converterClass:上面的自定义字符的类
<configuration>
<conversionRule conversionWord="nanos"
converterClass="chapters.layouts.MySampleConverter" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-6nanos [%thread] - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>
当需要在日志记录中添加自定义文本时,仅支持在
<pattern>
中添加ip或其他自定义的字段,不支持在目录或文件名<fileNamePattern>
中使用。如果想在文件目录或文件名中添加自定义字段,可以引入springboot中的参数
<springProperty scope="context" name="LOG_HOME" source="logPath"/>
如果需要使用springboot配置中不存在的参数,可以在logback-spring.xml中加入
<define>
<define name="initIp" class="com.test.util.InitIpUtil"/>
<springProperty scope="context" name="port" source="server.port" />
...
<fileNamePattern>
/data/logs/java-${initIp}-${port}
</fileNamePattern>
@Component
public class InitIpUtil extends PropertyDefinerBase {
@Override
public String getPropertyValue() {
return initIpAndPort();
}
public static String initIpAndPort() {
String subIp = null;
try{
InetAddress addr = InetAddress.getLocalHost();
String ip = addr.getHostAddress();
subIp = ip.substring(ip.lastIndexOf(".",ip.lastIndexOf(".")-1)+1);
}catch (Exception e){
e.printStackTrace();
}
return subIp;
}
}
(6)<appender>
写日志的组件
<configuration>
子节点<appender>
:负责写日志的组件,它有两个必要属性name和class。
- name:指定appender名称,
- class:指定appender的全限定名
Logback会把书写日志事件的任务委托给叫做appender的组件,appenders必须实现ch.qos.logback.core.Appender
接口,该接口方法如下:
package ch.qos.logback.core;
import ch.qos.logback.core.spi.ContextAware;
import ch.qos.logback.core.spi.FilterAttachable;
import ch.qos.logback.core.spi.LifeCycle;
public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachable {
public String getName();
public void setName(String name);
void doAppend(E event);
}
(6-1) Appender分类
1、ConsoleAppender
日志信息输出到控制台,也就是通过 System.out
或者 System.err
输出,前者是默认值。
子标签 | 类型 | 备注 |
---|---|---|
encoder | Encoder |
编码器。 |
target | String |
有效值为System.out或者System.err,默认为System.out。 |
withJansi | boolean |
默认为false,设为true激活Jansi库,该库提供了windows机器上ANSI颜色编码支持,用不上。 |
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<!-- 格式化输出:
%date(d%)表示日期,
%thread表示线程名,
%-5level:级别从左显示5个字符宽度,
%logger{36}表示logger名字最长36个字符,否则按照句点分割,
%msg:日志消息,
%n是换行符 -->
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>
2、FileAppender
OutputStreamAppender
的子类,输出日志信息到文件中,目标文件通过File选项指定。
子标签 | 类型 | 备注 |
---|---|---|
append | boolean |
是否追加到指定文件。 |
encoder | Encoder |
编码器。 |
file | String |
写入日志信息的文件名,如果文件不存在,自动创建。 |
prudent | boolean |
谨慎模式写入,默认为false。如果为 true,当多个JVM中的Appender实例写入相同文件时,谨慎模式下会串行I/O操作,效率低。 |
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>testFile.log</file>
<append>true</append>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
</configuration>
上述配置表示把>=DEBUG级别的日志都输出到testFile.log
日志文件唯一命名(通过timestamp)案例如下
<timestamp>
元素两个必选属性为key和datePattern,可选属性为timeReference,key指定名字,dataPattern指定日期转换格式,timeReference指定引用的时间戳。
<configuration>
<!-- Insert the current time formatted as "yyyyMMdd'T'HHmmss" under
the key "bySecond" into the logger context. This value will be
available to all subsequent configuration elements. -->
<timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss" timeReference="contextBirth"/>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<!-- use the previously created timestamp to create a uniquely
named log file -->
<file>log-${bySecond}.txt</file>
<encoder>
<pattern>%logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
</configuration>
3、RollingFileAppender
滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。例如,写入日志信息到名为log.txt的文件,由于超出指定的文件大小限制,日志输出到另一个文件。
子标签 | 类型 | 备注 |
---|---|---|
file | String |
参考FileAppender。 |
append | boolean |
参考FileAppender。 |
encoder | Encoder |
编码器。 |
rollingPolicy | RollingPolicy |
滚动策略。 |
triggeringPolicy | TriggeringPolicy |
触发策略。 |
prudent | boolean |
参考FileAppender。 |
滚动策略
滚动策略负责日志文件移动和重命名相关滚动步骤,该接口api如下:
package ch.qos.logback.core.rolling;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.spi.LifeCycle;
public interface RollingPolicy extends LifeCycle {
public void rollover() throws RolloverFailure;
public String getActiveFileName();
public CompressionMode getCompressionMode();
public void setParent(FileAppender appender);
}
滚动策略有以下几种
TimeBasedRollingPolicy(基于时间的滚动策略)
Size and time based rolling policy(基于文件大小和时间的滚动策略)
- TimeBasedRollingPolicy(基于时间的滚动策略)
基于时间的滚动策略是最长使用的滚动策略,可以通过天或者月份制定何时滚动。
子标签 | 类型 | 备注 |
---|---|---|
fileNamePattern | String |
必选参数,定义了归档日志文件的名字,它的值由文件名和%d的占位转换符组成,如果没有指定时间和日期格式,默认为yyyy-MM-dd。 多个%d转换符/var/log/%d{yyyy/MM, aux}/myapplication.%d{yyyy-MM-dd}.log |
maxHistory | int | 可选参数,表示日志文件保存的最大数量。例如:如果按天滚动,该值设为30,则日志文件最多保存30天。 |
totalSizeCap | int | 可选参数,表示所有归档日志文件的的文件大小,和maxHistory结合使用,maxHistory优先于totalSizeCap。 |
cleanHistoryOnStart | boolean | 可选参数,表示appender启动时是否清除归档日志文件,默认为false。 |
下面是一些fileNamePattern的示例:
文件命名格式 | 滚动计划 | 备注 |
---|---|---|
/wombat/foo.%d | 按日滚动,由于%d后缺失日期和时期格式,采用默认格式yyyy-MM-dd | 如果设置file属性(日志文件名),文件格式如下:昨天:/wombat/foo.2019-05-05当天:/wombat/foo.2019-05-06 如果设置file属性为/wombat/foo.txt,文件格式如下 昨天:/wombat/foo.2019-05-05当天:/wombat/foo.txt |
/wombat/%d{yyyy/MM}/foo.txt | 按月滚动 | 如果没设置file属性,文件格式如下:上个月:/wombat/2019/05/foo.txt当月:/wombat/2019/06/foo.txt 如果设置file属性为/wombat/foo.txt,上个月:/wombat/2019/05/foo.txt当月:/wombat/foo.txt |
/wombat/foo.%d{yyyy-ww}.log | 每周第一天滚动 | 文件命名规则与上类似 |
/wombat/foo%d{yyyy-MM-dd_HH}.log | 按小时滚动 | 文件命名规则与上类似 |
/wombat/foo%d{yyyy-MM-dd_HH-mm}.log | 按分钟滚动 | 文件命名规则与上类似 |
/wombat/foo%d{yyyy-MM-dd_HH-mm, UTC}.log | 指定时区按分钟滚动 | 文件命名规则与上类似,只是指定了时区 |
/foo/%d{yyyy-MM,aux}/%d.log | 按天滚动,归档日志文件在一个包含年和月文件夹里。 | 第一个%d起辅助作用,第二个%d由于没有指定日期和时间格式,默认为yyyy-MM-dd。 |
TimeBasedRollingPolicy支持归档日志文件自动压缩,如果fileNamePattern的值以.gz或者.zip结尾则可利用该特性。
文件命名格式 | 滚动计划 | 备注 |
---|---|---|
/wombat/foo.%d.gz | 按日滚动,归档日志文件会自动GZIP压缩 | 如果file属性没有设置,文件格式如下:昨天:/wombat/foo.2019-05-05.gz当天:/wombat/foo.2019-05-06 如果设置file属性为/wombat/foo.txt,文件格式如下:昨天:/wombat/foo.2019-05-05.gz当天:/wombat/foo.txt |
滚动策略为TimeBasedRollingPolicy的RollingFileAppender
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logFile.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每日滚动 -->
<fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 将30天的历史记录的总大小限制在3GB -->
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
</configuration>
- Size and time based rolling policy(基于文件大小和时间的滚动策略)
通过这种策略可以按日期来归档日志文件,同时也可以限制每个日志文件的大小,示例如下:
<configuration>
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>mylog.txt</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 每日滚动 -->
<fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
<!-- 每个文件应该不超过100MB,保留60天的历史记录,但不超过20GB -->
<maxFileSize>100MB</maxFileSize>
<maxHistory>60</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="ROLLING" />
</root>
</configuration>
注意:%i转换符和%d在这里是必须的,当前时间周期内如果日志文件大小达到了maxFileSize,则会进行归档,文件名以从0开始的递增索引命名,%i表示从0开始递增索引。例如:mylog-2019-05-05.0.txt
- FixedWindowRollingPolicy(固定窗口的滚动策略)
滚动时会根据固定窗口算法重命名文件,下面是FixedWindowRollingPolicy的子标签:
子标签 | 类型 | 备注 |
---|---|---|
minIndex | int |
最小索引 |
maxIndex | int |
最大索引 |
fileNamePattern | String |
文件命名格式,必须包含%i转换符,用来表示被插入的当前窗口索引的位置。例如:如果文件命名格式为MyLogFile%i.log,minIndex、maxIndex分别被设为1、3,那么滚动时会产生名为MyLogFile1.log、MyLogFile2.log、MyLogFile3.log的三个日志文件。 |
假设minIndex被设为1,maxIndex被设为3,fileNamePatter被设为foo%i.log,file属性被设为foo.log,具体示例如下:
滚动次数 | 输出目标 | 归档日志文件 | 备注 |
---|---|---|---|
0 | foo.log | - | 没有产生滚动,日志输出文件为初始文件foo.log。 |
1 | foo.log | foo1.log | 第一次滚动,foo.log重命名为foo1.log,新的foo.log被创建作为输出目标。 |
2 | foo.log | foo1.log, foo2.log | 第二次滚动,foo1.log重命名为foo2.log,foo.log重命名为foo1.log,新的foo.log被创建作为输出目标。 |
3 | foo.log | foo1.log, foo2.log, foo3.log | 第三次滚动,foo2.log重命名为foo3.log,foo1.log重命名为foo2.log,foo.log重命名为foo1.log,新的foo.log被创建作为输出目标。 |
4 | foo.log | foo1.log, foo2.log, foo3.log | 后面滚动会先删除foo3.log,然后循环如上步骤。 |
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>test.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>tests.%i.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
</configuration>
触发策略
TriggerPolicy 实现负责指导 RollingFileAppender什么时候回滚,该接口如下:
package ch.qos.logback.core.rolling;
import java.io.File;
import ch.qos.logback.core.spi.LifeCycle;
public interface TriggeringPolicy<E> extends LifeCycle {
public boolean isTriggeringEvent(final File activeFile, final <E> event);
}
- SizeBasedTriggeringPolicy(限制大小)
SizeBasedTriggeringPolicy
会观察当前日志文件的大小,如果增长到指定值,会通知RollingFileAppender触发滚动。SizeBasedTriggeringPolicy只接受一个参数,也就是maxFileSize,默认值为10MB。maxFileSize选项的值可以是bytes、kilobytes、megabytes、gigabytes。例如:5000000、5000KB、5MB、2GB,前面三个等价。
下面是RollingFileAppender结合SizeBasedTriggeringPolicy配置示例:
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>test.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>test.%i.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
</configuration>
(6-2)Filter过滤器
在logback中,提供了两种类型的filter:regular过滤器和turbo过滤器。
规律型过滤器继承自 Filter抽象类,该类主要由带有ILoggingEvent参数的decide()方法组成。多个过滤器会基于三进制规则进行排序,每个过滤器的decide(ILoggingEvent event)方法依次会被调用,该方法返回FilterReply的枚举值,例如:DENY、NEUTRAL、ACCEPT。如果方法返回值为DENY,那么日志对象会被终止而不会被其它过滤器访问。如果方法返回值为NEUTRAL,那么下一个过滤器会进行处理,如果没有其余过滤器,那么日志会被正常处理。如果方法返回值为ACCEPT,那么日志对象会跳过其余过滤器被立即处理。
- DENY:日志将立即被抛弃不再经过其他过滤器;
- NEUTRAL:有序列表里的下个过滤器过接着处理日志;(该级别既不处理,也不抛弃,相当于没有任何处理,日志会被保存下来并在本appender被执行)
- ACCEPT:日志会被立即处理,不再经过剩余过滤器。
1、自定义过滤器
package chapters.filters;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;
public class SampleFilter extends Filter<ILoggingEvent> {
@Override
public FilterReply decide(ILoggingEvent event) {
if (event.getMessage().contains("sample")) {
return FilterReply.ACCEPT;
} else {
return FilterReply.NEUTRAL;
}
}
}
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="chapters.filters.SampleFilter" />
<encoder>
<pattern>
%-4relative [%thread] %-5level %logger - %msg%n
</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
2、LevelFilter(级别过滤器)
LevelFilter基于匹配的具体级别过滤事件,如果日志事件的级别等于配置的级别,那么过滤器会接受或者拒绝日志事件,这取决于配置的onMatch和onMisMatch属性,如下:
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>
%-4relative [%thread] %-5level %logger{30} - %msg%n
</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
3、ThresholdFilter(阀值过滤器)
ThresholdFilter会过滤低于指定阀值的日志事件,对于等于或者大于阀值的日志事件,该过滤器会响应NEUTRAL,而对于低于阀值的日志事件,改过滤器会响应DENY。如下:
<configuration>
<appender name="CONSOLE"
class="ch.qos.logback.core.ConsoleAppender">
<!-- deny all events with a level below INFO, that is TRACE and DEBUG -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>
%-4relative [%thread] %-5level %logger{30} - %msg%n
</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
(7)<logger>
指定包的日志级别
用来设置某一个包或具体的某一个类的日志打印级别、以及指定 <appender>
。<logger>
仅有一个name属性,一个可选的level和一个可选的addtivity属性。
可以包含零个或多个 <appender-ref>
元素,标识这个appender将会添加到这个loger
name: 用来指定受此loger约束的某一个包或者具体的某一个类。
level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL和OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。 如果未设置此属性,那么当前loger将会继承上级的级别。
addtivity: 是否向上级loger传递打印信息。默认是true。同
<loger>
一样,可以包含零个或多个<appender-ref>
元素,标识这个appender将会添加到这个loger。
<configuration>
<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
<logger name="org.springframework" level="INFO"></logger>
<logger name="org.mybatis" level="INFO"></logger>
</configuration>
常用 logger 配置
<!-- show parameters for hibernate sql 专为 Hibernate 定制 -->
<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE" />
<logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG" />
<logger name="org.hibernate.SQL" level="DEBUG" />
<logger name="org.hibernate.engine.QueryParameters" level="DEBUG" />
<logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" />
<!--myibatis log configure-->
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
(8)<root>
根logger
它也是 <loger>
元素,但是它是根loger,是所有 <loger>
的上级。只有一个level属性,因为name已经被命名为”root”,且已经是最上级了。
- level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL和OFF,不能设置为INHERITED或者同义词NULL。 默认是DEBUG。
<configuration>
<!-- 最基础配置 -->
<root level="debug">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</configuration>
(9)<springProfile>
环境隔离
整体隔离
修改spring对应profile的配置文件
这里我们需要在spring不同的profile配置文件中,指定需要logback配置文件。
application.properties内容如下:
spring.profiles.active=dev
logging.config=classpath:logback.xml
application-dev.properties内容如下:
logging.config=classpath:logback-dev.xml
部分隔离
<configuration>
<!-- 开发环境 -->
<springProfile name="dev">
<logger name="com.llayjun.millet.api" level="info"/>
</springProfile>
<!-- 生产环境 -->
<springProfile name="prod">
<logger name="com.llayjun.millet.api" level="error"/>
</springProfile>
</configuration>
5、完整案例
以下配置适用于 lockback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。
当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
<contextName>logback-spring</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。 -->
<!-- 这边value配置成自己本地的日志地址 -->
<property name="logging.path" value="E:\prod_logs" />
<!--0. 日志格式和颜色渲染 -->
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!--1. 输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--2. 输出到文档-->
<!-- 不需要具体划分,则屏蔽INFO及以上 -->
<!-- 2.1 level为 DEBUG 日志,时间滚动输出 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
<file>${logging.path}/web_debug.log</file>
<!--日志文档输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${logging.path}/web-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文档保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文档只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 2.2 level为 INFO 日志,时间滚动输出 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
<file>${logging.path}/web_info.log</file>
<!--日志文档输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${logging.path}/web-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文档保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文档只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 2.3 level为 WARN 日志,时间滚动输出 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
<file>${logging.path}/web_warn.log</file>
<!--日志文档输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logging.path}/web-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文档保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文档只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 2.4 level为 ERROR 日志,时间滚动输出 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
<file>${logging.path}/web_error.log</file>
<!--日志文档输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logging.path}/web-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文档保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文档只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
以及指定<appender>。<logger>仅有一个name属性,
一个可选的level和一个可选的addtivity属性。
name:用来指定受此logger约束的某一个包或者具体的某一个类。
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
如果未设置此属性,那么当前logger将会继承上级的级别。
addtivity:是否向上级logger传递打印信息。默认是true。
<logger name="org.springframework.web" level="info"/>
<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
-->
<!--
使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
【logging.level.org.mybatis=debug logging.level.dao=debug】
-->
<!--
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
不能设置为INHERITED或者同义词NULL。默认是DEBUG
可以包含零个或多个元素,标识这个appender将会添加到这个logger。
-->
<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
<logger name="org.springframework" level="INFO"></logger>
<logger name="org.mybatis" level="INFO"></logger>
<logger name="org.apache.zookeeper" level="INFO"></logger>
<!-- 4. 最终的策略 -->
<!-- 4.1 开发环境:打印控制台-->
<!-- 记住:日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- 开发环境 -->
<springProfile name="dev">
<logger name="com.llayjun.millet.api" level="info"/>
</springProfile>
<!-- 生产环境 -->
<springProfile name="prod">
<logger name="com.llayjun.millet.api" level="error"/>
</springProfile>
<!-- 最基础配置 -->
<root level="debug">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</configuration>
6、日志按天归档
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="log" />
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--<file>${LOG_HOME}/sms.log</file>-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/response.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>-->
</appender>
<!-- 日志输出级别 -->
<root level="INFO">
<!--输出到控制台-->
<!--<appender-ref ref="STDOUT" />-->
<!--输出到文件中-->
<appender-ref ref="FILE" />
</root>
</configuration>
三、log4j2
导入maven包
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
测试代码
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class LoggerTest {
public static void main(String argv[]) {
Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
logger.trace("trace level");
logger.debug("debug level");
logger.info("info level");
logger.warn("warn level");
logger.error("error level");
logger.fatal("fatal level");
logger.error("字符串拼接一:{},记录main执行:","logger");
logger.error("字符串拼接二:","logger");
}
}