logback实践

Feb 8, 2017


logback

之前在学校做项目对日志并没有太多的概念,只是简单的认为log就如同sout(控制台输出)一样,只是为了调试错误而生

所以在实际项目中对log的记录并没有特别的在意,只是使用log4j+slf4j进行简单的日志记录

而到了公司之后,公司统一使用的是logback进行日志记录

然后我刚到对日志的理解很浅,就如同在学校一样只是为了sout

但是我觉得一个中心点并没有变,就是为了调试(便于调试)

举个简单的例子就是公司一般分dev,beta,prod环境,我们一般在本地根据产品需求开发完成然后本地测试成功之后发到dev进行自测, 发布过程我们一般需要盯着日志看看是否报错

如果这个过程依然使用sout进行输出,输出的记录会显得跟乱并且代码也不好维护

logback是一个开源日志组件,logback当前分成3个模块:

  • logback-core logback核心模块(公共模块),其它两个模块的基础模块
  • logback-access logback访问模块与Servlet容器集成提供通过Http来访问日志的功能
  • logback-classic logback实现slf4j api,可以方便的集成其它日志系统如log4j或java.util.logging

logback-project

为什么使用logback?

参考:从Log4j迁移到LogBack的理由

1. 快

因为logback是由log4j创始人设计的一个开源日志组件,所以logback针对log4j重写了内部实现,在保证logback的组建更加快速的同时,同时所需要的内存更加少

2. logback-classic 自然的实现了SLF4J

slf4j是一个日志门面框架,类似于提供了一个访问日志的api接口,比如:

private final static Logger log = LoggerFactory.getLogger(LogbackTest.class);

slf4j提供获取Logger对象的接口,而具体底层实现的log框架可自由选择

logback-slf4j

现在logback-classic自然实现了slf4j,所以如果需要切换其他的实现slf4j log框架(类如log4j),只需要替换一个jar包即可

3. 自动重新载入配置文件(logback.xml)

logback-classic可以在配置文件被修改后,自动重新载入,这个过程很快,无资源争用(即不需要另起一个线程去完成这个加载过程)

logback使用

在项目中使用logback所需要的组建如下:

  • logback-access-x.x.x.jar
  • logback-classic-x.x.x.jar
  • logback-core-x.x.x.jar
  • slf4j-api-x.x.x.jar

如果使用maven构建的话,在pom中加入以下依赖:

<dependency>
		<groupId>ch.qos.logback</groupId>
		<artifactId>logback-classic</artifactId>
		<version>x.x.x</version>
</dependency>

首先看看logback日志记录级别:

logback-level

分为5个级别,依次递增(定义于ch.qos.logback.classic.Level类)

遗漏了,logback还有一个特别的优势就是易于控制

我们可以很容易的通过定义指定日志的输出级别(level)来控制日志的输出

程序会打印高于或等于所设置级别的日志,如果设置级别为INFO,则优先级高于等于INFO级别(如:INFO、 WARN、ERROR)的日志信息将可以被输出,小于该级别的如DEBUG将不会被输出,默认情况下,这个级别是DEBUG

public class LogbackTest {

    private final static Logger log = LoggerFactory.getLogger(LogbackTest.class);
    
    public static void main(String[] args) {
        log.trace("test trace...");
        log.debug("test debug...");
        log.info("tets info...");
        log.warn("test warn...");
        log.error("test error...");
    }
}

在配置文件中设置ConsoleAppender过滤级别为trace,输出如下:

logback-level-out

logback配置文件—logback.xml

  • 尝试在 classpath下查找文件logback-test.xml;
  • logback-test.xml文件不存在,查找文件 logback.xml;
  • 两个文件都不存在,logback 用 BasicConfigurator 自动对自己进行配置,这会导致记录输出到控制台

示例配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">

        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>TRACE</level>
        </filter>

        <encoder charset="UTF-8"> <!-- encoder 可以指定字符集,对于中文输出有意义 -->
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">

        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>

        <!-- 可让每天产生一个日志文件,最多 10 个,自动回滚 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>/home/antsmarch/文档/LogTest/yngisht-%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>10</maxHistory>
        </rollingPolicy>

        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 输出到控制台和文件,可定义更多的 Appender -->
    <root level="DEBUG">
        <appender-ref ref="Console"/>
        <appender-ref ref="RollingFile"/>
    </root>

    <!-- 下面配置一些第三方包的日志过滤级别,用于避免刷屏 -->
    <logger name="org.springframework" level="WARN"/>
    <logger name="com.opensymphony" level="WARN"/>
    <logger name="org.apache" level="WARN"/>
    <logger name="com.qunar.travel.space.facade.impl.CommentFacadeImpl"
	level="info" additivity="false">
	  <appender-ref ref="RollingFile" />
   </logger>

    <!--日志异步到数据库 -->
    <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
        <!--日志异步到数据库 -->
        <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
            <!--连接池 -->
            <dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">
                <driverClass>com.mysql.jdbc.Driver</driverClass>
                <url>jdbc:mysql://127.0.0.1:3306/logtest</url>
                <user>username</user>
                <password>password</password>
           </dataSource>
        </connectionSource>
    </appender>

</configuration>

遇到的一个坑

由于刚接触logback,有些不理解其配置log记录的输出方式

在实际项目中,在beta环境上查看某个类输出的日志:

<logger name="com.qunar.travel.space.facade.impl.CommentFacadeImpl"
	  level="info" additivity="false">
	  <appender-ref ref="RollingFile" />
</logger>

当时不理解这个配置,所以在catalina.out文件中愣是找不到日志信息

原来实际的日志信息输出在comments.log文件中,这样可以通过不同的模块分离不同的日志信息,不用将整个项目的log全打在catalina.out文件中(减少文件压力)