1. 为什么要有日志
1.1 优点
● 开发调试:根据日志调试定位程序以达到正确的状态; ● 系统运行状态留存:应用系统发布运行投入生成,记录系统运行日志,根据日志排查定位问题; ● 数据收集:将应用日志接入大数据平台,收集用户行为数据,分析用户操作习惯、喜好、用户画像等;
1.2 缺点
● 代码冗余:日志并没有实现具体的业务,没有必要打印不必要的日志,在一定程度上增加代码冗余,降低代码可读性; ● 降低系统性能:有不少因大量日志输出导致系统崩溃的例子;
2. Log4J、Logback、Log4J2 发展轨迹
Log4J 最初是有俄罗斯 Ceki Gülcü 基于 JUL 开发的日志框架,被大范围使用后捐献给 Apache 孵化。 Ceki Gülcü 大神后续不满足 Apache 对 Log4J 的管理,后续又开发了 Logback 和 SLF4J ,Logback 改进了 Log4J 的缺点,性能大幅提升,使用方式几乎不变,用户开始将 Log4J 转到 Logback。 Logback 冲击了 Log4J 的市场后,Apache 开发了 Log4J2,借鉴了 Logback,改进了 Log4J 的缺点,同时号称性能完胜 Logback。
3. 门面模式
3.1 传统日志使用(没有门面模式)
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Log4jTest {
private static final Logger LOG = LogManager.getLogger(Log4jTest.class);
public static void main(String[] args) {
LOG.info("log4j");
}
}
3.2 现代日志记录(门面模式)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Log4jTest2 {
private static final Logger LOG = LoggerFactory.getLogger(Log4jTest2.class);
public static void main(String[] args) {
LOG.info("log4j");
}
}
3.3 为什么用门面模式
如果一直使用 log4j 或 logback,直接使用是可以的。有一天技术经理说要更换日志框架,那就悲催了,需要一个一个改,门面模式本身不记录日志,依赖log4j 或 Logback 记录日志,更换时只需要更换依赖即可。
3.4 门面模式
● 门面(Facade)角色:客户端可以调用这个角色的方法。此角色知晓相关的子系统的功能和责任。正常情况下,本橘色会将所有从客户端发来的请求委派到相应的子系统中。 ● 子系统(SubSystem)角色:可以同时又一个或多个子系统。每个子系统都不是一个单独的类,而不是一个类的合集。每个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另一个客户端。 门面模式的优点: ● 解耦:门面模式解耦了客户端与子系统之间的耦合,客户端不需要了解子系统是如何实现的,让子系统更容易扩展和维护;
4. Springboot 集成日志系统
4.1 如何选择日志系统 ?
Springboot 默认使用了 Logback 做日志记录,SLF4J 做门面系统。默认情况下Springboot 提供的日志系统足够使用。考虑到 LOG4J2 的性能出众,可以考虑使用 LOG4J2 + SLF4J 的组合。
4.2 Springboot 默认日志配置示例
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
<contextName>logback</contextName>
<springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
<property name="LOG_HOME" value="logs/${APP_NAME}" />
<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}}"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/log.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} -%5level ---[%15.15thread] %-40.40logger{39} : %msg%n%n</pattern>
<charset>UTF-8</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>15</maxHistory>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<springProfile name="dev">
<logger name="com.alibaba.nacos" level="OFF" addtivity="false"> </logger>
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
</springProfile>
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</springProfile>
<springProfile name="k8s">
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</springProfile>
</configuration>
4.3 LOG4J2 + SLF4J 配置示例
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="ERROR" monitorInterval="30">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5p] %l - %m%n"/>
</Console>
<File name="FileLog" fileName="log/demo.log" append="false">
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5p] %l - %m%n"/>
</File>
<RollingFile name="RollingFileInfo" fileName="log/rolling-info.log" filePattern="log/$${date:yyyy-MM}/rolling-info-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="info" onMatch="APPCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="50MB"/>
</Policies>
</RollingFile>
<RollingFile name="RollingFileWarn" fileName="log/rolling-warn.log" filePattern="log/$${date:yyyy-MM}/rolling-warn-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="50MB"/>
</Policies>
</RollingFile>
<RollingFile name="RollingFileError" fileName="log/rolling-error.log" filePattern="log/$${date:yyyy-MM}/rolling-error-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="50MB"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<root level="info">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
<appender-ref ref="FileLog"/>
</root>
</Loggers>
</Configuration>
|