摘要
你的Java程序是否被很多随即放置的System.out.println语句和stack traces(例如:ex.printStackTrace())弄乱呢?当你加入调试信息到工程中的类中,你的信息输出是否穿插于其他开发者的很多信息中,使得您的信息很难辨认和读取呢?你是否使用简单的日志API,并担心它可能不能提供您需要的足够的弹性和能力,当您的程序已存在于产品中时呢?如果以上的问题的答案都是Yes,到了你该选择一个工业级和强大的日志API和使用它的时候了!
这篇文章将通过评估两种广为使用的Java日志库:the Apache Group's Log4j和java.util.logging包(使用JUL代替),来帮助您选择日志API。这个文章调查了每一个库如何实现日志,评价他们的区别和相似点,并提供一些简单的指导路线,可以帮助您决定选择哪一个库。
Log4j的介绍
Log4j是一个开源日志库,被开发为Apache Software Foundation's日志服务项目的一个子项目。基于IBM开发的日志库早在1990年,它的第一个版本出现在1999。Log4j是一个广为使用在开源社区,包括一些大型项目比如JBoss和Hibernate。
Log4j的架构建立于三个大的概念上面:loggers,appenders,和layouts.(日志子,追加器,布局器)。这些概念允许开发者记录信息根据他们的类型和优先级,和来控制信息在哪结束以及他们的形式。loggers是你的应用程序首先调用的对象,用来初始化信息的日志记录。当loggers被给与一条信息来记录,loggers生成了Logging-Event对象来进行封装给定信息。该loggers此时交接LoggingEvents给它们关联的appender。Appenders发送LoggingEvents包含的信息到指定的输出目的地。例如,一个ConsoleAppender将信息写到System.out或者一个FileAppender将它附加于一个文件中。在发送LoggingEvent信息到最后输出目的地之前,一些appender使用布局器来创建以预期格式格式化的对于信息的文本表达。例如,Log4j包括了XMLLayout类来用于格式化loggingEvents以XML的字符串。
在Log4j中,LoggingEvent被赋予一个级别来指定他们的优先级。在Log4j中的默认级别(从高到低):OFF,FATAL,ERROR,WARN,INFO,DEBUG,和ALL.
Loggers和appenders也被分配到一个级别,并且只有当logging请求的级别比他们的级别相等并且更大时,才会执行。例如,如果一个appender他的级别是ERROR,它被请求输出一个有着WARN的级别的LoggingEvent,appender将不会写出被给与的logEvent。
Log4j中的所有loggers有一个名字。Log4j组织logger实例到一个树型的结构中,根据他们名字,同Java语言中的包的组织一样。正如Log4j的文档简洁的表述:“一个logger被认为是另外的logger的祖先,如果它的名字紧跟着一个点是后代的这个logger名字的前缀。”例如,一个名为"org.nrdc"被认为是"org"logger的子代。"org.nrdc.logging"logger是"org.nrdc" logger的子代,并且是"org" logger的重子代。如果logger的没有明确的指定级别,它会使用已经赋予级别的最近的父辈的级别。Loggers继承appenders从他们的父类,尽管他们也能被配置只使用直接赋给他们的appender。
当一个logger被请求来记录信息,它首先检查请求的级别是否比它的有效级别相同或者更大。如果是,它就创建LoggingEvent根据给定的信息,并传送LoggingEvent到它的appenders,格式它,并发送它到输出目的地。
JUL的介绍
java.util.logging包,Sun在2002年 Java SDK 1.4中介绍了它,作为JSR 47到来的,Logging API 规范。JUL非常类似于Log4j - 它多多少少的正确的使用了同样的概念,但是对他们重新命名了。例如,appenders 叫 “handlers”,layout 叫 “formatters”,并且LoggingEvent叫做“LogRecords”。图片1,汇总了Log4j和JUL的名称和概念。JUL使用级别与Log4j使用级别是一样的,并且JUL日志继承属性properties从他们父loggers中,有点像Log4j继承属性从父层次中。从Log4j到JUL概念几乎是一对一的;虽然两个库在细节上有所不同,任何熟悉Log4j的开发者只需要调整他们的词库就可以理解JUL。
功能不同点
虽然Log4j和JUL几乎有同样的概念,他们在功能上不同。他们的可以归纳为,“无论JUL能不能做成什么,Log4j都能做 - 并且做得更多。”他们主要在几个领域不同,appender/handler的实现,有用的格式化器/布局实现器,和配置灵活性上。
JUL包含4种具体的handler的实现,而Log4j则包括超过12个的appender实现。JUL的handler足够用来进行基本的日志记录 - 他们允许你写入到一个buffer,一个console,一个socket,和一个file中。Log4j的appenders,另一方面,大概覆盖了所有logging输出目的地你可以想到的。他们可以写到NT日志或者Unix syslog中,或者甚至发送Email。图片2提供了JUL的handler和Log4j的appenders的汇总。
JUL包含了两个格式化类:XMLFormatter和SimpleFormatter。Log4j包含了对应的布局器:XMLLayout和SimpleLayout.Log4j还提供了TTCCLayout,它格式化LoggingEvents到富内容字符串,和HTMLLayout,它可格式化LoggingEvent到HMTL表格中。
TTCCLayout和HTMLLayout都很有用,Log4j的确领先于JUL,在formatter/handler方面,由于PatternLayout。PatternLayout实例能够采用一个通过字符转换式模式而带来具有大量有弹性的被配置,类似于在C中的printf函数的表达式类型。在PatternLayout转换式模式中,特定转化字符被用来指定在布局格式化输出的信息。例如,"%t"被用来指定开始记录信息的线程;"%C"被用于开始记录信息的对象的类的名称;并且"%m"指定了信息。"%t: %m"将导致输出类似于这样"main thread:This is my message." "%C - %t:%m"会导致输出类似于"org.nrdc.My-Class - main thread:This is my message." Pattern-Layout非常有用,然而JUL的两个formatter类没有任何地方来匹配这样的多功能性。对于JUL使用者,自行定制formatter类是很少见,反之大多数Log4j用户通常需要学会如何使用PatternLayout转换式模式。
Log4j和JUL同时都能够使用配置文件进行配置,Log4j允许更广范围内的配置的可能性相对于JUL使用的配置文件。JUL能够使用.properties文件配置,但是到了J2SE5.0之前,handlers的配置只能是对于每一个类的而不是对于每一个实例。这就意味着如果你将使用Tiger版本的SDK,你将遗漏有用的配置选择,例如可以设置不同的FileHandler实例发送他们的输出到不同的文件中。
非常重要的,注意Tiger版的JUL能够很容易的被配置为写到多个文件,通过编写代码,而不是通过默认的配置机制。Log4j能够通过.properties文件或者XML文件配置,并且appenders能够以每一个实例为基础进行配置。同时,Log4j允许开发者关联布局实例和appender实例,并以每一个实例为基础进行配置布局。这包括PatternLayout实例 - 你能够设置转换式每一个模式的使用,在配置文件中。在开发过程中,通过重新编译来调整日志配置不是问题,开发结束后,然而,你或许不想通过重新编译来改变或者完全重新配置应用中的日志。这时,Log4j提供了更多的弹性,尤其使用Tiger。
Log4j提供了很多JUL缺少的功能,虽然JUL正在赶上。JUL可以完全扩展后,来做Log4j做的事情 - 你可以写更多的handlers,重新实现PatternLayout来为JUL,并且更新JUL配置机制,这些都不是很难。但是要在Log4j已存在这些特色数年时,为什么还做这些事呢?
你要选择哪一个库呢?
类似于这样的重要决定经常使得leaders失眠或者过早衰老。幸运的是,这个决定可以通过检测对于简单的问题后,容易的做出。
问题1
你过早需要那些JUL没有而Log4j有的handlers,例如SMTPHandler,NTEventLogHandler,或者其他任何非常便利的FileHandlers么?
问题2
你是否想频繁的切换你日志输出的格式?你是否需要简单的方式这样做?另外,你是否需要Log4j的PatternLayout?
问题3
你是否明确的需要在您的应用中有这种能力,来改变复杂的日志配置在您的应用中,即使他们已经被编译了并且部署到产品环境了?你的配置是不是听起来像:“来自这个类的几条信息通过邮件发送给技术支持工作者;类子集的几条信息被记录于我们服务器的syslog中;类子集的警告信息以一个文件记录于网络磁盘A中;并且各处所有信息以文件记录于网络磁盘B”?你是否没过10几天,就会改变一下?
如果你对上面的问题都回答Yes,使用Log4j。如果你的回答全是明确的No,JUL足够了,它已存在SDK中了。
结论
Log4j和JUL是非常相似的API。他们只在一些细节上不同,最后做的是同样的事情,除了Log4j有了更多的特色,但也许你用不到。
紧记,当你移植到你选择的日志库,那么日志将影响应用的性能。使得影响最小化的方法,就是尽量的重用loggers的引用;保存静态或者引用指针到loggers,而不是每次你需要一个logger时,调用Logger.getLogger("loggerName")。log表达式放置于公有区域,而不是循环中。
这篇文章不是深入研究如何使用Log4j或者JUL的教程,并且,实际上,演示了两个库很多的有用的特点,例如MBeans支持(J2SE5.0,你能够设置JUL记录级别远程的通过JMX),和ResourceBundle支持。还有很多Log4j的高级特点,例如filter链和Object-Renderers。因特网有很多如何使用他们的教程,JDJ中也有;在编码之前,一定找到并学习他们。
资源
Log4j's home page: http://logging.apache.org/log4j
JUL's home page: http://java.sun.com/j2se/1.4.2/docs/guide/util/logging
Aggarwal, V."Third Party Logging API." Java Developer's Journal, Vol. 5, issue 11: http://sys-con.com/story/?storyid=36144
Banes, J. "Building the Ultimate Logging Solution." Java Developer's Journal, Vol. 9, issue 5: http://sys-con.com/story/?storyid=44698
Writing a sweet Log4j Appender that sends instant messages: www.106.ibm.com/developerworks/java/library/j-instlog/
For those who don't like JUL or Log4j, try the Logging Toolkit for Java from IBM: www.alphaworks.ibm.com/tech/loggingtoolkit4j
转自: http://www.blogjava.net/lhulcn618/articles/16996.html
分享到:
相关推荐
详细介绍了java.util.logging.Logger的用法和结构,对如果扩展Logger起到抛砖引玉的作用!尊重劳动成果,亲下载了要给个评价!
log4j-1.2.16.jar,三个文件一起组成一个完整的日志输出,Apache的Common Logging只是一个高层的日志框架,本身并没有实现真正的写日志能力,而是依赖其它的日志系统如Log4j或者java本身的java.util.logging。...
tomcat默认使用Java.util.logging记录日志,默认只记录tomcat的日志,不记录应用的日志。tomcat支持采用log4j进行日志记录,配置方法如下: 1.更新最新的tomcat_juli.jar包到./bin/目录下; 2.拷贝log4j.jar,lo4j....
slf4j-log4j12-1.7.32.jar:用于绑定 1.2版的log4j , 这是一个广泛使用的日志系统,当然你还要把log4j包加到classpath中slf4j-jdk14-1.7.32.jar:用于绑定 java.util.logging, 作为JDK 1.4 的loggingslf4j-simple-...
Tomcat默认的日志是用java.util.logging,有几点不足,文件catalian.out不能像log4j一样按天生成,将越来越大。日志格式和项目中用log4j打出来的不一致,不利于解析。 从tomcat官网...
Java Util日志记录改进程序(JULI) 尽管很少有人将首选的框架java.util.logging (JUL)嵌入到Java中,所以它对最少的应用程序有帮助,但并不是最容易使用。 这个库轻轻地包装起来,使生活更轻松: 通过简化日志...
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. Exception in thread "main" java.lang.NullPointerException at java.lang.ProcessBuilder.start(ProcessBuilder.java:...
Log4j中是通过log4j.properties这个配置文件控制日志的输出,java logging中是通过logging.properties文件完成类似的功能。 Logging.properties文件位于JDK安装路径的 jre/lib/目录下,直接上配置文件: ...
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; ...
1.需要完成的任务 使用UserDaoImp1类和User类的相关方法,完成如下功能: (1)对空的User类对象调用getUserInfo()方法抛出的异常...实践四:使用log4j 需求说明 (1)使用log4j输出日志信息 (2)查看输出日志信息
它具有与 for log4j:trade_mark: 大致相当的功能,但强调稳定性、高性能和吞吐量。 与 Chainsaw 相比,它使用硬盘处理接收到的日志事件,而不是将它们保存在内存中。 因此,它能够同时处理来自多个来源的数百万个...
java.util.ServiceConfigurationError: org.apache.juli.logging.Log: Provider org .eclipse.jetty.apache.jsp.JuliLog 不是子类型 java.util.ServiceConfigurationError: org.apache.juli.logging.Log: Provider ...
Simple Logging Facade for Java (SLF4J) The Simple Logging ...Java的简单日志外观(SLF4J)作为各种日志框架(例如JavaUTIL日志记录、LogCub、Log4J)的简单外观或抽象,允许终端用户在部署时插入所需的日志框架。
Log4j vs Log4j2 vs Logback vs java.util.logging The Java log levels showdown: SEVERE FATAL ERROR OMG PANIC Chapter 3......................................................................................
如下所示: logging: config: classpath:spring-...org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under ‘logging.level’ to java.util.Map<java> … Caused by
ActiveMQ与Spring线程池整合的一个实例。 lib库没有上传。 对于实例的讲解,在竹子的论坛有我对这个实例的帖子...log4j-1.2.14.jar spring-2.0.jar xbean-spring-2.8.jar
Log4j(默认)默认配置文件:'config / trinidad-logging.properties' 登录默认配置文件:“ config / trinidad-logging.xml” java.util.logging默认配置文件:'config / trinidad-logging.properties' 要启用...
现在还有一个问题,假如你正在开发应用程序所调用的组件当中已经使用了 JCL 的,还有一些组建可能直接调用了 java.util.logging,这时你需要一个桥接器(名字为 XXX-over-slf4j.jar)把他们的日志输出重定向到 SLF4J...
只需一个简单的LogViewer(Java / Swing)即可查看由Java Logging-Framework生成的日志文件
logback-classic 模块可以看作是 log4j 的一个优化版本,它天然的支持 SLF4J,所以你可以随意的从其它日志框架(例如:log4j 或者 java.util.logging)切回到 logack。logback-access 可以与 Servlet 容器进行整合,...