日志框架是用来记录程序的运行信息的。而对于一个成熟的Java应用,这个是必不可少的。在开发和调试阶段,日志可以帮助我们更快的定位问题;而在应用的运维过程中,日志系统又可以帮助我们记录大部分的异常信息,通常很多企业会通过收集日志信息来对系统的运行状态进行实时监控预警。
常见的日志框架
Log4j
Apache Log4j 是一个基于 Java 的日志记录工具。它是由 Ceki Gülcü首创的,现在则是 Apache 软件基金会的一个项目。 Log4j 是几种 Java 日志框架之一。
Log4j2
Apache Log4j 2 是 apache 开发的一款 Log4j 的升级产品。
Commons Logging
Apache 基金会所属的项目,是一套 Java 日志接口,之前叫 Jakarta Commons Logging,后更名为 Commons Logging。
Slf4j
类似于 Commons Logging,是一套简易 Java 日志门面,本身并无日志的实现。(Simple Logging Facade for Java,缩写 Slf4j)。
Logback
一套日志组件的实现(Slf4j 阵营)。
Jul (Java Util Logging)
自 Java1.4 以来的官方日志实现。
历史与选择
历史:
1996 年早期,欧洲安全电子市场项目组决定编写它自己的程序跟踪 API(Tracing API)。经过不断的完善,这个 API 终于成为一个十分受欢迎的 Java 日志软件包,即 Log4j。后来 Log4j 成为 Apache 基金会项目中的一员。
期间 Log4j 近乎成了 Java 社区的日志标准。据说 Apache 基金会还曾经建议 Sun 引入 Log4j 到 java 的标准库中,但 Sun 拒绝了。
2002 年 Java1.4 发布,Sun 推出了自己的日志库 JUL(Java Util Logging),其实现基本模仿了 Log4j 的实现。在 JUL 出来以前,Log4j 就已经成为一项成熟的技术,使得 Log4j 在选择上占据了一定的优势。
接着,Apache 推出了 Jakarta Commons Logging,JCL 只是定义了一套日志接口(其内部也提供一个 Simple Log 的简单实现),支持运行时动态加载日志组件的实现,也就是说,在你应用代码里,只需调用 Commons Logging 的接口,底层实现可以是 Log4j,也可以是 Java Util Logging。
后来(2006 年),Ceki Gülcü不适应 Apache 的工作方式,离开了 Apache。然后先后创建了 Slf4j(日志门面接口,类似于 Commons Logging)和 Logback(Slf4j 的实现)两个项目,并回瑞典创建了 QOS 公司,QOS 官网上是这样描述 Logback 的:The Generic,Reliable Fast&Flexible Logging Framework(一个通用,可靠,快速且灵活的日志框架)。
现今,Java 日志领域被划分为两大阵营:Commons Logging 阵营和 Slf4j 阵营。
Commons Logging 在 Apache 大树的笼罩下,有很大的用户基数。但有证据表明,形式正在发生变化。2013 年底有人分析了 GitHub 上 30000 个项目,统计出了最流行的 100 个 Libraries,可以看出 Slf4j 的发展趋势更好。Apache 眼看有被 Logback 反超的势头,于 2012-07 重写了 Log4j 1.x,成立了新的项目 Log4j 2, Log4j 2 具有 Logback 的所有特性。
关系:
Log4j 2 与 Log4j 1 发生了很大的变化,Log4j 2 不兼容 Log4j 1。
Commons Logging 和 Slf4j 是日志门面(门面模式是软件工程中常用的一种软件设计模式,也被称为正面模式、外观模式。它为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用)。Log4j 和 Logback 则是具体的日志实现方案。可以简单的理解为接口与接口的实现,调用者只需要关注接口而无需关注具体的实现,做到解耦。
比较常用的组合使用方式是 Slf4j 与 Logback 组合使用,Commons Logging 与 Log4j 组合使用。Logback 必须配合 Slf4j 使用。由于 Logback 和 Slf4j 是同一个作者,其兼容性不言而喻。
选择:
如果是在一个新的项目中建议使用 Slf4j 与 Logback 组合,这样有如下的几个优点。
- Slf4j 实现机制决定 Slf4j 限制较少,使用范围更广。由于 Slf4j 在编译期间,静态绑定本地的 LOG 库使得通用性要比 Commons Logging 要好。
- Logback 拥有更好的性能。Logback 声称:某些关键操作,比如判定是否记录一条日志语句的操作,其性能得到了显著的提高。这个操作在 Logback 中需要 3 纳秒,而在 Log4J 中则需要 30 纳秒。LogBack 创建记录器(logger)的速度也更快:13 毫秒,而在 Log4J 中需要 23 毫秒。更重要的是,它获取已存在的记录器只需 94 纳秒,而 Log4J 需要 2234 纳秒,时间减少到了 1/23。跟 JUL 相比的性能提高也是显著的。
- Commons Logging 开销更高
- Logback 文档免费。Logback 的所有文档是全面免费提供的,不像 Log4J 那样只提供部分免费文档而需要用户去购买付费文档。
Slf4j 的使用:
- Slf4j 的设计思想比较简洁,使用了 Facade 设计模式,Slf4j 本身只提供了一个 slf4j-apiversion.jar 包,这个 jar 中主要是日志的抽象接口,jar 中本身并没有对抽象出来的接口做实现。
- 对于不同的日志实现方案(例如 Logback,Log4j…),封装出不同的桥接组件(例如 logbackclassic-version.jar,slf4j-log4j12-version.jar),这样使用过程中可以灵活的选取自己项目里的日志实现。
![Slf4j 与其他日志组件的桥接说明](/Slf4j 与其他日志组件的桥接说明.jpg)
![Slf4j 与其他各种日志组件的桥接说明](/Slf4j 与其他各种日志组件的桥接说明.jpg)
具体的接入方式:
![Slf4j 具体接入方式](/Slf4j 具体接入方式.jpg)
日志实现
Log4j主要用于日志信息的输出。可以将信息分级别(严重fatal、错误error、警告warn、调式debug、信息info)按不同方式(控制台、文件、数据库)和格式输出。
实现步骤如下:
- 导入log4j的jar包(slf4j-api.jar、slf4j-log4j12.jar、log4jjar 共三个jar包);
- 在classpath下添加log4j.properties(名字不能改);
- 日志级别:debug(调试时用)、info、warn、error(运行时用)
- 在日志中我们可以看到执行的SQL语句,可以看到我们传递的参数
Log4j主要有以下3部分组件构成:
- 日志器(Logger):负责消息输出,提供了各种不同级别的输出方法;
- 输出器(Appender):负责控制消息输出的方式,例如输出到控制台、文件输出等;
- 布局器(格式器,Layout):负责控制消息的输出格式;
要在项目中打开日志,大家在资源文件根目录下创建一个log4j.properties的文件(名称不要修改),并把下面的代码拷备到里面:
#日志器logger #輸出器appender #布局器layout
#1.控制台输出
#指定日志器的输出级别和日志器的名称
#log4j.rootLogger=info,myconsole
#指定输出器
#log4j.appender.myconsole=org.apache.log4j.ConsoleAppender
#指定布局器
#log4j.appender.myconsole.layout=org.apache.log4j.SimpleLayout
#2.文件输出.txt
#指定日志器的输出级别和日志器的名称
#log4j.rootLogger=error,myfile
#指定输出器
#log4j.appender.myfile=org.apache.log4j.FileAppender
#log4j.appender.myfile.File=E:\\log4j.txt
#指定布局器(普通布局表示文本输出)
#log4j.appender.myfile.layout=org.apache.log4j.SimpleLayout
#3.文件输出.html
#指定日志器的输出级别和日志器的名称
#log4j.rootLogger=error,myhtml
#指定输出器
#log4j.appender.myhtml=org.apache.log4j.FileAppender
#log4j.appender.myhtml.File=D:\\log4j.html
#指定布局器(网页布局)
#log4j.appender.myhtml.layout=org.apache.log4j.HTMLLayout
#4.控制台输出+文件输出.txt
#指定日志器的输出级别和日志器的名称
#log4j.rootLogger=error,con,file
#指定输出器
#log4j.appender.con=org.apache.log4j.ConsoleAppender
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=D\:\\log4j.txt
#指定布局器(网页布局)
#log4j.appender.con.layout=org.apache.log4j.SimpleLayout
#log4j.appender.file.layout=org.apache.log4j.SimpleLayout
#5.控制台输出+自定义布局
log4j.rootLogger=DEBUG,my
#指定输出器
log4j.appender.my=org.apache.log4j.ConsoleAppender
#指定布局器(自定义布局)
#指定布局为自定义布局
log4j.appender.my.layout=org.apache.log4j.PatternLayout
#指定在自定义布局的格式,%d -- 表示当前系统时间,%t -- 执行该业务的线程名称,%p -- 日记器的级别,-5 -- 5表示
输出字符的个数,符号表示右对齐
#%c -- 表示指定业务所在的类的完全限定名(包名.类名),%m -- 输出额外信息,%n -- 表示换行
log4j.appender.my.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
#设置package(可以是自定义的包也可以是api的包)输出级别
log4j.logger.org.springframework=info
log4j.logger.cn.itsource=trace