最近打在打印日志这块栽了个跟头,发现日志这块掌握得还不太好,所以大概梳理一下。
其实 SLF4J 类似于 Commons Logging,也是一个日志接口,而 Logback 类似于 Log4j,是一个日志的实现。
4 个日志级别
常用的 4 个日志级别,从低到高:DEBUG、INFO、WARN、ERROR。低级别能输出高级别的日志,级别越低输出内容越多。
- DEBUG:调试数据,生产环境关闭 Debug
- INFO:系统运行信息、外部接口部分,可通过日志看到功能流程
- WARN:不影响程序正常运行,但不应该出现的情况
- ERROR:影响程序正常运行的情况,此时需使用邮件等方式告警,如果抛出异常,不打印
使用 Logger 或使用注解 @Slf4j
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class Main {
final Logger logger = LoggerFactory.getLogger(getClass());
("/test")
public String test() {
logger.debug("debug: [{}]", "haha");
logger.info("info: [{}]", "haha");
logger.warn("warn: [{}]", "haha");
logger.error("error: [{}]", "haha");
return "test";
}
}
import lombok.extern.slf4j.Slf4j;
4j
class Main {
("/test")
public String test() {
log.debug("debug: [{}]", "haha");
log.info("info: [{}]", "haha");
log.warn("warn: [{}]", "haha");
log.error("error: [{}]", "haha");
return "test";
}
}
打印日志时,使用占位符和 [],当没有 logback.xml 时,默认隔离级别:INFO。
Logback 配置
logback.xml 基础配置:
<configuration>
<!--控制台输出设置-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> <encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder> </appender>
<root level="info"> <appender-ref ref="STDOUT" /> </root></configuration>
输出格式:
15:58:50.559 [http-nio-8080-exec-1] INFO w.depp.exceptionlog.TestController - info: haha
使用 logger 指定某个 package 使用某个级别:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> <encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder> </appender>
<logger name="chapters.configuration" level="INFO"/>
<!-- Strictly speaking, the level attribute is not necessary since -->
<!-- the level of the root level is set to DEBUG by default. --> <root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>
使用 logger 指定某个文件使用某个级别:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern> %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder> </appender>
<logger name="chapters.configuration" level="INFO" /> <logger name="chapters.configuration.Foo" level="DEBUG" />
<root level="DEBUG"> <appender-ref ref="STDOUT" /> </root>
</configuration>
为不同的环境配置不同的日志级别
有时候我们在系统整体使用某个级别外(如 INFO),还可以业务类针对不同的环境配置不同的日志级别,使用 springProfile
标签
<configuration debug="true">
<include resource="org/springframework/boot/logging/logback/base.xml"/> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> <encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder> </appender>
<root level="INFO"> <appender-ref ref="STDOUT" /> </root> <springProfile name="test,dev">
<logger name="wang.depp" level="DEBUG"> <appender-ref ref="STDOUT" /> </logger> </springProfile>
<springProfile name="pre,pro"> <logger name="wang.depp" level="INFO"> <appender-ref ref="STDOUT" /> </logger> </springProfile></configuration>
本地 application.yml 配置环境参数
spring:
profiles:
active: dev
打包部署时指定环境
$ java -jar \target\my-app.jar -Dspring.profiles.active=dev
默认 appender 将重复打印日志,此时可以通过在 logger 添加 additivity="false"
来关闭
<springProfile name="pre,pro">
<logger name="wang.depp" level="INFO" additivity="false"> <appender-ref ref="STDOUT" /> </logger> </springProfile>```
## 输出到日志文件
```xml
<configuration debug="true">
<include resource="org/springframework/boot/logging/logback/base.xml"/> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> <encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder> </appender>
<appender name="baselog" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>log/app.log</File>
<!--根据日期存放日志,每个文件限制 64MB --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>log/app.log.%d.%i</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!--or whenever the file size reaches 64 MB-->
<maxFileSize>64 MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <!--日志文件的日志格式-->
<encoder>
<pattern> %d %p (%file:%line\)- %m%n
</pattern>
<charset>UTF-8</charset>
<!-- 此处设置字符集 -->
</encoder>
</appender>
<springProfile name="test,dev"> <logger name="wang.depp" level="debug"> <appender-ref ref="STDOUT" /> <appender-ref ref="baselog"/> </logger> </springProfile>
<springProfile name="pre,pro"> <logger name="wang.depp" level="error"> <appender-ref ref="STDOUT" /> <appender-ref ref="baselog"/> </logger> </springProfile></configuration>
搭建 ELK 平台图形化查看日志
ELK:Elasticsearch、Logstash、Kibana
大致原理:
详细搭建过程:搭建 ELK 实时日志平台并在 Spring Boot 和 Nginx 项目中使用