本章内容阐述个人理解,以及使用方法。若有不正确的内容欢迎斧正。睡觉之前赶快记录下来免得有忘记了。
什么是Log?
- 日志记录的是什么?市面上流行的软件基本都有日志记录功能,作为开发人员的好帮手。日志可以有效的记录程序运行的状态以及运行的异常,比如说操作系统蓝屏了、手机死机了、软件卡死、程序崩溃、写了BUG等等都会有对应的日志留下。
如何利用log?
- 笔者是一个Java开发人员,本章内容代码部分已Java代码用例。大家都知道日志非常重要,但是经验不足的开发人员往往忽视了这个重要的手段,比如在控制台输出日志,所有输出信息都集中在一起。排除问题非常困难,一旦出现了线上异常信息首先要看的就是日志信息。所以有必要就日志手段多了解下。
我是如何操作的?
- 最在开发一个客户端应用,并不是GUI那种程序。功能不多但是日志信息却很多,循环监控数据,所以运行期产生的日志也有点多,开发的时候毕竟简单调试还能接受,运行起来日志过于集中眼睛疼,为了方便调试以及排除问题,考虑先将日志经拆分。不同业务或者类型使用不同的log文件来记录。
用例
这里简单的演示下如何将日志信息拆分到不同的文件中。
添加日志依赖
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
这里解释下为什么是log4j而不是其他的日志框架,因为依赖的某个基础库是使用log4j我也懒的去折腾就用这个吧。
- log4j配置文件
Log4j配置文件(Configreation File)就是记录器级别、存放位置、布局等等。通过该配置文件我们可以创建log4j的运行环境下面演示基础的配置信息。
log4j.debug=false
## 控制台输出
log4j.appender.stdoutAppender=org.apache.log4j.ConsoleAppender
log4j.appender.stdoutAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.stdoutAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{3} - %m%n
## The log level may be one of OFF, FATAL, ERROR, WARN, INFO,
## DEBUG, or ALL. The default level is defined as the first
## element in the list of values for the log4j.rootLogger
## property.
##
# 指定package
log4j.logger.z201.github.io.code.log.log4j = ALL , stdoutAppender
简单的解释下上面的配置信息
log4j.appender.stdoutAppender=org.apache.log4j.ConsoleAppender其中stdoutAppender简单的理解可以理解为日志Logger 的标识、ConsoleAppender就是日志的输出地方。log4j.appender.stdoutAppender.layout=org.apache.log4j.PatternLayout其中layout是布局,使用org.apache.log4j.PatternLayout来做布局。log4j.appender.stdoutAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{3} - %m%n这个就是布局的输出格式了。log4j.logger.z201.github.io.code.log.log4j = ALL , stdoutAppender指定程序package使用的log,并且指定日志级别ALL全部输出。- 这里简单介绍下log4j日志级别
Java用例代码
package z201.github.io.code.log.log4j;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestLog4j {
private static Logger log = LoggerFactory.getLogger(TestLog4j.class);
@Test
public void test01(){
log.info("log info");
log.error("log error");
log.warn("log warn");
log.trace("log trace");
log.debug("log debug");
}
}
- 由于日志级别是
ALL所以都会输出。
2018-06-13 00:05:13 INFO log.log4j.TestLog4j - log info
2018-06-13 00:05:13 ERROR log.log4j.TestLog4j - log error
2018-06-13 00:05:13 WARN log.log4j.TestLog4j - log warn
2018-06-13 00:05:13 TRACE log.log4j.TestLog4j - log trace
2018-06-13 00:05:13 DEBUG log.log4j.TestLog4j - log debug
尝试改造拆分日志
不同的日志级别输出到不同的日志文件中。简单介绍下日志级别LEVEL:OFF(关闭)FATAL(致命的) ERROR(错误)WARN(警告) INFO(信息)DEBUG (调试) ALL(所有) 输出日志的策略是由LEVEL决定的。
- 修改log4j配置文件
log4j.debug=false
## 控制台输出
log4j.appender.stdoutAppender=org.apache.log4j.ConsoleAppender
log4j.appender.stdoutAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.stdoutAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{3} - %m%n
#info日志信息
log4j.logger.infoFile=INFO,infoFile
log4j.appender.infoFile=org.apache.log4j.RollingFileAppender
log4j.appender.infoFile.Append=true
log4j.appender.infoFile.File=logs/infoFile.log
log4j.appender.infoFile.encoding=UTF-8
log4j.appender.infoFile.maxBackupIndex=30
log4j.appender.infoFile.MaxFileSize=15MB
log4j.appender.infoFile.Threshold=INFO
log4j.appender.infoFile.FILE.DatePattern='.'yyyy-MM-dd-HH-mm'.log'
log4j.appender.infoFile.layout=org.apache.log4j.PatternLayout
log4j.appender.infoFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%5p] - %F(%L) - %m%n
#error日志信息
log4j.logger.errorFile=ERROR,errorFile
log4j.appender.errorFile=org.apache.log4j.RollingFileAppender
log4j.appender.errorFile.Append=true
log4j.appender.errorFile.File=logs/errorFile.log
log4j.appender.errorFile.encoding=UTF-8
log4j.appender.errorFile.maxBackupIndex=30
log4j.appender.errorFile.MaxFileSize=15MB
log4j.appender.errorFile.Threshold=ERROR
log4j.appender.errorFile.FILE.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.errorFile.layout=org.apache.log4j.PatternLayout
log4j.appender.errorFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%5p] | %m%n
## The log level may be one of OFF, FATAL, ERROR, WARN, INFO,
## DEBUG, or ALL. The default level is defined as the first
## element in the list of values for the log4j.rootLogger
## property.
##
# system logs
log4j.logger.z201.github.io.code.log.log4j=ALL , infoFile , errorFile , stdoutAppender
- 再次简单解释下配置的logger
errorFile 和 infoFile这是两个文件输出。- Append 是否运行追加内容。
- File 文件存放地址
- encoding 日志编码集
- maxBackupIndex 最大存储文件个数
- MaxFileSize 单个文件最大大小
- Threshold 输出级别
- FILE.DatePattern 切割日志的时候文件名称格式化
- 依然是运行上面的Java代码,除了控制台会输出日志还会生成两个日志文件 infoFile、errorFile。依次看下日志文件中的内容。
# 文件 infoFile.log
2018-06-13 00:12:40 [ INFO] - TestLog4j.java(13) - log info
2018-06-13 00:12:40 [ERROR] - TestLog4j.java(14) - log error
2018-06-13 00:12:40 [ WARN] - TestLog4j.java(15) - log warn
# 文件 errorFile.log
2018-06-13 00:12:40 [ERROR] | log error
这里有一个疑问为什么infoFile里面输出的内容多点。这依然和日志的LEVEL有关系,由于INFO级别大小的问题,INFO级别的日志会输出别它大的级别日志。也就是设置成INFO的时候会输出 WARN 、ERROR、FATAL。而且log4j建议使用 DEBUG、INFO、WARN、ERROR这四种。
补充一点内容
实际上日志的拆分我们已经大概目的了,现在补充下其他的Appenders便于参考业务场景使用。
- org.apache.log4j.ConsoleAppender(控制台) org.apache.log4j.FileAppender(文件)
- org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
- org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
- org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
还有 Layouts的使用,列举下。
- org.apache.log4j.HTMLLayout(以HTML表格形式布局)
- org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
- org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
- org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)
简单的拆分日志就到这里了,log4j在日常开发中非常重要。确实不应该忽视它的存在,应该正确的使用。