《SpringBoot日志(logBack 和 log4j2)》
提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!!
SpringBoot 日志 logBack 和 log4j2
1. 常用日志框架
- java.util.logging:是JDK在1.4版本中引入的Java原生日志框架。
- Log4j:Apache的一个开源项目,可以控制日志信息输送的目的地是控制台、文件、GUI组件等,可以控制每一条日志的输出格式,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。虽然已经停止维护了,但目前绝大部分企业都是用的log4j。
- LogBack:是Log4j的一个改良版本。
- Log4j2:Log4j2已经不仅仅是Log4j的一个升级版本了,它从头到尾都被重写了。
1.1 日志框架比较
相比与其他的日志系统,log4j2丢数据这种情况少;disruptor技术,在多线程环境下,性能高于logback等10倍以上;利用jdk1.5并发的特性,减少了死锁的发生;
在这列举一下一些网上其他博文中对它们的性能评测:
- 可以看到在同步日志模式下, Logback的性能是最糟糕的.
- log4j2的性能无论在同步日志模式还是异步日志模式下都是最佳的.
log4j2优越的性能其原因在于log4j2使用了LMAX,一个无锁的线程间通信库代替了,logback和log4j之前的队列. 并发性能大大提升。
2. 日志门面slf4j
上述介绍的是一些日志框架的实现,这里我们需要用日志门面来解决系统与日志实现框架的耦合性。SLF4J,即简单日志门面(Simple Logging Facade for Java),它不是一个真正的日志实现,而是一个抽象层( abstraction layer),它允许你在后台使用任意一个日志实现。
前面介绍的几种日志框架一样,每一种日志框架都有自己单独的API,要使用对应的框架就要使用其对应的API,这就大大的增加应用程序代码对于日志框架的耦合性。
使用了slf4j后,对于应用程序来说,无论底层的日志框架如何变,应用程序不需要修改任意一行代码,就可以直接上线了。
3. logBack
首先说明: springboot默认是用logback的日志框架
官方推荐使用的xml名字的格式为:logback-spring.xml而不是logback.xml,至于为什么,因为带spring后缀的可以使用 < springProfile > 这个标签。
在resource下创建logback-spring.xml文件;
3.1 配置文件模板
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
<!--<include resource="org/springframework/boot/logging/logback/base.xml" />-->
<contextName>logback</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<property name="log.path" value="D:/nmyslog/nmys" />
<!-- 彩色日志 -->
<!-- 彩色日志依赖的渲染类 -->
<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">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--输出到文件-->
<!-- 时间滚动输出 level为 DEBUG 日志 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_debug.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 WARN 日志 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_warn.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
以及指定<appender>。<logger>仅有一个name属性,
一个可选的level和一个可选的addtivity属性。
name:用来指定受此logger约束的某一个包或者具体的某一个类。
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
如果未设置此属性,那么当前logger将会继承上级的级别。
addtivity:是否向上级logger传递打印信息。默认是true。
-->
<!--<logger name="org.springframework.web" level="info"/>-->
<!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
<!--
使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
-->
<!--
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
不能设置为INHERITED或者同义词NULL。默认是DEBUG
可以包含零个或多个元素,标识这个appender将会添加到这个logger。
-->
<!--开发环境:打印控制台-->
<springProfile name="dev">
<logger name="com.nmys.view" level="debug"/>
</springProfile>
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
<!--生产环境:输出到文件-->
<!--<springProfile name="pro">-->
<!--<root level="info">-->
<!--<appender-ref ref="CONSOLE" />-->
<!--<appender-ref ref="DEBUG_FILE" />-->
<!--<appender-ref ref="INFO_FILE" />-->
<!--<appender-ref ref="ERROR_FILE" />-->
<!--<appender-ref ref="WARN_FILE" />-->
<!--</root>-->
<!--</springProfile>-->
</configuration>
其中说一下,彩色日志这个功能,需要下载插件,然后在yml或者properties中配置。
logging.config=classpath:log/logback-spring.xml
logging.path=D:/nmyslog/nmys
3.2 参考配置
实际xml配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 文件输出格式 -->
<property name="PATTERN"
value="[requestId:%X{requestId}] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。 -->
<property name="FILE_PATH" value="./logs"/>
<!--1. 输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<encoder>
<Pattern>${PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--2. 输出到文档-->
<!-- 2.1 level为 info 日志,时间滚动输出 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
<file>${FILE_PATH}/info.log</file>
<!--日志文档输出格式-->
<encoder>
<Pattern>${PATTERN}</Pattern>
<charset>UTF-8</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${FILE_PATH}/bat/info-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>500MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文档保留天数-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<!-- 此日志文档只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="async_info_log" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>10</queueSize>
<appender-ref ref="INFO_FILE"/>
</appender>
<!--3. 输出到文档-->
<!-- 3.1 level为 DEBUG 日志,时间滚动输出 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
<file>${FILE_PATH}/error.log</file>
<!--日志文档输出格式-->
<encoder>
<Pattern>${PATTERN}</Pattern>
<charset>UTF-8</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${FILE_PATH}/bat/error-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>250MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文档保留天数-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<!-- 此日志文档只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="async_error_log" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>10</queueSize>
<appender-ref ref="ERROR_FILE"/>
</appender>
<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
</root>
</configuration>
注意:
- 文件输出格式 %X{requestId}] 表示请求id,可以用来追踪日志的调用链,需要在代码中使用MDC.put(“requestId”, requestId);指定, 如果内部涉及到多线程,可以通过参数传递方式将requestId传入子线程代码中,并重新设置MDC.put(“requestId”, requestId);方法调用结束后需要手动移除:MDC.remove(“requestId”);
- 关于 < property name=“FILE_PATH” value=“./logs”/>配置,
name的值是变量的名称,value的值是变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。当前是写的相对路径, 也可以在启动脚本中指定:-Dlog.path=./logs 指定日志目录
此脚本采用的配置分离,配置文件为: application.properties
日志文件为: logback.xml
4. log4j2
4.1 引入Jar包
springboot默认是用logback的日志框架的,所以需要排除logback,不然会出现jar依赖冲突的报错。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions><!-- 去掉springboot默认配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency> <!-- 引入log4j2依赖 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
4.2 yml配置文件
如果自定义了文件名,需要在application.yml中配置
logging:
config: xxxx.xml
level:
cn.jay.repository: trace
默认名log4j2-spring.xml,就省下了在application.yml中配置
4.3 配置文件模版
log4j是通过一个.properties的文件作为主配置文件的,而现在的log4j2则已经弃用了这种方式,采用的是.xml,.json或者.jsn这种方式来做,可能这也是技术发展的一个必然性,因为properties文件的可阅读性真的是有点差。这里给出博主自配的一个模版,供大家参考。
<?xml version="1.0" encoding="UTF-8"?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration monitorInterval="5">
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--变量配置-->
<Properties>
<!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
<!-- %logger{36} 表示 Logger 名字最长36个字符 -->
<property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
<!-- 定义日志存储的路径 -->
<property name="FILE_PATH" value="更换为你的日志路径" />
<property name="FILE_NAME" value="更换为你的项目名" />
</Properties>
<appenders>
<console name="Console" target="SYSTEM_OUT">
<!--输出日志的格式-->
<PatternLayout pattern="${LOG_PATTERN}"/>
<!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</console>
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
<File name="Filelog" fileName="${FILE_PATH}/test.log" append="false">
<PatternLayout pattern="${LOG_PATTERN}"/>
</File>
<!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log" filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
</appenders>
<!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
<!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
<logger name="org.mybatis" level="info" additivity="false">
<AppenderRef ref="Console"/>
</logger>
<!--监控系统信息-->
<!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。-->
<Logger name="org.springframework" level="info" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<root level="info">
<appender-ref ref="Console"/>
<appender-ref ref="Filelog"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</configuration>
配置参数简介
在这里简单介绍下常用的配置参数
- 日志级别
机制:如果一条日志信息的级别大于等于配置文件的级别,就记录。
- trace:追踪,就是程序推进一下,可以写个trace输出
- debug:调试,一般作为最低级别,trace基本不用。
- info:输出重要的信息,使用较多
- warn:警告,有些信息不是错误信息,但也要给程序员一些提示。
- error:错误信息。用的也很多。
- fatal:致命错误。
- 输出源
- CONSOLE(输出到控制台)
- FILE(输出到文件)
- 格式
- SimpleLayout:以简单的形式显示
- HTMLLayout:以HTML表格显示
- PatternLayout:自定义形式显示
PatternLayout自定义日志布局:
%d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生产时间,输出到毫秒的时间
%-5level : 输出日志级别,-5表示左对齐并且固定输出5个字符,如果不足在右边补0
%c : logger的名称(%logger)
%t : 输出当前线程名称
%p : 日志输出格式
%m : 日志内容,即 logger.info(“message”)
%n : 换行符
%C : Java类名(%F)
%L : 行号
%M : 方法名
%l : 输出语句所在的行数, 包括类名、方法名、文件名、行数
hostName : 本地机器名
hostAddress : 本地ip地址
Log4j2配置详解
- 根节点Configuration
有两个属性:
status
monitorinterval
有两个子节点:
Appenders
Loggers(表明可以定义多个Appender和Logger).
status用来指定log4j本身的打印日志的级别.
monitorinterval用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s.
- Appenders节点
常见的有三种子节点:Console、RollingFile、File
Console节点用来定义输出到控制台的Appender.
- name:指定Appender的名字.
- target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT.
- PatternLayout:输出格式,不设置默认为:%m%n.
File节点用来定义输出到指定位置的文件的Appender.
- name:指定Appender的名字.
- fileName:指定输出日志的目的文件带全路径的文件名.
- PatternLayout:输出格式,不设置默认为:%m%n.
RollingFile节点用来定义超过指定条件自动删除旧的创建新的Appender.
- name:指定Appender的名字.
- fileName:指定输出日志的目的文件带全路径的文件名.
- PatternLayout:输出格式,不设置默认为:%m%n.
- filePattern : 指定当发生Rolling时,文件的转移和重命名规则.
- Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志.
- TimeBasedTriggeringPolicy:Policies子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am…而不是7am.
- SizeBasedTriggeringPolicy:Policies子节点,基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小.
- DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)。
- Loggers节点,常见的有两种:Root和Logger.
Root节点用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出
- level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < AppenderRef:Root的子节点,用来指定该日志输出到哪个Appender.
- Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。
- level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
- name:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点.
- AppenderRef:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root.如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity="false"只在自定义的Appender中进行输出。
4.4 参考配置
配置文件
<?xml version="1.0" encoding="utf-8"?>
<Configuration>
<Properties>
<!-- 文件输出格式 -->
<Property name="PATTERN">[requestId:%X{requestId}]%d{yyyy-MM-dd HH:mm:ss.SSS} |-%-5level [%thread] %c [%L] -| %msg%n</Property>
<!-- 此处可以不配置??????????因为启动脚本中已经指定 -->
<Property name="PATH">${sys:log.path}/logs</Property>
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${PATTERN}"/>
</Console>
<RollingFile name="risk-number-clean-info" fileName="${PATH}/risk-number-clean-info.log"
filePattern="${PATH}/$${date:yyyy-MM}/risk-number-clean-info-%d{yyyy-MM-dd}-%i.log.gz">
<Filters>
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
<ThresholdFilter level="error" onMatch="DENY"/>
</Filters>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="500MB"/>
</Policies>
<PatternLayout pattern="${PATTERN}"/>
</RollingFile>
<RollingFile name="risk-number-clean-error" fileName="${PATH}/risk-number-clean-error.log"
filePattern="${PATH}/$${date:yyyy-MM}/risk-number-clean-error-%d{yyyy-MM-dd}-%i.log.gz">
<Filters>
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="250MB"/>
</Policies>
<PatternLayout pattern="${PATTERN}"/>
</RollingFile>
</Appenders>
<Loggers>
<logger name="org.springframework" level="info"/>
<logger name="org.mybatis" level="info"/>
<Root level="info">
<AppenderRef ref="console" level="debug"/>
<AppenderRef ref="risk-number-clean-info" level="debug"/>
<AppenderRef ref="risk-number-clean-error" level="error"/>
</Root>
<AsyncLogger name="com.risk.number.clean" additivity="false" level="debug">
<appender-ref ref="console" level="debug"/>
<appender-ref ref="risk-number-clean-info" level="debug"/>
<appender-ref ref="risk-number-clean-error" level="error"/>
</AsyncLogger>
</Loggers>
</Configuration>
5. 参考启动脚本
start.sh
#!/bin/bash
source /etc/profile
cd /data/risk_number
BASE_DIR=$(pwd)
PID_FILE="$BASE_DIR/bin/.run.pid"
LOG_DIR="$BASE_DIR/logs"
if [ ! -d "$LOG_DIR" ];then
mkdir $LOG_DIR
fi
function running(){
if [ -f "$PID_FILE" ]; then
pid=$(cat "$PID_FILE")
if [ -z "$pid" ]; then
return 1;
fi
process=`ps aux | grep " $pid " | grep -v grep`;
if [ -z "$process" ]; then
return 1;
else
return 0;
fi
else
return 1
fi
}
if running; then
echo "Server is running."
exit 1
fi
nohup /usr/local/jdk1.8.0_191/bin/java -Xmx6G -Xms6G -DBASE_DIR=$BASE_DIR -Dlog.path=$BASE_DIR/logs -Dspring.config.location=$BASE_DIR/config/application.properties -Dlogging.config=file:$BASE_DIR/config/logback.xml -jar $BASE_DIR/lib/*.jar >>$LOG_DIR/info.log &
echo $! > $PID_FILE
chmod 755 $PID_FILE
sleep 1;
tail -f $LOG_DIR/info.log
stop.sh
#!/bin/bash
cd /data/risk_number/bin
BASE_DIR=$(pwd)
PID_FILE="$BASE_DIR/.run.pid"
function running(){
if [ -f "$PID_FILE" ]; then
pid=$(cat "$PID_FILE")
if [ -z "$pid" ]; then
return 1;
fi
process=`ps aux | grep " $pid " | grep -v grep`;
if [ -z "$process" ]; then
return 1;
else
return 0;
fi
else
return 1
fi
}
function stop_server() {
if ! running; then
echo "App is not running."
exit 1
fi
count=0
pid=$(cat ${PID_FILE})
while running;
do
let count=$count+1
echo "Stopping app $count times"
if [ ${count} -gt 60 ]; then
echo "kill -9 $pid"
kill -9 ${pid}
else
kill -15 ${pid}
fi
sleep 3;
done
rm ${PID_FILE}
echo "Stop successfully."
}
stop_server $@;
此脚本采用的配置分离,配置文件为: application.yml
日志文件为: log4j2.xml
此处没有指定application.yml的目录, 因为spring boot 启动会扫描以下位置的application.properties 或者application.yml文件作为spring boot 的默认配置文件 ,加载的优先由上到下,加载的时候,会把以下路劲的文件都加载一遍。不同的配置内容会全部加载到系统,对于重复的配置内容,优先级别高的配置文件内容会覆盖优先级别低的配置文件内容。
除了上述的文件目录以外,还可以用spring.config.location 参数的形式指定配置文件 :java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties ,如果上述的默认路劲有配置文件的话,会和配置内容会形成互补作用,相同的内容优先级别高的会覆盖优先级别低的。
6. 自动部署脚本
deploy.sh
#!/bin/bash
cd /data/sourcecode/risk-number-identification
git pull
mvn clean install package -Dmaven.test.skip=true -e -U
sleep 2
app_home=/data/risk-number-identification
cd $app_home
if [ ! -d /data/sourcecode/risk-number-identification/target ]; then
echo "请打包代码,再执行启动服务"
return 0
fi
if [ ! -d bat ]; then
mkdir bat
else
rm -rf bat/risk-*.jar
fi
if [ ! -d lib ]; then
mkdir lib
else
echo lib dir exist
fi
if [ ! -d logs ]; then
mkdir logs
else
echo logs dir exist
fi
if [ ! -f "./lib/risk-*.jar" ];then
mv ./lib/risk-*.jar bat/
else
echo "文件存在"
fi
cp /data/sourcecode/risk-number-identification/target/risk-*.jar ./lib/
pid_no=$(ps -ef | grep risk-number-identification | grep -v grep | awk '{print $2}')
if [ -n "$pid_no" ]; then
echo "stop risk-number-identification process pid:${pid_no}"
kill -15 "$pid_no"
sleep 15
else
echo "==============risk-number-identification stop success============"
fi
source /etc/profile
nohup java -jar -Xmx6G -Xms6G -Xdebug -Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=18000 -Dspring.config.location=$app_home/config/application.properties -Dlog.path=$app_home/logs -Dlogging.config=file:$app_home/config/logback.xml $app_home/lib/*.jar >/dev/null 2>>$app_home/logs/out.log 2>&1 &
#nohup java -jar -Xmx6G -Xms6G -DBASE_DIR=$app_home -Dlog.path=$app_home/logs -Dspring.config.location=$app_home/config/application.properties -Dlogging.config=file:$app_home/config/logback.xml $app_home/lib/*.jar >>$app_home/logs/info.log 2>&1 &
sleep 2
pid_no=$(ps -ef | grep risk-number-identification | grep -v grep | awk '{print $2}')
if [ -n "$pid_no" ]; then
echo "==============risk-number-identification server start success=========="
else
echo "==============risk-number-identification server start fail=========="
fi
前提条件:
- 安装好mvn及git;
- 在源码目录git clone 代码,并切换到正确的分支;
- 目录结构:
. - 保存git账号密码:
进入项目目录
命令:git config --global credential.helper store
然后会生成一个本地文件用于记录用户名和密码,这个文件我们无需关心
再次git pull一下,会让输入用户名和密码。这次输入之后以后就不会每次输入了。