日志

基础知识

日志

如图所示,应用调了sl4j-api,即日志门面接口。

 

日志门面接口本身通常并没有实际的日志输出能力,它底层还是需要去调用具体的日志框架API的,也就是实际上它需要跟具体的日志框架结合使用。

 

由于具体日志框架比较多,而且互相也大都不兼容,日志门面接口要想实现与任意日志框架结合可能需要对应的桥接器,上图红框中的组件即是对应的各种桥接器!

 

我们在代码中需要写日志,变成下面这么写

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//省略
Logger logger = LoggerFactory.getLogger(Test.class);
// 省略
logger.info("info");

在代码中,并不会出现具体日志框架的api。

程序根据classpath中的桥接器类型,和日志框架类型,判断出logger.info应该以什么框架输出!注意了,如果classpath中不小心引了两个桥接器,那会直接报错的!

案例实战

案例一

一个项目,一个模块用log4j,另一个模块用slf4j+log4j2,如何统一输出?

这里就要用上slf4j的适配器,slf4j提供了各种各样的适配器,用来将某种日志框架委托给slf4j。其最明显的集成工作方式有如下:

日志

根据题意应该选log4j-over-slf4j适配器,于是就变成下面这张图

日志

就可以实现日志统一为log4j2来输出

 

根据适配器工作原理的不同,被适配的日志框架并不是一定要删除!

 

以上图为例,log4j这个日志框架删不删都可以,你只要能保证log4j的加载顺序在log4j-over-slf4j后即可。

 

因为log4j-over-slf4j这个适配器的工作原理是,内部提供了和log4j一模一样的api接口,因此你在程序中调用log4j的api的时候,你必须想办法让其走适配器的api。如果你删了log4j这个框架,那你程序里肯定是走log4j-over-slf4j这个组件里的api。如果不删log4j,只要保证其在classpth里的顺序比log4j前即可!

logback.xml

参考文档:

http://www.51gjie.com/javaweb/1107.html

<--把日志输出到控制台-->
<appender name="ConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
  <encoder>
    <charset>UTF-8</charset>
    <pattern>${NORMAL_PATTERN}</pattern>
  </encoder>
</appender>

<!--滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件-->
<appender name="RuntimeAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <file>${LOG_HOME}/runtime.log</file>
  <encoder>
    <pattern>${NORMAL_PATTERN}</pattern>
  </encoder>
  <!--设置日志滚动的策略,这是使用按照时间滚动-->
  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <!--设置滚动生成文件的格式,这里设置的精确到天,也就是按照天滚动,如果时间设置精确到秒,就按秒来滚动-->
    <!--设置按天来滚动,前一天日志打印到23点59分,然后就一直没有请求日志,直到次日的1点才有新的日志进入,
        在0点到1点这个时间段,日志文件是不会滚动生成新的日志文件。因为滚动的动作是需要日志写入动作来触发-->
    <fileNamePattern>${LOG_HOME}/runtime.%d{yyyy-MM-dd}.log</fileNamePattern>
    <!--设定最大的文件数,比如按天滚动,这里设置了30天,在第31天日志生成的时候,第一天的日志就会被删掉-->
    <maxHistory>7</maxHistory>
  </rollingPolicy>
</appender>

<appender name="ErrorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <file>${LOG_HOME}/error.log</file>
  <encoder>
    <pattern>${NORMAL_PATTERN}</pattern>
  </encoder>
  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <fileNamePattern>${LOG_HOME}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
    <maxHistory>7</maxHistory>
  </rollingPolicy>
  <!--将过滤器的日志级别配置为INFO,所有INFO级别的日志交给appender处理,非INFO级别的日志,被过滤掉-->
  <filter class="ch.qos.logback.classic.filter.LevelFilter">
    <level>ERROR</level>
    <onMatch>ACCEPT</onMatch>
    <onMismatch>DENY</onMismatch>
  </filter>
</appender>

<!--用于存放日志对象,同时指定关联的package位置 -->
<!-- name指定关联的package -->
<!-- level表明指记录哪个日志级别以上的日志 -->
<!-- appender-ref指定logger向哪个文件输出日志信息 -->
<!-- additivity为true时,logger会把根logger的日志输出地址加入进来,但logger水平不依赖于根logger -->
<logger name="com.campus.o2o" level="${log.level}" additivity="true">
    <appender-ref ref="debugAppender" />
    <appender-ref ref="infoAppender" />
    <appender-ref ref="errorAppender" />
</logger>
<!-- 特殊的logger,根logger -->
<root lever="info">
    <!-- 指定默认的日志输出 -->
    <appender-ref ref="consoleAppender" />
</root>