栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

彻底搞懂混而不乱的Java日志体系

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

彻底搞懂混而不乱的Java日志体系

文章目录
  • 1 混而不乱的Java日志体系
    • 1.1 Java日志发展史
    • 1.2 JUL
    • 1.3 log4j
      • 1.3 .1 日志级别
      • 1.3.2 配置文件
    • 1.4 JCL
    • 1.5 Slf4j+logback
      • 1.5.1 依赖
      • 1.5.2 使用
      • 1.5.3 日志级别
      • 1.5.4 logback配置文件
        • ① 根节点
        • ② property
        • ③ 子节点 appender
          • Ⅰ ConsoleAppender
          • Ⅱ FileAppender
          • Ⅲ **RollingFileAppender**
        • ④ 子节点 logger
        • ⑤ 子节点Root
        • ⑥ logback配置实例
    • 1.6 slf4j+log4j2
  • 2 统一日志输出
    • 2.1 Slf4j适配器
    • 2.2 Slf4j桥接器
      • 场景应用

1 混而不乱的Java日志体系 1.1 Java日志发展史

  • 1999年Ceki推出log4j日志框架,并捐给Apache。Ceki也加入Apache组织。据说Apache基金会还曾经建议Sun引入Log4j到Java的标准库中,但Sun拒绝了。
  • 2002年Java1.4发布,Sun推出了自己的日志库JUL(Java Util Logging),其实现基本模仿了Log4j的实现。在JUL出来以前,Log4j就已经成为一项成熟的技术,使得Log4j在选择上占据了一定的优势;
  • 2003年Apache推出了JCL(Jakarta Commons Logging)。JCL只是定义了一套日志接口(其内部也提供一个Simple Log的简单实现),支持运行时动态加载日志组件的实现,也就是说,在你应用代码里,只需调用Commons Logging的接口,底层实现可以是Log4j,也可以是Java Util Logging;
  • 2006年,Ceki离开了Apache,回瑞典创建了QOS公司,然后先后创建了Slf4j(日志门面接口,类似于Commons Logging)和Logback(Slf4j的实现)两个项目;
  • 2012年,Apache眼看有被Logback反超的势头,于2012-07重写了Log4j 1.x,成立了新的项目Log4j 2,2014年7月其GA版本(正式发布版)发布。
1.2 JUL

Sun公司在 jdk1.4版本增加了一个日志包java.util.logging,简称为jul,用以对抗log4j。

  • JUL控制台输出使用System.err 进行日志输出


  • JUL日志输出级别

    日志级别从小到大,分别为:ALL

    输出所有:ALL

    非常详细: FINEST

    较详细: FINER

    详细: FINE

    配置: CONFIG

    信息: INFO

    警告: WARNING

    严重: SEVERE

    所有都不输出:OFF

    jul默认日志级别为INFO。默认配置文件在 %JAVA_HOME%/jre/lib/logging.properties

  • 使用方式

    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    //--------省略其他代码--------
    
    Logger logger=Logger.getLogger(JULService.class.getName());
    //方式1
    logger.log(Level.FINEST,"FINEST LOG");
    
    //方式2 简写
    logger.finest("finest log ");
    
    //--------省略其他代码--------
    
  • 配置文件

    默认配置文件在 %JAVA_HOME%/jre/lib/logging.properties

1.3 log4j

log4j最后一次更新时间是2012年。apache已不在维护,建议使用log4j2

1.3 .1 日志级别
级别描述
OFF最高级别,用于关闭日志记录。
FATAL导致应用程序提前终止的严重错误。一般这些信息将立即呈现在状态控制台上。
ERROR其他运行时错误或意外情况。一般这些信息将立即呈现在状态控制台上。
WARN使用已过时的API,API的滥用,潜在错误,其他不良的或意外的运行时的状况(但不一定是错误的)。一般这些信息将立即呈现在状态控制台上。
INFO令人感兴趣的运行时事件(启动/关闭)。一般这些信息将立即呈现在状态控制台上,因而要保守使用,并保持到最低限度。
DEBUG流经系统的详细信息。一般这些信息只记录到日志文件中。
TRACE最详细的信息。一般这些信息只记录到日志文件中
1.3.2 配置文件
  • 自定义输出格式说明

    %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
    %r 输出自应用启动到输出该log信息耗费的毫秒数
    %c 输出所属的类目,通常就是所在类的全名
    %t 输出产生该日志事件的线程名

    %m 用于输出与日志记录事件相关联的应用程序提供的消息。

    %n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n”
    %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
    %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。

  • Log4j提供的appender有以下几种:

    org.apache.log4j.ConsoleAppender(控制台),
    org.apache.log4j.FileAppender(文件),
    org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
    org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
    org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

  • log4j.properties 文件

    # 把logger和具体的appender关联起来
    log4j.rootLogger=INFO,stdout,R,error
    
    # stdout 输出到控台
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    # 日志输出级别
    log4j.appender.stdout.Threshold = TRACE 
    # stdout 输出格式
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    # %d{yyyy-MM-dd HH:mm:ss} [Thread: %t] %-5p %20c %L:%m %n   
    log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [Thread: %t] %-5p %20c %L:%m %n   
    
    # R 输出到文件 (文件大小到达指定尺寸的时候产生一个新的文件)
    log4j.appender.R=org.apache.log4j.RollingFileAppender
    log4j.appender.R.File=/log/example.log
    log4j.appender.R.Append = true
    # 日志输出级别
    log4j.appender.R.Threshold = ERROR 
    # 日志文件最大大小
    log4j.appender.R.MaxFileSize=100MB
    #保留最近的7个日志文件
    log4j.appender.R.MaxBackupIndex=7
    log4j.appender.R.layout=org.apache.log4j.PatternLayout
    log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [Thread: %t] %-5p %20c %L:%m %n
    
    #  输出到文件,每天产生一个日志文件,不会自动清除日志文件
    log4j.logger.error=error
    log4j.appender.error = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.error.DatePattern='_'yyyy-MM-dd'.log'
    log4j.appender.error.File = /log/error.log 
    log4j.appender.error.Append = true
    # 日志输出级别
    log4j.appender.error.Threshold = ERROR 
    log4j.appender.error.layout = org.apache.log4j.PatternLayout
    log4j.appender.error.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [Thread: %t] %-5p %20c %L:%m %n  
    
    
    log4j.logger.com.warybee=INFO
    
  • log4j.xml 文件

    
    
    
    
        
            
                
            
        
    
        
        
            
            
                
            
            
                
            
            
                
                
            
        
    
        
        
            
        
    
        
            
            
            
            
        
    
    
  • 使用

    添加依赖

    
        log4j
        log4j
        1.2.16
    
    
package com.warybee.service;

import org.apache.log4j.Logger;

public class Log4jTestService {

      private static Logger logger=Logger.getLogger(Log4jTestService.class);

      public void test1(){

            logger.trace("trace");
            logger.debug("logger");
            logger.info("info");
            logger.warn("warn");
            logger.error("error");
            logger.fatal("fatal");
      }
}
1.4 JCL

JCL,全称为"Jakarta Commons Logging"。最后一次更新2014年,差不多已经退出历史舞台。

commons-logging的目的是为“所有的Java日志实现”提供一个统一的接口,使项目与日志实现工具解耦,具体的日志实现可以是Log4j,也可以是Java Util Logging

  • 添加依赖包

    
        commons-logging
        commons-logging
        1.2
    
    
  • 使用

    package com.warybee.service;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    
    public class JCLService {
    
          private static Log log= LogFactory.getLog(JCLService.class);
          
          public void test1(){
              log.trace("trace");
              log.debug("log");
              log.info("info");
              log.warn("warn");
              log.error("error");
              log.fatal("fatal");
          }
    }
    

​ JCL默认使用JUL(Java Util Logging)进行日志输出

  • commons-logging+log4j

    • 添加log4j依赖

      
          log4j
          log4j
          1.2.16
      
      
    • 添加log4j配置文件

      参考上一节log4j配置

1.5 Slf4j+logback

JAVA简易日志门面(Simple Logging Facade for Java,缩写SLF4J)

1.5.1 依赖

    org.slf4j
    slf4j-api
    1.7.32


    ch.qos.logback
    logback-core
    1.2.6


    ch.qos.logback
    logback-classic
    1.2.6

1.5.2 使用
package com.warybee;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;

public class Slf4jService {

    final Logger logger = LoggerFactory.getLogger(Slf4jService.class);

    public void test1(String name){

        logger.info("param is {}",name);
    }
}
1.5.3 日志级别

SLF4J相比log4j去除了FATAL 级别。其他与log4j一样

级别描述
ERROR其他运行时错误或意外情况。一般这些信息将立即呈现在状态控制台上。
WARN使用已过时的API,API的滥用,潜在错误,其他不良的或意外的运行时的状况(但不一定是错误的)。一般这些信息将立即呈现在状态控制台上。
INFO令人感兴趣的运行时事件(启动/关闭)。一般这些信息将立即呈现在状态控制台上,因而要保守使用,并保持到最低限度。
DEBUG流经系统的详细信息。一般这些信息只记录到日志文件中。
TRACE最详细的信息。一般这些信息只记录到日志文件中
1.5.4 logback配置文件 ① 根节点

包含下面三个属性:

  • scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
  • scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
  • debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false

示例:



    

② property

可以用来设置变量,可以通过${name}来访问
示例:


   
    

③ 子节点 appender

负责写日志的组件,它有两个必要属性name和class。name指定appender名称,class指定appender的全限定名。下面只介绍常见的appder

Ⅰ ConsoleAppender

把日志输出到控制台,有以下子节点

  • :对日志进行格式化。
  • :字符串System.out(默认)或者System.err

    
    
    
    
        
            %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
        
    
    
    
        
    

Ⅱ FileAppender

把日志添加到文件,有以下子节点

  • :被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。
  • :如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true。
  • :对记录事件进行格式化。
  • :如果是 true,日志会被安全的写入文件,即使其他的FileAppender也在向此文件做写入操作,效率低,默认是 false。

    
    
    
    
         ${log.path}
         true
        
            %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
        
    

    
        
    

Ⅲ RollingFileAppender

滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。有以下子节点:

  • :被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。

  • :如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true

  • :当发生滚动时,决定RollingFileAppender的行为,涉及文件移动和重命名。属性class定义具体的滚动策略类

  • ch.qos.logback.core.rolling.TimebasedRollingPolicy

    最常用的滚动策略,它根据时间来制定滚动策略,有如下子节点:

    • 文件名称生成规则,默认格式是 yyyy-MM-dd
    • 控制保留的归档文件的最大数量,超出数量就删除旧文件
  • ch.qos.logback.core.rolling.SizebasedTriggeringPolicy

    根据当前活动文件的大小,如果超过指定大小会告知RollingFileAppender 触发当前活动文件滚动。


    
    
    
    
    
        ${log.path}/debug.log
        
            ${log.path}/debug.%d{yyyy-MM-dd}.%i.log
            100MB
            
            30
        
        
            %date [%thread] %-5level [%logger{50}] %file:%line - %msg%n
            UTF-8
        
    

    
        
    

④ 子节点 logger

用来设置某一个包或具体的某一个类的日志打印级别、以及指定

包含的属性有:

  • name属性:用来指定受此loger约束的某一个包或者具体的某一个类
  • level属性:用来设置打印级别,大小写无关:ALL,TRACE, DEBUG, INFO, WARN, ERROR,和OFF, 如果未设置此属性,那么当前loger将会继承上级的级别
  • addtivity属性:是否向上级logger传递打印信息。默认是true
  • 可以包含零个或多个元素,标识这个appender将会添加到这个logger。




⑤ 子节点Root
  • level属性:用来设置打印级别,大小写无关:ALL,TRACE, DEBUG, INFO, WARN, ERROR,和OFF, 如果未设置此属性,那么当前loger将会继承上级的级别
  • 可以包含零个或多个元素,标识这个appender将会添加到这个logger。

    
    

⑥ logback配置实例

    
    
    
    
        
            %date [%thread] %-5level [%logger{50}] %file:%line - %msg%n
        
    

    
    
         ${log.path}
         true
        
            %date [%thread] %-5level [%logger{50}] %file:%line - %msg%n
        
    
    
    
        ${log.path}/debug.log
        
            ${log.path}/debug.%d{yyyy-MM-dd}.%i.log
            100MB
            
            30
        
        
            %date [%thread] %-5level [%logger{50}] %file:%line - %msg%n
            UTF-8
        
    

    
    
        
        
        
    

1.6 slf4j+log4j2
         
            org.slf4j
            slf4j-api
            1.7.32
        

        
        
            org.apache.logging.log4j
            log4j-slf4j-impl
            2.14.1
        

        
        
            org.apache.logging.log4j
            log4j-core
            2.14.1
        
        
            org.apache.logging.log4j
            log4j-api
            2.14.1
        

log4j2配置文件




     
        
            log4j2_logs
        
    

    
    
    
        
        
        
        
    
        
    
    
        
        
    


    
    
        
            %5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n
        
        
            
            
        
        
            
            
            
        
    

    
    
        
            %5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n
        
        
            

            
            

        
        
            
            
        
    

    
    
        
            %5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n
        
        
            
        
        
            
            
        
    

    
    
        
            %5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n
        
        
            
        
        
            
            
        
    

    
    
        
            %5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n
        
        
            
        
        
            
        
    


    
        
        
        
        
            
            
            
            
            
            
            
        

    

2 统一日志输出 2.1 Slf4j适配器

图片来自官网:http://www.slf4j.org/manual.html

如果你想用slf4j作为日志门面的话,你如何去配合使用其他日志实现组件

  • slf4j + logback
    slf4j-api.jar + logback-classic.jar + logback-core.jar
  • slf4j + log4j
    slf4j-api.jar + slf4j-log4j12.jar + log4j.jar
  • slf4j + jul
    slf4j-api.jar + slf4j-jdk14.jar
  • 也可以只用slf4j无日志实现
    slf4j-api.jar + slf4j-nop.jar
2.2 Slf4j桥接器

图片来自官网文档:http://www.slf4j.org/legacy.html

  • jcl-over-slf4j.jar

    简化从 JCL 到 SLF4J 的迁移

  • log4j-over-slf4j

    简化从log4j 到 SLF4J 的迁移

  • jul-over-slf4j.jar
    简化从 JUL 到 SLF4J 的迁移

场景应用

自己的应用使用了slf4j+logback,引入的第三方框架使用的是log4j,此时如何桥接到slf4j进行统一管理?方法如下:

  1. 排除掉第三方框架的日志实现,第三框框架(log4j-demo)使用的log4j,要先排除掉。

    
        com.warybee
        log4j-demo
        1.0-SNAPSHOT
        
            
                log4j
                log4j
            
        
    
    
  2. 引入桥接器

    
        org.slf4j
        log4j-over-slf4j
        1.7.32
    
    
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/425022.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号