在程序开发中,日志是一个很重要的角色,其主要用于记录程序运行的情况,以便于程序在部署之后的排错调试等。
(1)日志的作用及好处
查看程序的运行状态以及程序的运行轨迹,方便对程序进行分析。
系统问题排查,日志结合异常处理,可快速发现程序发生异常的地点。
查看系统运行时间,为系统性能优化提供相关的依据。
安全审计,通过系统日志分析,可以判断一些非法攻击,非法调用,以及系统处理过程中的安全隐患。
(2)最简单的日志
最简单的日志使用便是System.out.print()
public class Application(){
public static void main(String[] args){
// 设置日期格式
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// new Date()为获取当前系统时间
String beginTime = df.format(new Date());
System.out.print(beginTime + "程序开始了......");
...
...
...
String endTime = df.format(new Date());
System.out.print(endTime + "程序结束了......");
}
}
优点:直观、方便
缺点:
System.out.print
和java
运行程序运行在同一线程,业务程序会等待System.out.print
的动作,导致资源被占用。
System.out.print
是在控制台输出,只能输出到控制台,没有存储到日志文件当中。
不规范。
(3)日志框架
Java 拥有功能和性能都非常强大的日志库,但不幸的是,日志库并不止一个,如JUL(Java Util Log)
、JCL(Commons Logging)
、Log4j
、SLF4J
、Logback
、Log4j2
等等的日志工具,那么到底使用那一个呢?
日志最早出现的是Apache开源社区的Log4j
,此日志确实是应用最广泛的日志工具,成为了 Java 日志事实上的标准。之后, Java 的开发主体 Sun 公司为了抢回市场,在Jdk1.4
中增加了与Log4j
没有关联的 JUL(java.util.logging
)日志实现,用于对抗 Log4j
,但是却成为了 Java 目前记录日志局面混乱的开端。
当项目使用的第三方库使用了不同的日志工具时,就会造成一个应用中存在着多种日志的情况,由于各种日志之间互相没有关联,替换和统一日志工具也就变成了一件比较棘手的事情。为解决多种log工具存在的问题,Apache 开源社区提供了一个日志框架作为日志的抽象,叫 commons-logging
,也被称为 JCL
。JCL
会对各种日志接口进行抽象,抽象出一个接口层,实现对每个日志框架都进行适配,在使用日志工具时直接使用抽象接口即可,完成了各种主流日志框架的兼容实现(Log4j
、JUL
、simplelog
等),较好的解决了上述问题。
JCL
出现之后,元老级日志Log4j
的作者 觉得 JCL
不够优秀,所以他再度开发了一套更优雅的日志框架 SLF4J
(Simple Logging Facade for Java),即简单日志门面,并为 SLF4J
实现了一个亲儿子——logback
日志框架。在弄完后,觉得还是得照顾一下自己的“大儿子”log4j
,于是对log4j
进行升级,便出现了Log4j2
。
java common logging
和 SLF4J
都是日志的接口,供用户使用,而没有提供实现,Log4j
、JUL
、logback
、Log4j2
等等才是日志的真正实现。他们之间的关系可看作电脑与打印机设备之间的关系,电脑连接多台没有关联的打印机,用户只需用电脑选择打印机进行打印。不相同的是,当我们调用日志接口时,接口会自动寻找恰当的实现,返回一个合适的实例给我们服务。这些过程都是透明化的,用户不需要进行任何操作。(如不理解,请继续往后阅读)
日志级别
日志级别 | 日志描述 |
---|---|
OFF | 关闭:最高级别,不输出日志 |
FATAL | 致命:输出非常严重的可能会导致应用程序终止的错误。 |
ERROR | 错误:严重错误,主要是程序出错。 |
WARN | 警告:输出可能潜在的危险状况。 |
INFO | 信息:输出应用运行过程的详细信息。 |
DEBUG | 调试:输出更细致的对调试应用有用的信息。 |
TRACE | 跟踪:输出更细致的程序运行轨迹。 |
ALL | 所有:输出所有级别信息。 |
最常见的日志级别为Debug、Info、Warn、Error
日志优先级别从低到高顺序为:ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
最先出现的日志框架,是 Apache 的一个开源项目。使用Log4j可以通过配置文件来灵活进行配置,控制日志信息的输出格式和目标,而不需要修改程序代码。
使用日志级别
日志级别 | 日志描述 |
---|---|
OFF | 关闭:最高级别,不输出日志 |
FATAL | 致命:输出非常严重的可能会导致应用程序终止的错误。 |
ERROR | 错误:严重错误,主要是程序出错。 |
WARN | 警告:输出可能潜在的危险状况。 |
INFO | 信息:输出应用运行过程的详细信息。 |
DEBUG | 调试:输出更细致的对调试应用有用的信息。 |
TRACE | 跟踪:输出更细致的程序运行轨迹。 |
ALL | 所有:输出所有级别信息。 |
日志优先级别从高到低顺序为: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL
apache建议使用4级,即 ERROR、WARN、INFO、DEBUG
使用步骤
(1)引入相关依赖
log4j
log4j
1.2.12
(2)配置log4j
核心配置文件log4j.properties
先认识一下Log4j
三大组件Logger、Appender、Layout。
Logger: 日志记录器,日志记录的核心类,用于输出不同日志级别的消息。
Appender: 日志输出目标,用于指定日志输出的目的地,如控制台、文件等等。
Layout: 日志格式化器,用于指定日志按照什么格式输出,是日志输出的格式化器。
配置样例:
# Global logging configuration
######################### Logger ############################
# 设置日志输出级别以及输出目的地,等号后第一个参数写日志级别,级别后面写输出目的地,目的地名可自定义,多个目的地以逗号分开。
# 设置根Logger,默认输出DEBUG以上的记录,输出目标(appender)为CONSOLE、LOGFILE
log4j.rootLogger=DEBUG,CONSOLE,LOGFILE
######################### Appender #########################
# 对目标CONSOLE进行配置(与Logger对应)
# 设置日志目标类型为org.apache.log4j.ConsoleAppender控制台类型
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
# 输出到的目的地
log4j.appender.CONSOLE.Target = System.out
# 指定控制台输出日志级别
log4j.appender.CONSOLE.Threshold = DEBUG
# 默认值是 true, 表示是否立即输出
log4j.appender.CONSOLE.ImmediateFlush = true
# 设置编码方式
log4j.appender.CONSOLE.Encoding = UTF-8
# 设置日志输出布局方式Layout
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
# 如果日志输出布局为PatternLayout 自定义级别,需要使用ConversionPattern指定输出格式
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p (%c:%L) - %m%n
# 对目标LOGFILE进行设置(与Logger对应)
# 设置日志目标类型为org.apache.log4j.FileAppender文件类型
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
# 指定输出文件路径,相对路径或绝对路径
log4j.appender.LOGFILE.File =./logs/error.log
#日志输出到文件,默认为true
log4j.appender.LOGFILE.Append = true
# 指定输出日志级别
log4j.appender.LOGFILE.Threshold = ERROR
# 是否立即输出,默认值是 true,
log4j.appender.LOGFILE.ImmediateFlush = true
# 设置编码方式
log4j.appender.LOGFILE.Encoding = UTF-8
# 设置日志输出布局方式Layout
log4j.appender.LOGFILE.layout = org.apache.log4j.PatternLayout
# 如果日志输出布局为PatternLayout 自定义级别,需要使用ConversionPattern指定输出格式
log4j.appender.LOGFILE.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
rootLogger部分
总是存在一个rootLogger,即使没有显示配置也是存在的,并且默认输出级别为DEBUG,所有其他的Logger都默认继承自rootLogger
子Logger格式:log4j.logger.childName=INFO,appenderName1,appenderName2...
注意,在设置子Logger后,会造成appender叠加,即子Logger输出一次,父Logger也会输出一次,如果要限制叠加,则需要添加下面的语句:
log4j.additivity.childName=false
Appender部分
日志信息输出目的地类型
类型 | 描述 |
---|---|
org.apache.log4j.ConsoleAppender | 控制台 |
org.apache.log4j.FileAppender | 文件 |
org.apache.log4j.DailyRollingFileAppender | 每天产生一个日志文件 |
org.apache.log4j.RollingFileAppender | 文件大小到达指定尺寸的时候产生一个新的文件 |
org.apache.log4j.WriterAppender | 将日志信息以流格式发送到任意指定的地方 |
ConsoleAppender
控制台常配置属性
Threshold: 指定日志消息的输出最低日记级别。
ImmediateFlush: 默认值是true,意谓着所有的消息都会被立即输出。
Target:指定输出控制台,默认情况下是System.out
FileAppender
文件的常配置属性
Threshold:指定日志消息的输出最低日记级别。
ImmediateFlush:默认值是true,意谓着所有的消息都会被立即输出。
File:指定消息输出的文件路径。
Append:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。
RollingFileAppender
的常配置属性
Threshold:指定日志消息的输出最低日记级别。
ImmediateFlush:默认值是true,意谓着所有的消息都会被立即输出。
File:指定消息输出到mylog.txt文件。