日志组件
业务需求
在系统运行中,都需要记录运行日志,通过不同的配置指定不同内容和不同级别的日志输出到不同的存储,进一步利用日志记录的信息为系统进行监控排错、定位问题和优化性能。
解决方案
iuap后台日志中,统一使用slf4j+logback的方式进行日志的记录和输出,通过slf4j对各个日志组件的桥接器,适配不同日志件对日志的输出。 同时,日志组件采用slf4j和MDC的结合,可以在日志中记录如用户编号,线程调用唯一标识等指定信息,方便问题的追踪,为运维管理中如ELK方案追踪日志信息提供线索。
功能说明
- 支持适配不同日志组件对日志的输出;
- 支持日志不同输出级别的设置;
- 支持包、类不同粒度的日志输出设置;
- 结合MDC,支持日志中输出字段的自定义;
使用说明
配置logback.xml
在工程的classpath中加入logback的日志配置文件logback.xml,详细配置请参考示例工程
日志的配置中,可以配置日志的输出级别,输出格式,自定义输出变量等,还可以指定具体包下的日志输出级别。
示例配置文件如下
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{HH:mm:ss.SSS} [%X{call_thread_id}] [%X{current_user_name}] [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="rollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/tmp/logs/iuap-logexample.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/tmp/logs/iuap-logexample.%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%date{HH:mm:ss.SSS} [%X{call_thread_id}] [%X{current_user_name}] [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 可以定制某些包下的日志输出级别 -->
<logger name="com.yonyou.iuap" level="DEBUG" />
<!--log4jdbc是否支持 -->
<logger name="jdbc.connection" level="OFF" />
<logger name="jdbc.audit" level="OFF" />
<logger name="jdbc.resultset" level="OFF" />
<logger name="jdbc.sqlonly" level="OFF" />
<logger name="jdbc.sqltiming" level="OFF" />
<root level="DEBUG">
<appender-ref ref="console" />
<appender-ref ref="rollingFile" />
</root>
</configuration>
配置组件的Maven依赖
<dependency>
<groupId>com.yonyou.iuap</groupId>
<artifactId>iuap-log</artifactId>
<version>${iuap.modules.version}</version>
</dependency>
iuap.modules.version为在pom.xml定义的需要引用组件的版本。
注意:iuap-log组件默认引入对slf4j、logback和各种桥接包的依赖,内部依赖不需要再次引入,依赖如下:
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 代码直接调用log4j会被桥接到slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 代码直接调用common-logging会被桥接到slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 代码直接调用java.util.logging会被桥接到slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.googlecode.log4jdbc</groupId>
<artifactId>log4jdbc</artifactId>
<version>${log4jdbc.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
调用方式
在代码中声明logger
private static final Logger logger = LoggerFactory.getLogger(LogTest.class);
在业务代码中,调用logger的API输出各种级别的日志信息
/**
* 多参数示例
*/
@Test
public void testMultiParamsLog() {
logger.info("this is a {} log demo! level is:{}", "multi params", "info");
}
更多API操作和配置方式,请参考对应的示例工程(DevTool/examples/example_iuap_log)
常用接口
输出简单日志信息
/**
* 简单示例
*/
@Test
public void testSimpleLog() {
logger.info("this is a simple log demo!");
}
参数化输出日志
/**
* 参数化示例
*/
@Test
public void testParamsLog() {
logger.info("this is a params log demo! level is:{}", "info");
}
{}为参数占位符,“info”为要输出的参数的值。
多参数输出日志
/**
* 多参数示例
*/
@Test
public void testMultiParamsLog() {
logger.info("this is a {} log demo! level is:{}", "multi params", "info");
}
异常输出示例
/**
* 异常信息示例
*/
@Test
public void testExceptionLog() {
try {
String errNum = "123456a";
Integer.parseInt(errNum);
} catch (Exception e) {
logger.error("this is a {} demo! ", "exception log", e);
}
}
定制输出日志信息
/**
* MDC定制日志信息
*/
@Test
public void testMDCLog() {
MDC.put(LogConstants.CURRENT_USERNAME, "admin");
MDC.put(LogConstants.THREAD_CALLID, Thread.currentThread().getName());
logger.info("this is a mdc log demo!");
}
注意:MDC中放置的信息的可以在日志输出格式化中声明,格式如下: [%X{current_user_name}]