日志
1. 日志架构
日志一般构建在三个主要的类分为Logger、Appender、Layouts,再加一个过滤器Filters
三者之间的关系:
-
Logger (日志记录器)
被称为记录器,应用程序通过获取Logger对象,调用其API来来发布日志信息。Logger 通常时应用程序访问日志系统的入口程序。
Logger可以通过一下两个方法获取,
//JUL为例 //直接获取日志记录器 Logger logger = Logger.getLogger(String.valueOf(getClass())); //根据日志记录器工厂获取Logger Logger logger = LoggerFactory.getLogger(getClass());
-
Appender (日志输出目的地)
也被称为 Handlers (处理器),每个Logger都会关联一组Handlers,Logger会将日志交给关联 Handlers处理,由Handlers负责将日志做记录。Handlers在此是一个抽象,其具体的实现决定了 日志记录的位置可以是控制台、文件、网络上的其他日志服务或操作系统日志等。
Appender的类别有:Console(控制台)、File(文件)、JDBC(数据库)、JMS等等。
//JUL为例 //关闭系统默认配置 logger.setUseParentHandlers(false); //把日志输出到控制台 // a. 创建handler处理对象 ConsoleHandler consoleHandler = new ConsoleHandler(); // b. 设置日志输出位置 logger.addHandler(consoleHandler); //把日志输出到文件 // a. 创建handler对象 FileHandler fileHandler = new FileHandler("D:\\test.log"); // b. 设置日志输出位置 logger.addHandler(fileHandler); // e. 设置日志级别 logger.setLevel(Level.ALL); consoleHandler.setLevel(Level.ALL);
//还有其他的日志输出目的地,以log4j为例
//将日志信息输出到一个日志文件,并且每天输出到一个新的日志文件。
org.apache.log4j.DailyRollingFileAppender
//将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大小达到指定尺寸时,会自动把文件改名,同时产生一个新的文件。
org.apache.log4j.RollingFileAppender
//将日志信息以流格式发送到任意指定地方。
org.apache.log4j.WriteAppender
//通过JDBC把日志信息输出到数据库中。
org.apache.log4j.jdbc.JDBCAppender
-
Layouts (日志格式化)
也被称为Formatters (格式化器),它负责对日志事件中的数据进行转换和格式化。Layouts决定了 数据在一条日志记录中的最终形式。
-
SimpleFormatter:写简短的“人类可读”日志记录摘要。
-
XMLFormatter:写入详细的XML结构信息。
// c.创建formatter对象 SimpleFormatter simpleFormatter = new SimpleFormatter();
-
-
Filters (过滤器)
根据所要记录的信息进行指定的过滤,或者根据日志级别过滤掉低级别的日志。
常用的过滤器在框架内部基本都有实现,但是不尽相同。后面会根据不同的日志框架进行详细的讲解。
2. 日志级别
可能每个框架的日志隔离级别不尽相同,但是大多可能表示不同,含义相同,一下是以logback为例的日志级别。
日志级别 | 说明 |
---|---|
OFF | 关闭:最高级别,不打印日志。 |
Fatal | 致命:指明非常严重的可能会导致应用终止执行错误事件。 |
Error | 错误:指明错误事件,但应用可能还能继续运行。 |
Warn | 警告:指明可能潜在的危险状况。 |
Info | 信息:指明描述信息,从粗粒度上描述了应用运行过程。 |
Debug | 调试:指明细致的事件信息,对调试应用最有用。 |
Trace | 跟踪:指明程序运行轨迹,比DEBUG级别的粒度更细。 |
All | 所有:所有日志级别,包括定制级别。 |
//日志优先级别标准顺序为 ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
一般开发中常用的日志级别有四个分别为: Fatal、Error、Warn、Info、Debug
3. 日志框架之间的联系
日志架构之间的关系
日志架构主要包括日志门面和具体实现:
-
日志门面:统一抽象出来的一些接口
-
日志实现:定制了自己的日志 API ,并且有相应的具体实现
下图就是日志门面与日志之间的一些关系
如下图所示日志门面slf4j使用日志绑定包进行绑定具体的日志实现,一次来完成日志文件的记录。
日志门面
目前用于实现日志统一的框架 commons-logging、slf4j ,遵循面向接口编程的原则,这两大框架可以让用户在程序运行期间去选择具体的日志实现系统(log4j1\log4j2\logback等)来记录日志,是统一抽象出来的一些接口。
1. slf4j
从官网的描述看,slf4j只是一种日志的门面和日志抽象框架,而java.util.logging,log4j,logback都是slf4j抽象框架的具体实现,只要调用slf4j的API就可以集成任何的实现框架在一起。
-
SLF4J编译时静态绑定真正的Log库。使用SLF4J时,如果你需要使用某一种日志实现,那么你必须选择正确的SLF4J的jar包的集合(使用各种桥接包或者绑定包)。静态绑定性能优于采用运行时搜寻的方式。
-
优点:1、更好的可读性;
2、提高性能。
//SLF4J支持了占位符的日志记录、 提高了日志记录的性能 logger.info("my name is {}", "medusar");
2. commons-logging (JCL)
是apache最早提供的日志的门面接口。它的主要作用是提供一个日志门面,使用者可以使用不同的日志实现。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库。common-logging内部有一个Simple logger的简单实现,但是功能很弱。
-
JCL的原理是在运行时,动态查找日志框架实现,并为具体的日志框架实现提供适配器,将其转为JCL的接口。于是程序中可以统一使用JCL接口,并轻松切换日志框架实现。JCL内部有一个Simple logger的简单实现,但是功能很弱。
日志门面的实现
首先目前的日志框架有JDK自带的logging,log4j、logback ,这些框架都自己定制了日志 API ,并且有相应的实现
1. logging (JUL)
Java内部自带的日志工具,java.util.logging包下的各个类提供了原生的日志记录和输出支持。
-
API并不完善,对开发者不是很友好,而且对于日志的级别分类也不是很清晰,但是简单易上手,可以用在控制台进行查看日志记录
2. log4j
经典的一种日志解决方案。内部把日志系统抽象封装成Logger 、appender 、pattern等实现。我们可以通过配置文件轻松的实现日志系统的管理和多样化配置。pache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIXSyslog守护进程等;用户也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,用户能够更加细致地控制日志的生成过程。这些可以通过一个 配置文件来灵活地进行配置,而不需要修改程序代码。
-
使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、数据库等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
3. logback
Logback是由log4j创始人设计的又一个开源日记组件。logback当前分成三个模块:logback-core,logback-classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个改良版本。此外logback-classic完整实现SLF4J API使你可以很方便地更换成其它日记系统如log4j或JDK14Logging。logback-access访问模块与Servlet容器集成提供通过Http来访问日记的功能。
-
优点:
1、更快的实现:Logback的内核重写了,在一些关键执行路径上性能提升10倍以上,而且初始化内存加载也更小了;
2、自动重新加载配置文件,当配置文件修改了,Logback-classic能自动重新加载配置文件,扫描过程快且安全,它并不需要另外创建一个扫描线程;
3、支持占位符
4、自动清除旧的日志归档文件;
5、自动压缩归档日志文件;
6、Logback-access模块,提供了通过HTTP访问日志的能力,logback-access模块可与Jetty或者Tomcat进行集成,提供了非常丰富而强大的通过HTTP访问日志的功能。
门面模式
门面模式,是面向对象设计模中的结构模式,又称为外观模式。外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 简单理解就是通过门面模式对外提供一个统一的调用接口,屏蔽子系统之间复杂的调用关系,对客户端来讲,使用起来更容易。
commons-logging和slf4j就是这样,它们提供了日志的更高层次的抽象,具体的实现使用者不需要关心,而且可以自由选择。