Fork me on GitHub

Java中的日志管理

日志是应用程序运行中不可缺少的一部分,JAVA中有很多已经成熟的方案,尽管记录日志是应用开发中并不可少的功能,在 JDK 的最初版本中并不包含日志记录相关的 API 和实现。相关的 API(java.util.logging 包,JUL)和实现,直到 JDK 1.4 才被加入。因此在日志记录这一个领域,社区贡献了很多开源的实现。其中比较流行的包括 log4j 及其后继者 logback。除了真正的日志记录实现之外,还有一类与日志记录相关的封装 API,如 Apache Commons Logging 和 SLF4J。这类库的作用是在日志记录实现的基础上提供一个封装的 API 层次,对日志记录 API 的使用者提供一个统一的接口,使得可以自由切换不同的日志记录实现。比如从 JDK 的默认日志记录实现 JUL 切换到 log4j。这类封装 API 库在框架的实现中比较常用,因为需要考虑到框架使用者的不同需求。在实际的项目开发中则使用得比较少,因为很少有项目会在开发中切换不同的日志记录实现。

日志的实现

JAVA 中都有 java.util.logging, log4j ,logback,log4j2 等日志实现。其中logback是log4j作者觉得log4j已经太烂不想再改了,重新写的一个实现。Log4j本来一统江湖好好的,后来被人说方法上太多同步修饰符,在高并发下性能太烂。Netflix的blitz4j就重新实现了一次log4j项目,去掉了大量的同步修饰符,不过其负责人自己说,新项目还是建议直接用logback。不过,后来apache社区感觉slf4j和logback都是log4j作者开的qos.ch公司的产品,日志是件很重要的事情,不应该操控在一家公司手里。所以又以纯社区驱动搞了log4j2,参考了logback,也做了一些自己的改动。

SLF4J

http://www.slf4j.org/manual.html
SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只为各种日志实现提供一个简单统一的接口,从而使得最终用户能够在部署的时候配置自己希
望的实现。slf4j只是一个日志外壳,需要你加入slf4j-jdk14.jar, slf4j-log4j12.jar或logback.jar,将日志调用转发到实际的日志框架。在classpath中有哪个jar包,slf4j就会选择哪个实现。如果错误的同时存在多个jar包。比如:选择JDK自带的日志系统,则只需要将slf4j-api-xxx.jar和slf4j- jdk14-xxx.jar放置到classpath中即可,如果中途无法忍受JDK自带的日志系统了,想换成log4j的日
志系统,仅需要用slf4j-log4j12-xxx.jar替换slf4j-jdk14-xxx.jar即可(当然也需要log4j的jar及配置文件)。
替换默认的common-logging
有些第三方的工具包,已经直接使用了log4j, common-logging 或 java.util.logging。如果我们最后决定使用log4j做最终输出,则需要放一个jcl-over-slf4j.jar和 jul-to-slf4j.jar来替换common-logging或java.util.logging的api,将日志请求转发给 slf4j,slf4j再转发给log4j,此时还需要保证,classpath里没有common-logging.jar。 而原本直接使用log4j的就不需要做任何改动。
Maven中使用SLF4J替换Common-logging(比如默认的Spring就依赖Common-logging)

      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${spring.version}</version>
          <exclusions>
              <exclusion>
                  <artifactId>commons-logging</artifactId>
                  <groupId>commons-logging</groupId>
              </exclusion>
          </exclusions>
      </dependency>
则可以把Common-logging排除掉后,使用Jcl-over-slf4j来替代绑定关系
      <!--slf4j-->
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>${slf4j.version}</version>
      </dependency>
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>jcl-over-slf4j</artifactId>
          <version>${slf4j.version}</version>
      </dependency>
      <!--spring-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${spring.version}</version>
          <exclusions>
              <exclusion>
                  <artifactId>commons-logging</artifactId>
                  <groupId>commons-logging</groupId>
              </exclusion>
          </exclusions>
      </dependency>
如果slf4j找不到对应的绑定关系,就会提示如下错误

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

绑定关系对应表

As mentioned previously, SLF4J supports various logging frameworks. The SLF4J distribution ships with several jar files referred to as "SLF4J bindings", with each binding corresponding to a supported framework.

slf4j-log4j12-1.7.9.jar
Binding for log4j version 1.2, a widely used logging framework. You also need to place log4j.jar on your class path.
slf4j-jdk14-1.7.9.jar
Binding for java.util.logging, also referred to as JDK 1.4 logging
slf4j-nop-1.7.9.jar
Binding for NOP, silently discarding all logging.
slf4j-simple-1.7.9.jar
Binding for Simple implementation, which outputs all events to System.err. Only messages of level INFO and higher are printed. This binding may be useful in the context of small applications.
slf4j-jcl-1.7.9.jar
Binding for Jakarta Commons Logging. This binding will delegate all SLF4J logging to JCL.
logback-classic-1.0.13.jar (requires logback-core-1.0.13.jar)
Native implementation There are also SLF4J bindings external to the SLF4J project, e.g. logback which implements SLF4J natively. Logback's ch.qos.logback.classic.Logger class is a direct implementation of SLF4J's org.slf4j.Logger interface. Thus, using SLF4J in conjunction with logback involves strictly zero memory and computational overhead.

concrete-bindings

log4j

http://logging.apache.org/log4j/1.2/ 

log4j与slf4j是最常见的一种方式

image
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>1.7.10</version>
      </dependency>

log4j.properties

#Log4j
log4j.rootLogger=info,console

# 控制台日志设置
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
#log4j.appender.console.layout.ConversionPattern=%p %d{HH:mm:ss.SSS} [%X{ip}] - %l %m%n
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss.SSS} %-5p [%F\:%L]%x %m%n

# 文件日志设置
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
#log4j.appender.file.file=/opt/logs/test.log
log4j.appender.file.DatePattern='.'yyyy-MM-dd
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss.SSS} %-5p [%F\:%L]%x %m%n

web.xml

    <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>Log4j</param-value>
    </context-param>
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/log4j.properties</param-value>
    </context-param>
    <context-param>
        <param-name>log4jRefreshInterval</param-name>
        <param-value>10000</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>

JUnit
运行单元测试时,报以下错误
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See
http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
原因是找不到默认的log4j配置文件,可手动指定,如:
Log4jConfigurer.initLogging("classpath:log4j.test.properties");
log4j.test.properties是为执行单元测试类使用的一个配置文件

log4j2

http://logging.apache.org/log4j/2.x/  log4j2 是log4j的升级版

logback

http://logback.qos.ch/  logback是对slf4j的原生实现
Logstash

Refer:
Java 日志管理最佳实践
http://www.ibm.com/developerworks/cn/java/j-lo-practicelog/
为什么要使用SLF4J而不是Log4J
http://www.importnew.com/7450.html

posted @ 2014-12-26 14:44  花儿笑弯了腰  阅读(3916)  评论(2编辑  收藏  举报