实践-log4j的使用(一)

本章内容阐述个人理解,以及使用方法。若有不正确的内容欢迎斧正。睡觉之前赶快记录下来免得有忘记了。

什么是Log?

  • 日志记录的是什么?市面上流行的软件基本都有日志记录功能,作为开发人员的好帮手。日志可以有效的记录程序运行的状态以及运行的异常,比如说操作系统蓝屏了、手机死机了、软件卡死、程序崩溃、写了BUG等等都会有对应的日志留下。

如何利用log?

  • 笔者是一个Java开发人员,本章内容代码部分已Java代码用例。大家都知道日志非常重要,但是经验不足的开发人员往往忽视了这个重要的手段,比如在控制台输出日志,所有输出信息都集中在一起。排除问题非常困难,一旦出现了线上异常信息首先要看的就是日志信息。所以有必要就日志手段多了解下。

我是如何操作的?

  • 最在开发一个客户端应用,并不是GUI那种程序。功能不多但是日志信息却很多,循环监控数据,所以运行期产生的日志也有点多,开发的时候毕竟简单调试还能接受,运行起来日志过于集中眼睛疼,为了方便调试以及排除问题,考虑先将日志经拆分。不同业务或者类型使用不同的log文件来记录。

用例

  • 这里简单的演示下如何将日志信息拆分到不同的文件中。

    添加日志依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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的运行环境下面演示基础的配置信息。
1
2
3
4
5
6
7
8
9
10
11
12
13
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用例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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所以都会输出。
1
2
3
4
5
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配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
  • 再次简单解释下配置的loggererrorFile 和 infoFile这是两个文件输出。
    • Append 是否运行追加内容。
    • File 文件存放地址
    • encoding 日志编码集
    • maxBackupIndex 最大存储文件个数
    • MaxFileSize 单个文件最大大小
    • Threshold 输出级别
    • FILE.DatePattern 切割日志的时候文件名称格式化
  • 依然是运行上面的Java代码,除了控制台会输出日志还会生成两个日志文件 infoFile、errorFile。依次看下日志文件中的内容。
1
2
3
4
# 文件 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

1
2
# 文件 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在日常开发中非常重要。确实不应该忽视它的存在,应该正确的使用。

END