SpringBoot系列: logging
我们的 SpringBoot 程序都会加 spring-boot-starter 包, 而该包一个依赖项 spring-boot-starter-logging, 所以SpringBoot 程序不需要再显式增加 spring-boot-starter-logging 包依赖.
使用 mvn dependency:tree 命令可以分析出应用程序的依赖树, 从中可以看到 spring-boot-starter-logging 包也自动设置了
slf4j 和 logback 依赖, SpringBoot 使用了 slf4j 日志接口框架, 而 logback 是默认的日志实现框架, springBoot缺省的日志实现是logback, 也可以选用其他日志实现, 比如 log4j, log4j2等, 其中logback完全符合slf4j规范.
logback log4j 使用方式几乎一样, 功能更强大, 重要体现在:
1. 可以自动加载配置文件, 这个太好了, 不需要重启系统就能实时调整日志设置.
2. 配置文件可以支持多个environment.
SpringBoot程序有一个默认的logback配置, 配置由一个关联到root logger的ConsoleAppender组成, 默认的级别是Debug, 也就是该最小化配置是非常适合程序开发环境.
SpringBoot 使用 logback 作为日志引擎, 有下面三种方法:
1. 全部使用 application.property 配置日志输出
这种做法最简单了, 简单几个属性设置就行了, 适合简单的应用程序.
2. 使用 logback-spring.xml 配置
这种做法是最推荐的, 可以支持多环境, 可以支持实时修改日志设置. 当然也可以换个其他名字, 方法是在 application.properties文件中, 设置 logging.config 属性.
3. 使用 logback.xml 配置
SpringBoot程序不太推荐logback.xml 配置, Spring Boot包含很多有用的Logback扩展, 这些扩展不能在标准的 logback.xml 配置文件中配置, 因为logback.xml加载的太早了.
===============================
application.property 配置方式
===============================
# springBoot缺省的日志实现是logback, 也可以选用其他日志实现, 比如 log4j, log4j2, 或 none, 其中none是彻底关闭日志. # org.springframework.boot.logging.LoggingSystem=Logback # logging.config=classpath:logback-spring.xml spring.application.name=<your app name here> # 推荐使用logging.file属性, 而不是 logging.path, 后者仅能指定日志文件的目录, 其文件名永远是spring.log logging.file=${java.io.tmpdir}/${spring.application.name}.log # debug=true #当使用debug模式时, SpringBoot和Hibernate等核心组件会输出更多的信息, debug模式下并不会确保我们应用程序能输出DEBUG级别信息. 要想输出com.springbootmybatis.mybatissample包的debug日志, 需要设置 logging.level.com.springbootmybatis.mybatissample=DEBUG # trace=true # 不要打开 trace , 否则会输出太多的trace日志信息, 日志文件可读性非常差, 同时也会影响性能. #root logger的级别, logging.level.root=ERROR #其他 class 的级别 logging.level.org.springframework.web=ERROR logging.level.org.hibernate=ERROR logging.level.com.springbootmybatis.mybatissample=DEBUG # 设置高亮error/info日志输出 spring.output.ansi.enabled=ALWAYS # NEVER: 禁用ANSI-colored输出(默认项) # DETECT:会检查终端是否支持ANSI,是的话就采用彩色输出(推荐项) # ALWAYS:总是使用ANSI-colored格式输出,若终端不支持的时候,会有很多干扰信息,不推荐使用
===============================
logback-spring.xml 配置方式
===============================
先讲几点注意事项:
(1) logback-spring.xml 不能像 application.properties 文件一样外置, 只能被打包到 jar 文件中, 所以, 最好是 logback-spring.xml 文件最好是使用 springProperty 来参数化.
(2) 如果logback-spring.xml配置有问题的话, 程序会在直接在显示的SpringBoot ASCII形式的图标后停止, 我发现好像springProfile配置项目下, 缺少 CONSOLE或 STDOUT appender, 就会出现无法启动的情况.
(3) 如果在application.properties 和 logback-spring.xml 都设置了日志配置, SpringBoot 会用logback-spring.xml覆盖 application.properties 中的配置项.
application.properties 示例:
# org.springframework.boot.logging.LoggingSystem=Logback # logging.config=classpath:logback-spring.xml spring.profiles.active=prod
logback-spring.xml 简单示例:
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds" debug="false"> <include resource="org/springframework/boot/logging/logback/defaults.xml"/> <include resource="org/springframework/boot/logging/logback/console-appender.xml"/> <!--- 定义参数, 后面可以使用 ${USER_DEFINED_VAR} 引用参数 --> <property name="USER_DEFINED_VAR" value="ABCDEFG" /> <!--甚至, 可以引用的 .properties 文件中定义的参数--> <springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="MyBatisSample"/> <springProperty scope="context" name="LOG_LEVEL" source="app.logging.level" defaultValue="INFO"/> <springProperty scope="context" name="LOG_PATH" source="app.logging.path" defaultValue="C:\\app\logs"/> <!-- 开发和测试环境--> <springProfile name="dev,test"> <logger name="com.springbootmybatis.mybatissample" level="${LOG_LEVEL}" /> <root level="DEBUG"> <appender-ref ref="FILE"/> <appender-ref ref="STDOUT"/> </root> </springProfile> <!-- 生产环境 --> <springProfile name="prod"> <logger name="com.springbootmybatis.mybatissample" level="${LOG_LEVEL}" /> <root level="INFO"> <appender-ref ref="FILE"/> <appender-ref ref="STDOUT"/> </root> </springProfile> </configuration>
注意 configuration tag 的三个重要属性:
scan: 当此属性设置为 true 时,配置文件如果发生改变,将会被重新加载,默认值为 true.
scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒.当 scan 为 true 时,此属性生效.默认的时间间隔为 1 分钟.
debug: 当此属性设置为 true 时,将console上打印出 logback 内部日志信息,实时查看 logback 运行状态, 但这些logback内部日志不会记录到log文件中. 默认值为 false.
logback-spring.xml 较为完善的示例:
主要内容有:
(1) 定义了多个级别日志的appender形式, 过滤器采用了 LevelFilter 和 ThresholdFilter
(2) 日志文件采用了RollingFileAppender ,避免日志文件太大
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds" debug="false"> <contextName>logback-demo</contextName> <!--输出到控制台 ConsoleAppender--> <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender"> <!--展示格式 layout--> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </layout> </appender> <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--日志级别是大于或等于INFO都将被收录--> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则 如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天 的日志改名为今天的日期。即,<File> 的日志都是当天的。 --> <File>${logback.logdir}/info.${logback.appname}.log</File> <!--滚动策略,按照时间滚动 TimeBasedRollingPolicy--> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间--> <FileNamePattern>${logback.logdir}/info.${logback.appname}.%d{yyyy-MM-dd}.log</FileNamePattern> <!--只保留最近90天的日志--> <maxHistory>90</maxHistory> <!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志--> <!--<totalSizeCap>1GB</totalSizeCap>--> </rollingPolicy> <!--日志输出编码格式化--> <encoder> <charset>UTF-8</charset> <pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</pattern> </encoder> </appender> <appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 此日志文件只记录Error级别的被收录 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>Error</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则 如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天 的日志改名为今天的日期。即,<File> 的日志都是当天的。 --> <File>${logback.logdir}/error.${logback.appname}.log</File> <!--滚动策略,按照时间滚动 TimeBasedRollingPolicy--> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间--> <FileNamePattern>${logback.logdir}/error.${logback.appname}.%d{yyyy-MM-dd}.log</FileNamePattern> <!--只保留最近90天的日志--> <maxHistory>90</maxHistory> <!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志--> <!--<totalSizeCap>1GB</totalSizeCap>--> </rollingPolicy> <!--日志输出编码格式化--> <encoder> <charset>UTF-8</charset> <pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</pattern> </encoder> </appender> <springProfile name="dev,test"> <logger name="com.logbacksample" level="debug"/> <root level="info"> <appender-ref ref="consoleLog"/> <appender-ref ref="fileInfoLog"/> <appender-ref ref="fileErrorLog"/> </root> </springProfile> <springProfile name="prod"> <logger name="com.logbacksample" level="info"/> <root level="info"> <appender-ref ref="fileInfoLog"/> <appender-ref ref="fileErrorLog"/> </root> </springProfile> </configuration>
===============================
Java 代码中的logger使用
===============================
root logger 是一个所有class logger 的根, 通常我们不需要用代码获取root logger, 直接在logback 配置文件中设置它的logging 输出配置即可, 下面是获取 root logger 和普通class的logger的代码, 注意代码中仅引入了slf4j的类, 而不会引入任何logback的类.
# MyApp.java import org.slf4j.Logger; import org.slf4j.LoggerFactory; Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); Logger myAppLogger = LoggerFactory.getLogger(MyApp.class)
===============================
参考
===============================
http://tengj.top/2017/04/05/springboot7/
http://www.hifreud.com/2017/06/27/spring-boot-07-log/
https://www.mkyong.com/spring-boot/spring-boot-slf4j-logging-example/
https://www.cnblogs.com/lixuwu/p/5804793.html
https://howtoprogram.xyz/2016/12/23/how-to-configure-logging-in-spring-boot/
http://www.cnblogs.com/lixuwu/p/6323739.html