1.前言
Logback日志是一款功能强大,使用最广泛的日志框架之一。下面给出logback在项目中配置方式,并对相关配置进行详细的解释。详细配置见官方文档:https://logback.qos.ch/manual/introduction.html.
2.添加logback依赖
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.logback-extensions</groupId>
<artifactId>logback-ext-spring</artifactId>
<version>0.1.4</version>
</dependency>
3.web.xml添加LogbackConfigListener
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>demo.root</param-value>
</context-param>
<context-param>
<param-name>logbackConfigLocation</param-name>
<param-value>classpath:config/logback.xml</param-value>
</context-param>
<!-- This listener should be registered before ContextLoaderListener in web.xml,
when using custom Logback initialization. -->
<listener>
<listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class>
</listener>
4. 配置文件logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- debug:默认为false,设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。
scan:配置文件如果发生改变,将会重新加载,默认值为true。
scanPeriod:检测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位时毫秒。
当scan为true时,这个属性生效,默认时间间隔为1min,单位有milliseconds, seconds, minutes or hours。
https://logback.qos.ch/manual/configuration.html#autoScan
-->
<configuration debug="true" scan="false" scanPeriod="1 hour">
<!-- 日志上下文名称,默认"default" -->
<contextName>logback</contextName>
<!-- 设置参数,通过${paramName}获取参数值。
https://logback.qos.ch/manual/configuration.html#definingProps -->
<property name="log.path" value="/logs/demo" scope="local"/>
<!-- 引用classpath中资源文件 -->
<property resource="config/log.properties"/>
<!-- 引用外部资源文件
<property file="src/main/java/chapters/configuration/variables1.properties" />-->
<!-- Setting a timestamp:https://logback.qos.ch/manual/configuration.html#timestamp -->
<timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss" timeReference="contextBirth"/>
<!-- Conditional processing of configuration files:https://logback.qos.ch/manual/configuration.html#conditional -->
<!-- ConsoleAppender, https://logback.qos.ch/manual/appenders.html#ConsoleAppender -->
<appender name="stdOut" class="ch.qos.logback.core.ConsoleAppender">
<!-- "System.out" or "System.err",默认 System.out-->
<target>System.out</target>
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default.
https://logback.qos.ch/manual/layouts.html#conversionWord -->
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!-- 日志输出过滤器,控制台只打印INFO级别的日志。
https://logback.qos.ch/manual/filters.html#levelFilter -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- FileAppender, https://logback.qos.ch/manual/appenders.html#FileAppender -->
<appender name="fileAppender" class="ch.qos.logback.core.FileAppender">
<!-- file必须 -->
<file>${log.path}/demo.log</file>
<append>true</append>
<!-- 可以设置immediateFlush=false提高吞吐量 -->
<immediateFlush>true</immediateFlush>
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- RollingFileAppender, https://logback.qos.ch/manual/appenders.html#RollingFileAppender
TimeBasedRollingPolicy(基于时间滚动策略), https://logback.qos.ch/manual/appenders.html#TimeBasedRollingPolicy -->
<appender name="daoRollingFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 非必须的-->
<file>${log.path}/dao.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/dao.%d{yyyy-MM-dd, UTC}.log.zip</fileNamePattern>
<!-- 最多保存30天的日志文件,但所有日志文件大小不能超过3GB -->
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- RollingFileAppender, SizeAndTimeBasedRollingPolicy(基于文件大小和时间滚动策略),
https://logback.qos.ch/manual/appenders.html#SizeAndTimeBasedRollingPolicy -->
<appender name="jobRollingFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/job.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/job.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
<!-- 最多保存30天的日志文件,每个日志文件最大20MB(默认10MB),但所有日志文件大小不能超过3GB -->
<maxHistory>30</maxHistory>
<maxFileSize>20MB</maxFileSize>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- RollingFileAppender,FixedWindowRollingPolicy(固定文件数滚动策略),
https://logback.qos.ch/manual/appenders.html#FixedWindowRollingPolicy -->
<appender name="serviceRollingFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<file>${log.path}/service.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/service.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
<!-- the lower bound for the window's index -->
<minIndex>1</minIndex>
<!-- the upper bound for the window's index -->
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<!-- 每个日志文件最大5MB -->
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!--DBAppender把日志事件保存到数据库中, https://logback.qos.ch/manual/appenders.html#DBAppender -->
<appender name="dbAppender" class="ch.qos.logback.classic.db.DBAppender">
<!-- DataSourceConnectionSource, 从连接池中获取连接 -->
<connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
<dataSource class="org.apache.tomcat.jdbc.pool.DataSource">
<driverClassName>${driverClassName}</driverClassName>
<url>${url}</url>
<username>${username}</username>
<password>${password}</password>
</dataSource>
</connectionSource>
<!-- JNDIConnectionSource, 需要再服务器中配置数据源 -->
<!-- <connectionSource class="ch.qos.logback.core.db.JNDIConnectionSource">
<jndiLocation>java:comp/env/jdbc/logging</jndiLocation>
</connectionSource> -->
<!-- DriverManagerConnectionSource, 每次调用都创建新的连接 -->
<!-- <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
<driverClass>${driverClassName}</driverClass>
<url>${url}</url>
<user>${username}</user>
<password>${password}</password>
</connectionSource> -->
</appender>
<!-- 其他类型的Appender -->
<!-- SocketAppender:https://logback.qos.ch/manual/appenders.html#SocketAppender -->
<!-- SMTPAppender:https://logback.qos.ch/manual/appenders.html#SMTPAppender -->
<!-- SyslogAppender:https://logback.qos.ch/manual/appenders.html#SyslogAppender -->
<!-- AsyncAppender:https://logback.qos.ch/manual/appenders.html#AsyncAppender -->
<!-- 不同包下的日志放在不同的文件中 -->
<logger name="com.wxyh.demo.dao" level="INFO" additivity="false">
<appender-ref ref="daoRollingFileAppender"/>
</logger>
<logger name="com.wxyh.demo.service" level="INFO" additivity="false">
<appender-ref ref="serviceRollingFileAppender"/>
</logger>
<logger name="com.wxyh.demo.web.job" level="INFO" additivity="false">
<appender-ref ref="jobRollingFileAppender"/>
<appender-ref ref="dbAppender"/>
</logger>
<!-- the level of the root level is set to DEBUG by default. -->
<root level="INFO">
<appender-ref ref="stdOut"/>
<appender-ref ref="fileAppender"/>
</root>
</configuration>
5. DBAppender
如果需要配置DBAppender,则需要事先在数据库中建好相关表,建表脚本在logback-classic-1.2.3.jar中ch.qos.logback.classic.db.script包下。下面给出mysql数据库的建表脚本。
BEGIN;
DROP TABLE IF EXISTS logging_event_property;
DROP TABLE IF EXISTS logging_event_exception;
DROP TABLE IF EXISTS logging_event;
COMMIT;
BEGIN;
CREATE TABLE logging_event
(
timestmp BIGINT NOT NULL,
formatted_message TEXT NOT NULL,
logger_name VARCHAR(254) NOT NULL,
level_string VARCHAR(254) NOT NULL,
thread_name VARCHAR(254),
reference_flag SMALLINT,
arg0 VARCHAR(254),
arg1 VARCHAR(254),
arg2 VARCHAR(254),
arg3 VARCHAR(254),
caller_filename VARCHAR(254) NOT NULL,
caller_class VARCHAR(254) NOT NULL,
caller_method VARCHAR(254) NOT NULL,
caller_line CHAR(4) NOT NULL,
event_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
COMMIT;
BEGIN;
CREATE TABLE logging_event_property
(
event_id BIGINT NOT NULL,
mapped_key VARCHAR(254) NOT NULL,
mapped_value TEXT,
PRIMARY KEY(event_id, mapped_key),
FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
);
COMMIT;
BEGIN;
CREATE TABLE logging_event_exception
(
event_id BIGINT NOT NULL,
i SMALLINT NOT NULL,
trace_line VARCHAR(254) NOT NULL,
PRIMARY KEY(event_id, i),
FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
);
COMMIT;
6.测试用例
@Component
public class JobExample4SpringTask {
private final Logger logger = LoggerFactory.getLogger("com.wxyh.demo.web.job");
private final AtomicInteger ai = new AtomicInteger(0);
@Scheduled(cron = "0/5 * * * * ?")
public void execute() {
int execBath = ai.incrementAndGet();
logger.debug("执行JobExample4SpringTask, 批次={}", execBath);
logger.info("执行JobExample4SpringTask, 批次={}", execBath);
logger.warn("执行JobExample4SpringTask, 批次={}", execBath);
logger.error("执行JobExample4SpringTask, 批次={}", execBath);
}
}
7.测试结果
7.1job.log日志文件
2017-10-19 16:30:00.002 [jobScheduler-1] INFO com.wxyh.demo.web.job - 执行SpringTask任务,taskName=JobExample4SpringTask
2017-10-19 16:30:00.183 [jobScheduler-1] WARN com.wxyh.demo.web.job - 执行SpringTask任务,taskName=JobExample4SpringTask
2017-10-19 16:30:00.189 [jobScheduler-1] ERROR com.wxyh.demo.web.job - 执行SpringTask任务,taskName=JobExample4SpringTask
2017-10-19 16:37:00.001 [jobScheduler-1] INFO com.wxyh.demo.web.job - 执行SpringTask任务,taskName=JobExample4SpringTask
2017-10-19 16:37:00.119 [jobScheduler-1] WARN com.wxyh.demo.web.job - 执行SpringTask任务,taskName=JobExample4SpringTask
2017-10-19 16:37:00.136 [jobScheduler-1] ERROR com.wxyh.demo.web.job - 执行SpringTask任务,taskName=JobExample4SpringTask
7.2logging_event表中日志数据