一、写在前面
对于日志文件,相信大家都并不陌生,通过在关键位置打印相关的日志,有利于快速跟踪和定位软件系统运行中存在的问题。
在之前的 java 实现日志记录的文章中,我们介绍了能实现日志记录的主流框架有 log4j、log4j2、logback 等,通过一些性能测试发现,logback 和 log4j2 两个都比较优秀。同时,它们都支持与 slf4j 框架的集成,可以轻松实现系统日志框架实现的切换,这主要得益于门面模式的设计。
当采用 slf4j 来实现日志输出时,我们不需要再纠结到底是用 log4j2 还是用 logback 。slf4j 相当于一个门面接口,可以让代码更加统一,同时它并不是一个日志实现框架,具体的实现会在 slf4j 接口被调用的时候委托给具体的日志框架来实现。比如,当系统中有 logback 时,就委托 logback 来输出日志;当有 log4j2 时,就委托 log4j2 来实现;如果两者同时存在,可能会报循环依赖的错误,因此在项目添加依赖的时候,只能选择其中一个,如果有不兼容的问题,需要手动排除。
对于一个 java web 项目,当采用slf4j + logback来实现日志信息的输出时,通常会添加类似于如下的相关依赖包。
<!-- 添加slf4j依赖包 --> <dependency> <groupid>org.slf4j</groupid> <artifactid>slf4j-api</artifactid> <version>1.7.25</version> </dependency> <!-- 添加logback依赖包 --> <dependency> <groupid>ch.qos.logback</groupid> <artifactid>logback-classic</artifactid> <version>1.1.7</version> </dependency>
然后,在项目根目录下创建logback.xml并配置相关参数,示例如下。
<?xml version="1.0" encoding="utf-8"?> <!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。 scanperiod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 --> <configuration scan="true" scanperiod="60 seconds" debug="false"> <!-- %d{yyyy-mm-dd hh:mm:ss} [%level] - %msg%n logger: %logger class: %class file: %file caller: %caller line: %line message: %m method: %m relative: %relative thread: %thread exception: %ex xexception: %xex nopexception: %nopex rexception: %rex marker: %marker newline:%n --> <property name="custom_log_pattern" value="%d{yyyy-mm-dd hh:mm:ss} [%thread] %-5level %logger{90} - %msg%n" /> <!-- 上下文名称 --> <contextname>${context_name}</contextname> <!-- 日志输出组件 --> <appender name="console" class="ch.qos.logback.core.consoleappender"> <!-- 对日志进行格式化。 --> <encoder> <pattern>${custom_log_pattern}</pattern> <charset>utf-8</charset> </encoder> </appender> <!-- 日志级别为info,日志输出到控制台 --> <root level="info"> <appender-ref ref="console" /> </root> </configuration>
最后,通过门面接口来输出日志,示例如下:
import org.slf4j.logger; import org.slf4j.loggerfactory; public class logprintutil { private static final logger logger = loggerfactory.getlogger(logprintutil.class); public static void main(string[] args){ logger.info("info信息"); logger.warn("warn信息"); logger.error("error信息"); } }
二、spring boot 日志配置
当我们采用 springboot 框架来开发系统的时候,其实默认已经帮我们集成好了spring-boot-starter-logging日志依赖包,它底层采用的就是上面介绍的logback日志实现框架,同时也集成了slf4j依赖库。
默认的logback日志配置文件在org/springframework/boot/logging/logback/defaults.xml下,我们只需要在相关的位置采用slf4j接口来打印日志即可,示例如下:
import org.slf4j.logger; import org.slf4j.loggerfactory; import org.springframework.boot.springapplication; import org.springframework.boot.autoconfigure.springbootapplication; @springbootapplication public class logapplication { private static final logger logger = loggerfactory.getlogger(logapplication.class); public static void main(string[] args) { springapplication.run(logapplication.class, args); logger.error("hello world"); logger.warn("hello world"); logger.info("hello world"); logger.debug("hello world"); logger.trace("hello world"); } }
启动服务,可以看到类似于如下的打印结果:
默认的日志级别为info
,如果想更改日志级别,可以在application.properties
文件配置日志打印级别,比如改成trace
,参数如下:
logging.level.root=trace
重新启动服务,日志打印结果如下:
从控制台输出的结果可以初步分析出,trace
级别最低,可以打印所有级别的日志。在整个日志体系中,级别从低到高分为:
trace < debug < info < warn < error
级别越底,可打印的日志就更多;相反,级别越高,输出的日志就更少。
从实际情况来看,太多的日志打印也未必是一件好事,有时候会把服务器磁盘撑爆,导致服务宕机。通常我们会配置info
级别,在关键的位置打印相关信息即可。
2.1、logback 自定义配置
在实际的业务开发中,通常我们会自定义logback
相关配置文件,有两种做法。
- 第一种:创建
logback.xml
配置文件,这种配置文件会直接被日志框架加载 - 第二种:创建
logback-spring.xml
配置文件,这种配置文件不会直接被日志框架加载,而是先由 springboot 去解析日志配置再加载,可以使用 springboot 的一些高级功能,比如 profile 属性。
这里,我们选择第二种方式,在src/main/resources
目录下,创建logback-spring.xml
文件,一般标准写法如下:
<?xml version="1.0" encoding="utf-8"?> <configuration> <!--定义相关变量--> <property name="log.dir" value="log-demo" /> <property name="custom.log.pattern" value="%d{yyyy-mm-dd hh:mm:ss} [%thread] %-5level %logger{90} - %msg%n" /> <!-- 控制台文件输出 --> <appender name="console" class="ch.qos.logback.core.consoleappender"> <encoder> <pattern>${custom.log.pattern}</pattern> <charset>utf-8</charset> </encoder> </appender> <!-- 文件输出 --> <appender name="app_log" class="ch.qos.logback.core.rolling.rollingfileappender"> <file>${log.dir}/log_info.log</file> <encoder class="ch.qos.logback.classic.encoder.patternlayoutencoder"> <pattern>${custom.log.pattern}</pattern> <charset>utf-8</charset> </encoder> <rollingpolicy class="ch.qos.logback.core.rolling.timebasedrollingpolicy"> <filenamepattern>${log.dir}/histroy/log-%d{yyyy-mm-dd}-%i.log </filenamepattern> <maxhistory>30</maxhistory> <timebasedfilenamingandtriggeringpolicy class="ch.qos.logback.core.rolling.sizeandtimebasedfnatp"> <maxfilesize>250mb</maxfilesize> </timebasedfilenamingandtriggeringpolicy> </rollingpolicy> </appender> <root level="info"> <appender-ref ref="console" /> <appender-ref ref="app_log" /> </root> </configuration>
其中console
节点,表示将日志输出到控制台;app_log
节点,表示将日志输出到文件中,并自动将最近 30 天的日志文件进行归档到histroy
文件夹中。
如果想要读取 spring boot properties 或根据 spring profile 定义日志配置,可以通过如下方式实现。
<?xml version="1.0" encoding="utf-8"?> <configuration> <!--获取application.properties中定义的变量--> <springproperty scope="context" name="customlogpattern" source="custom.log.pattern" defaultvalue="%d{yyyy-mm-dd hh:mm:ss} [%thread] %-5level %logger{90} - %msg%n"/> <springproperty scope="context" name="logdir" source="custom.log.dir" defaultvalue="log-demo"/> <!-- 控制台文件输出 --> <appender name="console" class="ch.qos.logback.core.consoleappender"> <encoder> <pattern>${customlogpattern}</pattern> <charset>utf-8</charset> </encoder> </appender> <!-- 文件输出 --> <appender name="app_log" class="ch.qos.logback.core.rolling.rollingfileappender"> <file>${logdir}/log_info.log</file> <encoder class="ch.qos.logback.classic.encoder.patternlayoutencoder"> <pattern>${customlogpattern}</pattern> <charset>utf-8</charset> </encoder> </appender> <!--获取springprofile变量--> <springprofile name="dev"> <root level="info"> <appender-ref ref="console" /> <appender-ref ref="app_log" /> </root> </springprofile> <springprofile name="prod"> <root level="info"> <appender-ref ref="app_log" /> </root> </springprofile> </configuration>
application.properties
文件相关的配置参数如下:
# 指定spring profiles 参数 spring.profiles.active=dev # 自定义打印格式 custom.log.pattern=%d{yyyy-mm-dd hh:mm:ss} [%thread] %-5level %logger{90} - %msg%n # 自定义日志存储路径 custom.log.dir=app-demo
2.2、log4j2 自定义配置
如果项目更倾向于使用 log4j2 而不是 logback,迁移方式也很简单。
首先,需要排除掉默认 logback 相关依赖库,然后添加log4j2
相关依赖包,示例如下:
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter</artifactid> <exclusions> <exclusion> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-logging</artifactid> </exclusion> </exclusions> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-log4j2</artifactid> </dependency>
与logback
类似,当添加相关依赖包之后,spring boot 默认带了一个log4j2.xml
日志配置文件,在org/springframework/boot/logging/log4j2/log4j2.xml
。
但是,基于业务的需要,通常我们会自定义配置文件,一般写法如下:
<?xml version="1.0" encoding="utf-8"?> <configuration status="info" monitorinterval="3"> <!--变量配置--> <properties> <!--定义日志存储的路径 --> <property name="log.dir" value="app-demo"/> <!-- 定义日志输出格式 --> <property name="custom.log.pattern" value="%d{yyyy-mm-dd hh:mm:ss} [%t] %-5level %l %msg%n"/> </properties> <appenders> <!-- 控制台输出 --> <console name="console" target="system_out"> <patternlayout pattern="${custom.log.pattern}"/> </console> <!-- 文件输出 --> <rollingfile name="app_log" filename="${log.dir}/app.log" filepattern="${log.dir}/app-%d{mm-dd-yyyy}-%i.log.gz"> <patternlayout pattern="${custom.log.pattern}"/> <policies> <timebasedtriggeringpolicy/> <!-- size根据实际的日志量填写 --> <sizebasedtriggeringpolicy size="100 mb"/> </policies> </rollingfile> </appenders> <loggers> <!-- 日志记录级别 --> <root level="info"> <appenderref ref="console"/> <appenderref ref="app_log"/> </root> </loggers> </configuration>
此时如果代码中采用的是门面模式的编程方式,无需做任何的调整,即可实现日志框架的切换改造。
小结
最后总结一下,对于简单的应用场景,并发量不高的环境下,可以采用 logback 来实现日志打印;如果对性能要求较高,可以采用 log4j2,据官方提供的测试报告中,log4j2 在性能和新技术的应用,比 logback 领先,毕竟是后起之秀,但是兼容性方面,logback 更优。
到此这篇关于spring boot配置日志的实现步骤的文章就介绍到这了,更多相关spring boot配置日志内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论