程序园

初探log4j

2019-09-25  本文已影响0人  赵阳_c149

log4j 1.x

log4j是目前较为常用的日志框架,该项目由apache进行维护。(其他常见的日志框架还有java.util.logging,Logback)。Log4j相比较于System.out.println 的一个最大优势,就在于他将日志进行了归类,即划分了不同的优先级。通过优先级的划分,log4j可以控制输出哪些日志,不输出哪些日志。

那么log4j是如何做到的呢?我想从结构相对简单的log4j 1.x说起。事实上,从2015年 8月5日起,apache已经宣称不再继续维护Log4j 1,而转而支持Log4j 2【1】。Log4j 2在Log4j 1的基础上进行了一系列的增强和扩展,但是基本思路并没有本质的改变,即都是通过继承的层级实现了对日志输出的控制。Log4j 1的结构相对简单,所以本文将从Log4j 1开始讲起,介绍Log4j的基本思路,然后扩展到Log4j 2的一些特性。

在介绍log4j 1.x的组件之前,让我们首先看看他是如何对日志划分优先级的。默认情况下,日志的优先级按照从低到高的顺序可以列为:
TRACE,DEBUG,INFO,WARN,ERROR 和FATAL。
这些优先级的含义可以从其名字粗略的推断出来,详细的说明可以查看文档【2】。

简单来说log4j 1.x主要包含三个组件:Loggers,Appenders 和Layout。

Logger logger = LogManager.getLogger();logger.error("trace level");

Logger有自己的名字,他的名字是区分大小写的,logger和Logger之间通过名字定义继承关系。

Named Hierarchy
A logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of >the descendant logger name. A logger is said to be a parent of a child logger if there are no >ancestors between itself and the descendant logger.

举个简单的例子,一个命名为“com.foo”的logger是命名为“com.foo.Bar”的logger的父亲。在继承树的顶端是一个默认的根logger,由Log4j维护(类似java 类型树的根节点Object)。运行以下代码将创建一个logger,并将其加入以root logger为根的继承树

LogManager.getLogger()

如果不特殊指定,新创建的Logger从其祖先节点继承日志的优先级。

logger.error("trace level");

将向所有添加到该logger及其祖先的appender输出一条日志。

可以使用Configuration 文件对log4j 进行配置:

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

log4j 2

以上我们简单浏览了log4j 1 的一些基本特性,接下来我们看看在此基础上,log4j 2做了哪些改进。
首先来看一下log4j 2的架构图:


log_4_j_2.png

通过架构图,不难看出,log4j主要增加了一下几个组件:Filter,LoggerContext,LoggerConfig,StrSubsitutor和StrLookup【3】。下面逐一对其进行介绍。

  1. Accept:日志请求可以被处理,不管还有没有必要调用其他filter。
  2. Deny:日志请求将被直接返回。
  3. Neutral:日志请求将被传输给其他的filter。
    Filter是对依据logLevel(日志优先级)自动过滤机制的补充。

Named Hierarchy
A LoggerConfig is said to be an ancestor of another LoggerConfig if its name followed by a >dot is a prefix of the descendant logger name. A LoggerConfig is said to be a parent of >a child LoggerConfig if there are no ancestors between itself and the descendant >LoggerConfig.

举个简单的例子,一个命名为“com.foo”的LoggerConfig是命名为“com.foo.Bar”的LoggerConfig的父亲。在继承树的顶端是一个默认的根LoggerConfig,由Log4j维护。

每个在configuration 中声明的Logger都有一个LoggerConfig,不同Logger之间可能会共享同一个LoggerConfig。当创建一个logger的时候,将为其关联一个LoggerConfig,具体关联到哪个,遵从以下规则:

  1. LoggerConfig的名字和logger相同
  2. LoggerConfig的名字和父包相同。
  3. 根LoggerConfig
    每个LoggerConfig上关联着Filter和Appender,用于日志事件的实际分发。

总体来说,log4j 2在保留了log4j 1的诸多特性的同时,配置更加灵活,支持更多的场景(包括多线程),自动重加载, 支持基于context data,markers,regular 表达式,和其他组件的filter,此外,极大的改善了性能。

Sample

最后,是一个简单的sample。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Root level="error">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4jHelloWorld {
    public static void main(String...strings){
        Logger logger = LogManager.getLogger();
        logger.error("trace level");
    }
}
13:39:52.521 [main] ERROR Log4jHelloWorld - trace level

如果没有配置文件,运行没有问题,但是log4j会抱怨找不到配置文件,而且日志只会在console中输出。

ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2
13:37:48.723 [main] ERROR Log4jHelloWorld - trace level

【1】log4j 1.x
【2】log4j log level
【3】architecture
【4】Iptables
【5】Logging Separation
【6】commons-lang

上一篇下一篇

猜你喜欢

热点阅读