Log配置教程及框架性能比较,看这篇就够了!

本文转载自微信公众号「Java极客技术」,作者鸭血粉丝 。转载本文请联系Java极客技术公众号。

一、摘要

不管是使用何种编程语言,何种框架,日志输出几乎无处不再,也是任何商业软件中必不可少的一部分。

总结起来,日志的用途大致可以归纳成以下三种:

问题追踪:通过日志不仅仅包括我们程序的一些bug,也可以在安装配置时,通过日志可以发现问题。

状态监控:通过实时分析日志,可以监控系统的运行状态,做到早发现问题、早处理问题。

安全审计:审计主要体现在安全上,通过对日志进行分析,可以发现是否存在非授权的操作。

以 Java 编程语言为例,打印日志的方式有很多,例如通过System.out.print()方法将关键信息输出到控制台,也可以通过 JDK 自带的日志Logger类输出,虽然 JDK 从1.4开始支持日志输出,但是功能单一,无法更好的满足商业要求,于是诞生了很多第三方日志库,像我们所熟悉的主流框架log4j、log4j2、logback等,提供的 API 功能都远胜 JDK 提供的Logger。

二、Log4j

2.1、介绍

Log4j 是一种非常流行的日志框架,由Ceki Gülcü首创,之后将其开源贡献给 Apache 软件基金会。

Log4j 有三个主要的组件:Loggers(记录器),Appenders (输出源)和Layouts(布局)。这里可简单理解为日志类别、日志要输出的地方和日志以何种形式输出。

综合使用这三个组件可以轻松地记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。

Log4j 的架构大致如下:

当我们使用 Log4j 输出一条日志时,Log4j 自动通过不同的Appender(输出源)把同一条日志输出到不同的目的地。例如:

  • console:输出到屏幕;
  • file:输出到文件;
  • socket:通过网络输出到远程计算机;
  • jdbc:输出到数据库

在输出日志的过程中,通过Filter来过滤哪些log需要被输出,哪些log不需要被输出。

在Loggers(记录器)组件中,级别分五种:DEBUG、INFO、WARN、ERROR和FATAL。

这五个级别是有顺序的,DEBUG < INFO < WARN < ERROR < FATAL,分别用来指定这条日志信息的重要程度,明白这一点很重要,Log4j有一个规则:只输出级别不低于设定级别的日志信息。

假设Loggers级别设定为INFO,则INFO、WARN、ERROR和FATAL级别的日志信息都会输出,而级别比INFO低的DEBUG则不会输出。

最后,通过Layout来格式化日志信息,例如,自动添加日期、时间、方法名称等信息。

具体输出样式配置,可以参考如下内容Log4j2 - Layouts布局介绍

2.2、项目应用

以 Java 项目为例,在 Maven 的pom.xml中添加如下依赖!

2.2.1、添加 maven 依赖

 
 
 
 
  1.     
  2.         org.slf4j
  3.         slf4j-api
  4.         1.6.6
  5.     
  6.     
  7.         org.slf4j
  8.         slf4j-log4j12
  9.         1.6.6
  10.     
  11.     
  12.         log4j
  13.         log4j
  14.         1.2.17
  15.     

2.2.2、创建log4j配置

在实际应用中,要使Log4j在系统中运行须事先设定配置文件。

配置文件实际上也就是对Logger、Appender及Layout进行相应设定。

Log4j支持两种配置文件格式,一种是XML格式的文件,一种是properties属性文件,二选一。

创建一个log4j.xml或者log4j.properties,将其放入项目根目录下。

1、XML格式

 
 
 
 
  1.     
  2.     
  3.         
  4.         
  5.         
  6.             
  7.             
  8.         
  9.     
  10.     
  11.     
  12.         
  13.         
  14.         
  15.         
  16.         
  17.         
  18.         
  19.             
  20.             
  21.         
  22.     
  23.     
  24.     
  25.         
  26.     
  27.     
  28.     
  29.     
  30.         
  31.         
  32.         
  33.     

2、XML格式

 
 
 
 
  1. log4j.rootLogger=INFO,M,C,E
  2. log4j.additivity.monitorLogger=false
  3. # INFO级别文件输出配置
  4. log4j.appender.M=org.apache.log4j.DailyRollingFileAppender
  5. log4j.appender.M.File=/logs/info.log
  6. log4j.appender.M.ImmediateFlush=false
  7. log4j.appender.M.BufferedIO=true
  8. log4j.appender.M.BufferSize=16384
  9. log4j.appender.M.Append=true
  10. log4j.appender.M.Threshold=INFO
  11. log4j.appender.M.DatePattern='.'yyyy-MM-dd
  12. log4j.appender.M.layout=org.apache.log4j.PatternLayout
  13. log4j.appender.M.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} %p %l %m %n
  14. # ERROR级别文件输出配置
  15. log4j.appender.E=org.apache.log4j.DailyRollingFileAppender
  16. log4j.appender.E.File=/logs/error.log
  17. log4j.appender.E.ImmediateFlush=true
  18. log4j.appender.E.Append=true
  19. log4j.appender.E.Threshold=ERROR
  20. log4j.appender.E.DatePattern='.'yyyy-MM-dd
  21. log4j.appender.E.layout=org.apache.log4j.PatternLayout
  22. log4j.appender.E.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} %p %l %m %n
  23. # 控制台输出配置
  24. log4j.appender.C=org.apache.log4j.ConsoleAppender
  25. log4j.appender.C.Threshold=INFO
  26. log4j.appender.C.layout=org.apache.log4j.PatternLayout
  27. log4j.appender.C.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %l %m %n

2.2.3、log4j使用

在需要打印日志的类中,引入Logger类,在需要的地方打印即可!

 
 
 
 
  1. package org.example.log4j.service;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. public class LogPrintUtil {
  5.     /**log静态常量*/
  6.     private static final Logger logger = LoggerFactory.getLogger(LogPrintUtil.class);
  7.     public static void main(String[] args){
  8.             logger.info("info信息");
  9.             logger.warn("warn信息");
  10.             logger.error("error信息");
  11.     }
  12. }

当然你还可以这样写

 
 
 
 
  1. if(logger.isInfoEnabled()) {
  2.     logger.info("info信息");
  3. }
  4. if(logger.isWarnEnabled()) {
  5.     logger.warn("warn信息");
  6. }

2.2.4、isInfoEnabled()有何作用呢?

简单来说,在某些场景下,用isInfoEnabled()方法判断下是能提升性能的!

例如我们打印这段内容logger.info("User:" + userId + appId),程序在打印这行代码时,先对内容("User:" + userId + appId)进行字符串拼接,然后再输出。

如果当前配置文件中日志输出级别是info,是直接输出的,当日志输出级别是error时,logger.info()的内容时不输出的,但是我们却进行了字符串拼接,如果加上if(logger.isInfoEnabled())进行一次判定,logger.info()就不会执行,从而更好的提升性能,这个尤其是在高并发和复杂log打印情况下提升非常显著。

另外,ERROR及其以上级别的log信息是一定会被输出的,所以只有logger.isDebugEnabled、logger.isInfoEnabled和logger.isWarnEnabled()方法,而没有logger.isErrorEnabled方法。

三、Log4j2

3.1、介绍

log4j2 是 log4j 1.x 的升级版,参考了 logback 的一些优秀的设计,并且修复了一些问题,因此带来了一些重大的提升,主要特点有:

  • 异常处理:在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异常处理机制。
  • 性能提升, log4j2相较于log4j 1和logback都具有很明显的性能提升,后面会有官方测试的数据。
  • 自动重载配置:参考了logback的设计,当然会提供自动刷新参数配置,最实用的就是我们在生产上可以动态的修改日志的级别而不需要重启应用——那对监控来说,是非常敏感的。
  • 无垃圾机制:log4j2在大部分情况下,都可以使用其设计的一套无垃圾机制,避免频繁的日志收集导致的jvm gc。

3.2、项目应用

3.2.1、添加 maven 依赖

 
 
 
 
  1.     
  2.     
  3.         org.slf4j
  4.         slf4j-api
  5.         1.7.13
  6.     
  7.     
  8.     
  9.         org.slf4j
  10.         jcl-over-slf4j
  11.         1.7.13
  12.         runtime
  13.     
  14.     
  15.     
  16.         org.apache.logging.log4j
  17.         log4j-api
  18.         2.4.1
  19.     
  20.     
  21.         org.apache.logging.log4j
  22.         log4j-core
  23.         2.4.1
  24.     
  25.     
  26.     
  27.         org.apache.logging.log4j
  28.         log4j-slf4j-impl
  29.         2.4.1
  30.     
  31.     
  32.     
  33.         com.lmax
  34.         disruptor
  35.         3.2.0
  36.     

3.2.2、创建log4j2配置

在项目的根目录下创建一个log4j2.xml的文件,与log4j相比,log4j2的异步输出日志性能非常强劲,配置如下:

1、同步输出日志

 
 
 
 
  1.     
  2.     
  3.         /logs/log4j2
  4.         /logs/log4j2/history
  5.     
  6.     
  7.         
  8.         
  9.         
  10.         
  11.         
  12.         
  13.             
  14.             
  15.         
  16.         
  17.         
  18.             
  19.             
  20.             
  21.             
  22.             
  23.                 
  24.                 
  25.                 
  26.             
  27.                
  28.             
  29.         
  30.         
  31.             
  32.             
  33.             
  34.                 
  35.                 
  36.             
  37.             
  38.         
  39.         
  40.             
  41.             
  42.             
  43.                 
  44.                 
  45.             
  46.             
  47.         
  48.     
  49.     
  50.     
  51.          
  52.         
  53.          
  54.         
  55.             
  56.         
  57.     

2、异步输出日志

 
 
 
 
  1.     
  2.     
  3.         /logs/log4j2
  4.         /logs/log4j2/history
  5.     
  6.     
  7.         
  8.         
  9.         
  10.         
  11.         
  12.         
  13.             
  14.             
  15.         
  16.         
  17.         
  18.             
  19.             
  20.             
  21.             
  22.             
  23.                 
  24.                 
  25.                 
  26.             
  27.                
  28.             
  29.         
  30.         
  31.             
  32.             
  33.             
  34.                 
  35.                 
  36.             
  37.             
  38.         
  39.         
  40.             
  41.             
  42.             
  43.                 
  44.                 
  45.             
  46.             
  47.         
  48.     
  49.     
  50.     
  51.          
  52.         
  53.             
  54.             
  55.         
  56.          
  57.         
  58.     

详细 API 可以参考官方网站!

3.2.3、log4j2使用

与 log4j 类似,直接在需要位置打印日志即可

 
 
 
 
  1. package org.example.log4j.service;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. public class LogPrintUtil {
  5.     /**log静态常量*/
  6.     private static final Logger logger = LoggerFactory.getLogger(LogPrintUtil.class);
  7.     public static void main(String[] args){
  8.             logger.info("info信息");
  9.             logger.warn("warn信息");
  10.             logger.error("error信息");
  11.     }
  12. }

四、Logback

4.1、介绍

Logback 也是用 java 编写一款非常热门的日志开源框架,由 log4j 创始人写的,性能比 log4j 要好!

logback 主要分为3个模块:

  • logback-core:核心代码模块
  • logback-classic:log4j的一个改良版本,同时实现了slf4j的接口,这样你如果之后要切换其他日志组件也是一件很容易的事
  • logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能

4.2、项目应用

4.2.1、添加 maven 依赖

 
 
 
 
  1.     ch.qos.logback
  2.     logback-classic
  3.     1.2.3
  4.     org.codehaus.janino
  5.     janino
  6.     2.7.8

4.2.2、创建logback配置文件

1、配置说明

logback在启动的时候,会按照下面的顺序加载配置文件:

  • 如果java程序启动时指定了logback.configurationFile属性,就用该属性指定的配置文件。如java -Dlogback.configurationFile=/path/to/mylogback.xml Test,这样执行Test类的时候就会加载/path/to/mylogback.xml配置
  • 在classpath中查找logback.groovy文件
  • 在classpath中查找logback-test.xml文件
  • 在classpath中查找logback.xml文件
  • 如果是jdk6+,那么会调用ServiceLoader查找 com.qos.logback.classic.spi.Configurator接口的第一个实现类
  • 自动使用ch.qos.logback.classic.BasicConfigurator,在控制台输出日志

上面的顺序表示优先级,使用java -D配置的优先级最高,只要获取到配置后就不会再执行下面的流程。相关代码可以看ContextInitializer#autoConfig()方法。

2、同步输出日志

 
 
 
 
  1.     
  2.     
  3.     
  4.     
  5.     
  6.     
  7.     
  8.     
  9.     
  10.       
  11.     
  12.     
  13.     
  14.     
  15.         value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{90} - %msg%n" />
  16.     
  17.     ${CONTEXT_NAME}
  18.     
  19.     
  20.         
  21.         
  22.             ${CUSTOM_LOG_PATTERN}
  23.             UTF-

    分享文章:Log配置教程及框架性能比较,看这篇就够了!
    标题路径:http://www.csdahua.cn/qtweb/news28/320478.html

    网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

    广告

    声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网