Log4j2研究之lookup

一个称得上优秀的框架,必备的要素之一可以通过某种约定的格式读取到所运行环境中的配置信息。本文中我们就来感受下log4j2实现此项功能时的精妙设计。

1. 概述

“ Lookups provide a way to add values to the Log4j configuration at arbitrary places. They are a particular type of Plugin that implements the StrLookup interface. ”

以上内容复制于log4j2的官方文档lookup - Office Site。其清晰地说明了lookup的主要功能就是提供另外一种方式以添加某些特殊的值到日志中,以最大化松散耦合地提供可配置属性供使用者以约定的格式进行调用

2. 配置示例

以下列举了两个主要使用的位置;当然不仅仅如此,log4j2允许你在任何需要的地方使用约定格式来获取环境中的指定配置信息。

<properties>
   
  <property name="logPath">${sys:catalina.home}/xmlogsproperty>
properties>



<PatternLayout pattern="[${hostName}];[${thread:threadName}];[%X{user}];[$${ctx:user}];[$${date:YYYY-MM/dd}]" />

3. 继承链

在开始构建自定义lookup逻辑前,我们先来看看log4j2已经为我们提供了的各类lookup实现;这样既可以避免作些无用功,也能在我们的自定义实现中最大化地复用现有代码,站在巨人的肩膀上。
Log4j2研究之lookup_第1张图片

由以上类层次结构图可以看出
1. log4j2提供不下十种获取所运行环境配置信息的方式,基本能满足实际运行环境中获取各类配置信息的需求。
2. 我们在自定义lookup时,可以根据自身需求自由选择继承自StrLookupAbstractLookupAbstractConfigurationAwareLookup等等来简化我们的代码。

以上默认提供的各类lookup,其取值来源看官可以通过下面给出的引用链接中的第二个进行详细的了解,我就不再在这里赘述一遍了。

4. 自定义lookup

下面我们将自定义一个lookup,以获取记录日志的线程名。

// 从这里的注解可以看出,lookup属于一类特殊的plugin
@Plugin(name = "thread", category = StrLookup.CATEGORY)
public class ThreadLookup implements StrLookup {
    @Override
    public String lookup(String key) {
        return Thread.currentThread().getName();
    }

    @Override
    public String lookup(LogEvent event, String key) {
        return event.getThreadName() == null ? Thread.currentThread().getName() : event
                .getThreadName();
    }
}

可以看到自定义lookup的操作非常简单,log4j2的设计精妙由此也可见一斑。接下来我们就需要进行一些配置工作,让log4j2知道如何使用该lookup。


<Configuration status="TRACE" monitorInterval="5"
    packages="com.kanq.extend.cat.log4j2,slf4j._log4j2.classes.core.lookup">    
    
    <PatternLayout pattern="${thread:threadName}" />
Configuration>

最后附上一张执行堆栈图,还是比较清晰的
Log4j2研究之lookup_第2张图片

5. 补充

接下来我们来探索一些稍微深入的内容,以及一些细节性的内容。

  1. 作为lookup对外门面的Interpolator是通过 log4j2中负责解析节点的PropertiesPlugin类来并入执行流程中的。具体源码可以参见PropertiesPlugin.configureSubstitutor方法。其中注意的是,我们在中提供的属性是以default的优先级提供给外界的
  2. 作为lookup对外门面的Interpolator,在其构造函数中载入了所有category值为StrLookup.CATEGORY的plugin【即包括log4j2内置的(“org.apache.logging.log4j.core” package下的),也包括用户自定义的(log4j2.xml文件中的 Configuration.packages 属性值指示的package下的)】。
  3. Interpolator可以单独使用,但某些值可能取不到。
  4. 获取MDC中的内容,log4j2提供了两种方式:$${ctx:user}%X{user}
  1. lookup - Office Site
  2. Property Substitution - Configuration - Office Site
  3. custom lookup – 千万注意定义plugin时的契约,这里的教训是plugin的命名要求全小写,千万别习惯成自然地弄成驼峰命名。

你可能感兴趣的:(log4j2)