● 开发调试:根据日志调试定位程序以达到正确的状态;
● 系统运行状态留存:应用系统发布运行投入生成,记录系统运行日志,根据日志排查定位问题;
● 数据收集:将应用日志接入大数据平台,收集用户行为数据,分析用户操作习惯、喜好、用户画像等;
● 代码冗余:日志并没有实现具体的业务,没有必要打印不必要的日志,在一定程度上增加代码冗余,降低代码可读性;
● 降低系统性能:有不少因大量日志输出导致系统崩溃的例子;
Log4J 最初是有俄罗斯 Ceki Gülcü 基于 JUL 开发的日志框架,被大范围使用后捐献给 Apache 孵化。
Ceki Gülcü 大神后续不满足 Apache 对 Log4J 的管理,后续又开发了 Logback 和 SLF4J ,Logback 改进了 Log4J 的缺点,性能大幅提升,使用方式几乎不变,用户开始将 Log4J 转到 Logback。
Logback 冲击了 Log4J 的市场后,Apache 开发了 Log4J2,借鉴了 Logback,改进了 Log4J 的缺点,同时号称性能完胜 Logback。
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");
}
}
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");
}
}
如果一直使用 log4j 或 logback,直接使用是可以的。有一天技术经理说要更换日志框架,那就悲催了,需要一个一个改,门面模式本身不记录日志,依赖log4j 或 Logback 记录日志,更换时只需要更换依赖即可。
● 门面(Facade)角色:客户端可以调用这个角色的方法。此角色知晓相关的子系统的功能和责任。正常情况下,本橘色会将所有从客户端发来的请求委派到相应的子系统中。
● 子系统(SubSystem)角色:可以同时又一个或多个子系统。每个子系统都不是一个单独的类,而不是一个类的合集。每个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另一个客户端。
门面模式的优点:
● 解耦:门面模式解耦了客户端与子系统之间的耦合,客户端不需要了解子系统是如何实现的,让子系统更容易扩展和维护;
Springboot 默认使用了 Logback 做日志记录,SLF4J 做门面系统。默认情况下Springboot 提供的日志系统足够使用。考虑到 LOG4J2 的性能出众,可以考虑使用 LOG4J2 + SLF4J 的组合。
<configuration scan="true" scanPeriod="10 seconds">
<contextName>logbackcontextName>
<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>DEBUGlevel>
filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}Pattern>
<charset>UTF-8charset>
encoder>
appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/log.logfile>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} -%5level ---[%15.15thread] %-40.40logger{39} : %msg%n%npattern>
<charset>UTF-8charset>
encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}.%i.logfileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MBmaxFileSize>
timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>15maxHistory>
rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFOlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
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>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-loggingartifactId>
<groupId>org.springframework.bootgroupId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-log4j2artifactId>
dependency>
<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>