Java在设计之初,借鉴了很多其他语言不错的特性和优点,唯独没有设计日志系统,但是日志的重要性不言而喻,一旦程序运行起来,运行结果与预期不一致,基本就是出Bug了,这个时候需要进行Bug排查,一般有两种排查方式:1 断点单步调试,这种办法虽然精准,但是费时费力,而且项目如果是运行在生产环境下,无法进行此模式的排查.2将重要的信息输出到指定的文件,也就是日志,这种方式就算是项目在生产环境下也适用

Java中的IO在最初提供了System.err.println来供程序员打印日志,但是这种打印日志的方法只能输出到控制台,让控制台一团糟.

于是,江山代有才人出.有一位小伙子,姑且叫他小李.他在写项目的过程中也遇到了日志的问题.于是请教大师,大师给小伙子对日志设计提供了四点要求:

1. 日志消息除了能打印到控制台, 还可以输出到文件,甚至可以通过邮件发送出去(例如生成环境出错的消息)

2. 日志内容应该可以做格式化, 例如变成纯文本,XML, HTML格式等等

3. 对于不同的Java class,不同的 package , 还有不同级别的日志,应该可以灵活地输出到不同的文件中。

4.  能对日志进行分级, 有些日志纯属debug , 在本机或者测试环境使用, 方便程序员的调试, 生产环境完全不需要。有些日志是描述错误(error)的, 在生产环境下出错的话必须要记录下来,帮助后续的分析。

小李听完大师的话后茅塞顿开,拍着胸脯说:我一定会设计好这个日志系统来造福所有的Java程序员

小李回到家后开始分析需求,掏出一本面向对象设计.试图从需求中抽象出一些概念

首先要记录日志,肯定需要一个类来表达日志的概念,这个类至少应该有两个属性,一个是时间戳,一个是消息本身,把它叫做LoggingEvent吧,记录日志就像记录一个事件嘛。

其次是日志可以输出到不同的地方,控制台、文件、邮件等等, 这个可以抽象一下,不就是写到不同的目的地吗? 可以叫做LogDestination?

嗯, 还是简单一点,叫做Appender吧, 暗含了可以不断追加日志的意思。

至于第二条的日志内容可以格式化,完全可以比葫芦画瓢, 定义一个Formatter接口去格式化消息。

对了, Appender 应该引用Formatter ,这样以来就可以对LoggingEvent记录格式化以后再发送。

第三条需求把小李给难住了,不同的class, package 输出的目的地不同?  “目的地”这个概念是由Appender来表达的, 难道让不同的class, package 和Appender关联? 不不, 不能这样 !

还需要一个新的概念 , 这个概念是什么?

从用户角度想一下, 程序员要想获取日志,必须得先获取个什么东西,这个东西是不是可以称为Logger啊?  灵感的火花就闪了那么一下就被小李抓住了: 获取Logger的时候要传入类名或者包名!

这样一来,不同的class, package就区分开了, 然后让Logger 和Appender关联,灵活地设置日志的目的地, 并且一个Logger可以拥有多个Appender,同一条日志消息可以输出到多个地方, 完美!

小李迅速地画出了核心类的类图:

还算漂亮,小李陶醉着自我欣赏了一下。

再接再厉, 把第四条需求也设计一下,日志要分级,这个简单, 定义一个Priority的类,里边定义5个常量DEBUG, INFO, WARN, ERROR, FATAL, 表示5个不同的级别就OK了。当然这我5个级别有高低之分, DEBUG级别最低, FATAL级别最高。

还可以给Logger增加一些辅助编程的方法,如Logger.debug(....) , Logger.info(...)  , Logger.warn(...) 等等, 这样村民们将来就可以轻松地输出各种级别的日志了。

等一下, 大师还说过“对于所有的ERROR级别的日志,都输出到  errors.log文件中” 类似这样的需求, 好像给忽略了。

这也好办嘛, 只要在Appender上增加一个属性,就叫做Priority, 如果用户要输出的日志是DEBUG级别, 但是有个FileAppender的Priority是 ERROR级别,那这个日志就不用在这个FileAppender中输出了 ,因为ERROR级别比DEBUG级别高嘛。

同理, 在Logger类上也可以增加一个Priority的属性,用户可以去设置, 如果一个Logger的Priority是ERROR, 而用户调用了这个Logger的debug方法, 那这个debug 的消息也不会输出。

小李全心全意地投入到设计当中,一看时间, 都快半夜了, 赶紧休息, 明天向大师汇报去。

第二天, 小李给大师展示了自己设计的LoggerEvent, Logger , Appender, Formatter, Priority 等类和接口, 大师捻着胡子满意地点点头:“不错不错,与上一次相比有巨大的进步。你知不知道我在需求中其实给了你引导?”

“引导? 什么引导? ”

“就是让你朝着正交的方向去努力啊”

“正交? ”

‘“如果你把Logger, Appender, Formatter看成坐标系中的X轴,Y轴,Z轴, 你看看,这三者是不是可以独立变化而不互相影响啊?”

“我赛,果然如此,我可以任意扩展Appender接口而影响不到Logger和Formatter, 无论有多少个Logger 都影响不了Appender和Formatter , 这就是正交了?”

“是啊,当你从系统中提取出正交的概念的时候,那就威力无比了,因为变化被封装在了一个维度上,你可以把这些概念任意组合,而不会变成意大利面条似的代码。 ”

听到大师做了理论的升华, 小李兴奋得直搓手。

“好吧,你把这个设计实现了吧,对了,你打算叫什么名字? ”  大师问道

“我打算把他叫做Log4j , 意思是Log for Java”

“不错,就这么定了吧”

小李又花了两个月的时间把Log4j 开发了出来, 由于Log4j有着良好的设计,优异的性能, 很多Java程序员都爱上了它。

后来小李把Log4j 在Apache部落开源了, 这下子吸引了无数的人无偿帮助测试它,扩展它,改进它, 很快就成了帝国最流行的日志工具。

大师建议帝国把Log4j 纳入到JDK 中, Java帝国那效率低下的官僚机构竟然拒绝了。  消息传到了IO大臣的耳朵里,他不由的扼腕叹息: 唉,失去了一次极好的招安机会啊。 现在唯一的办法就是赶紧上奏皇上,在官方也提供一套,争取让臣民们使用官方版本。

到了第四代国王(JDK1.4),臣民们终于看到了帝国提供的java.util.logging包,也是用来记录日志的,并且其中的核心概念Logger, Formatter, Handler 和 Log4j非常相似,只是为时已晚, Log4j早已深入人心了, 不可撼动了。

Log4j 在Apache开源以后, 小李也逐渐地有点落寞,他闲不住又写了一个工具,叫做logback, 有了之前的经验,这logback 比log4j 还要快。

如今的日志世界有了很多的选择 ,除了java.util.logging, log4j 之外,还有logback,tinylog 等其他工具。

小李想了想, 这么多日志工具,用户如果想切换了怎么办?不想用log4j了,能换到logback吗?

我还是提供一个抽象层吧, 用户用这个抽象层的API来写日志, 底层具体用什么日志工具不用关心,这样就可以移植了。

小李把这抽象层就叫做Simple Logging Facade for Java,简称SLF4J。

对于Log4j , JDK logging, tinylog 等工具, 需要一个适配层, 把SLF4J 的API转化成具体工具的调用接口。

由于Logback这个工具也是出自小李之手, 直接实现了SLF4J的API,所以连适配层都不需要了, 用起来速度飞快,效率最高,SLFJ4+Logback 成为了很多人的最爱, 大有超越Apache Common Logging + Log4j 之势。

后记: 本文主要想讲一下日志工具的历史和现状, 尤其是Log4j核心的设计理念。

文中的小李其实就是Ceki Gülcü,他开发了Log4j , logback,以及slfj4, 为Java的日志事业做出了卓越的贡献。

 默默奉献的人有辣么多,今天只讲Ceki Gülcü ! 你可喜欢他? 来日还有更多欢喜,记得关注我哦   

本文来自 码农翻身

著名的Log4j是怎么来的?的更多相关文章

  1. log4cxx安装和使用

    log4cxx是Java社区著名的log4j的c++移植版,用于为C++程序提供日志功能,以便开发者对目标程序进行调试和审计,log4cxx是apache软件基金会的开源项目,基于APR实现跨平台支持 ...

  2. log4cxx入门第一篇--一个小例子

    先看官网:http://logging.apache.org/log4cxx/index.html 转载自:http://wenku.baidu.com/view/d88ab5a9d1f34693da ...

  3. C/C++log日志库比较

    事实上,在C的世界里面没有特别好的日志函数库(就像Java里面的的log4j,或者C++的log4cxx).C程序员都喜欢用自己的轮子.printf就是个挺好的轮子,但没办法通过配置改变日志的格式或者 ...

  4. 编译安装log4cxx

    1.介绍 Log4cxx是开放源代码项目Apache Logging Service的子项目之一,是Java社区著名的log4j的c++移植版,用于为C++程序提供日志功能,以便开发者对目标程序进行调 ...

  5. 在vs2010中编译log4cxx-0.10.0具体方法(从下载、编译、解决错误具体介绍)

    一. 简单介绍 log4cxx是Java社区著名的log4j的c++移植版.用于为C++程序提供日志功能,以便开发人员对目标程序进行调试和审计,log4cxx是apache软件基金会的开源项目,基于A ...

  6. log4cxx入门篇

    log4cxx入门篇     先看官网:http://logging.apache.org/log4cxx/index.html 转载自:http://wenku.baidu.com/view/d88 ...

  7. 【知识点】C++的日志框架

    常用的 C++ 日志框架 一.日志框架 一个经过专门设计的实用程序,用于规范应用程序的日志记录过程,就是日志框架.   日志框架可以自己编写(需要一定的能力哦),也可以由第三方(例如:log4cplu ...

  8. SLF4J和Logback和Log4j和Logging的区别与联系

    本文转载自:一个著名的日志系统是怎么设计出来的?(作者:刘欣) 前言 Java帝国在诞生之初就提供了集合.线程.IO.网络等常用功能,从C和C++领地那里吸引了大量程序员过来加盟,但是却有意无意地忽略 ...

  9. 利用log4j+mongodb实现分布式系统中日志统一管理

    背景     在分布式系统当中,我们有各种各样的WebService,这些服务可能分别部署在不同的服务器上,并且有各自的日志输出.为了方便对这些日志进行统一管理和分析.我们可以将日志统一输出到指定的数 ...

随机推荐

  1. Docker Compose 配置文件常用指令

    Docker Compose 配置文件常用指令 YAML文件格式及编写注意事项 YAML是一种标记语言很直观的数据序列化格式,可读性高.类似于XML数据描述语言,语法比XML简单的很多. YAML数据 ...

  2. springboot shiro和freemarker集成之权限控制完全参考手册(跳过认证,登录由三方验证,全网首发)

    本文主要考虑单点登录场景,登录由其他系统负责,业务子系统只使用shiro进行菜单和功能权限校验,登录信息通过token从redis取得,这样登录验证和授权就相互解耦了. 用户.角色.权限进行集中式管理 ...

  3. 获奖感想和python学习心得

    一,获奖感想 很荣幸能成为小黄杉的获得者,也很感谢老师对我的这份鼓励和期望.回顾本学期的python学习中,我从一名对编程一无所知的小白,成为一名刚入门的程序猿.首先,我要感谢我的任课老师娄嘉鹏老师, ...

  4. koa2 中 cookie 存在的中文问题

    koa2  中的 cookie 没办法直接设置中文,会报错 ‘ argument value is invalid ’ 解决办法: 先将它转成 ‘ base64 ’ 编码来存储 new Buffer( ...

  5. 运行软件出现:模块“msvcp110.dll”已加载,但找不到入口点DllRegister

    根据百度大多数回答来说 1:先是出现   无法启动程序,因为计算机丢失mfc110.dll 尝试重新安装该程序以解决问题 错误处理:下载或者在别人电脑上拷一份 如:'msvcp110.dll‘ 这类文 ...

  6. 王之泰201771010131《面向对象程序设计(java)》第六周学习总结

    第一部分:理论知识学习部分 第五章 第五章学习内容主要分为七个模块,分别为: 1.类.超类和子类: a. 类继承的格式: class 新类名extends已有类名. b. 已有类称为:超类(super ...

  7. Linux 软连接 (ln命令)

    这是linux中一个非常重要命令.它的功能是为某一个文件在另外一个位置建立一个同不的链接,这个命令最常用的参数是-s,具体用法是:ln -s 源文件 目标文件. 当我们需要在不同的目录,用到相同的文件 ...

  8. C#关于多线程及线程同步 lock锁的应用

    Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.D ...

  9. Windows Server 2008环境下Apache2.4+Tomcat8配置

    安装步骤 1. 安装配置JDK2. 安装配置Apache3. 安装配置Tomcat4. 启动服务并测试 一.Apache安装与配置 1.Apache解压在D盘根目录下建立一个文件夹Apache Gro ...

  10. 清晰的教你如何将 Maven 项目上传至 中央仓库以及版本更新

    项目中总会依赖一些大牛的开源库,例如 Android 开发 通过以下方式就可以方便的引入库.那么如何将我们自己的库也能这样来使用呢?下面我们将详细的讲解每一步的过程: implementation ' ...