1、描述
使用spring boot 记录多个项目的日志,日志太多,配置了logback ,但是只记录了日志,不输出堆栈的信息,不好排查问题。
2、配置logback
Maven配置
spring boot默认的日志框架是 log4j ,所以要保证这个日志能用需要去掉项目中所有的common-log
例如
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
配置logback
<?xml version="1.0" encoding="UTF-8"?>
<!-- 说明: 1. 文件的命名和加载顺序有关 logback.xml早于application.yml加载,logback-spring.xml晚于application.yml加载
如果logback配置需要使用application.yml中的属性,需要命名为logback-spring.xml 2. logback使用application.yml中的属性
使用springProperty才可使用application.yml中的值 可以设置默认值 -->
<configuration scan="true" scanPeriod="30 seconds">
<!-- 定义日志的根目录 -->
<property name="LOG_HOME" value="logs" />
<!-- 定义日志文件名称 -->
<property name="appName" value="hn-info"/>
<property name="py2java" value="py2java"/>
<property name="tax" value="tax"/>
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n%ex
</pattern>
</encoder>
</appender>
<!-- 日志文件输出 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log
</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4relative [%thread] %-5level %logger{35} - %msg%n%ex
</pattern>
</encoder>
</appender>
<!-- 日志文件输出 -->
<appender name="PYFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/${py2java}-%d{yyyy-MM-dd}-%i.log
</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4relative [%thread] %-5level %logger{35} - %msg%n%ex
</pattern>
</encoder>
</appender>
<appender name="TAXFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/${tax}-%d{yyyy-MM-dd}-%i.log
</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4relative [%thread] %-5level %logger{35} - %msg%n%ex
</pattern>
</encoder>
</appender>
<!-- ************************LOGGER开始****************************** -->
<!-- 全局日志记录器 -->
<!-- 级别依次为【从高到低】:FATAL > ERROR > WARN > INFO > DEBUG > TRACE -->
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
<!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 -->
<!-- 级别依次为【从高到低】:FATAL > ERROR > WARN > INFO > DEBUG > TRACE -->
<!-- additivity=false 表示匹配之后,不再继续传递给其他的logger -->
<logger name="cn.com.at.hb.py2java" level="DEBUG" additivity="false">
<appender-ref ref="PYFILE" />
<appender-ref ref="STDOUT" />
</logger>
<logger name="cn.com.at.hb.hninformation" level="DEBUG" additivity="false">
<appender-ref ref="FILE" />
<appender-ref ref="STDOUT" />
</logger>
<logger name="com.at21.hnbdc" level="DEBUG" additivity="false">
<appender-ref ref="TAXFILE" />
<appender-ref ref="STDOUT" />
</logger>
</configuration>
3、日志输出
获取堆栈的日志输出为字符串
public class ExceptionUtils {
public static void main(String[] args) {
try {
String a = "";
} catch (Exception e) {
ExceptionUtils.error(Logger, "", e);
}
}
public static void error(Logger log, String message, Exception e) {
log.error(e.getMessage());
log.error(message, e);
e.printStackTrace();
getMessage(e);
}
public static String getMessage(Exception e) {
try(StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
) {
// 将出错的栈信息输出到printWriter中
e.printStackTrace(pw);
pw.flush();
sw.flush();
return sw.toString();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}