Log4j2分析与实践-Lookups

Lookups使得我们可以自由地再Log4j2配置文件中添加某些值(使用占位符设置变量),它们是一种特殊类型的插件,并且实现了StrLookup接口。

Context Map Lookup

ContextMapLookup使得我们可以在Log4j2的ThreadContext Map中保存值,并在Log4j2的配置文件中可以取得值。下面的例子中,应用将会把当前用户的登录ID保存在ThreadContext Map中,KEY为loginId。在配置初始化时,Log4j2会删除其中的一个$符号(解析把第一个$符号当作转义字符,就不会在初始化期间为变量赋值了)。PattenLayout支持使用Lookups设置变量,将会为每次日志事件解析设置的变量。

<File name="Application" fileName="application.log">
<PatternLayout>
<pattern>%d %p %c{1.} [%t] $${ctx:loginId} %m%n</pattern>
</PatternLayout>
</File>

日期Lookup

DateLookUp跟其它lookups不太一样,它并非根据一个关键字变量去获取一个值的,但它可以利用关键字来指定一种格式,且为SimpleDateFormat合法的格式。以下示例表示当前日志事件产生的时间:

<RollingFile name="Rolling-${map:type}" fileName="${filename}" filePattern="target/rolling1/test1-$${date:MM-dd-yyyy}.%i.log.gz">
<PatternLayout>
<pattern>%d %p %c{1.} [%t] %m%n</pattern>
</PatternLayout>
<SizeBasedTriggeringPolicy size="500" />
</RollingFile>

环境Lookup

EnvironmentLookup可以获取到例如/etc/profile或者应用启动脚本的环境变量,下面例子表示获取当前登录用户:

<File name="Application" fileName="application.log">
<PatternLayout>
<pattern>%d %p %c{1.} [%t] $${env:USER} %m%n</pattern>
</PatternLayout>
</File>

Java Lookup

JavaLookup使得我们可以使用java:前缀方便地取得Java环境信息。
version:Java版本号
runtime:Java运行时版本号
vm:Java虚拟机版本号
os:操作系统版本号
locale:语言和编码信息
hw:硬件信息
示例:

<File name="Application" fileName="application.log">
<PatternLayout header="${java:runtime} - ${java:vm} - ${java:os}">
<Pattern>%d %m%n</Pattern>
</PatternLayout>
</File>

Log4j2 配置Location Lookup

${log4j:configLocation}表示Log4j2配置文件的绝对位置,${log4j:configParentLocation}表示配置文件的父级目录绝对位置。以下示例表示在Log4j2配置文件的同级目录创建一个日志文件:

<File name="Application" fileName="${log4j:configParentLocation}/logs/application.log">
<PatternLayout>
<pattern>%d %p %c{1.} [%t] %m%n</pattern>
</PatternLayout>
</File>

主函数参数 Lookup

这个Lookup需要你在程序中显式地为Log4j2提供主函数参数:

public static void main(String args[]) {
MainMapLookup.setMainArguments(args);
...
}

在配置文件中就可以获取到传入到主函数的参数了。前缀main:之后既可以是数字,也可以是字符串。是数字的话,代表输入参数的单词位置;是字符串的话,代表这个字符串对应的变量值。比如,若传入主函数的参数如下:
--file foo.txt --verbose -x bar
${main:0}表示--file
${main:1}表示foo.txt
${--file}表示foo.txt
${main:bar}表示null
示例:

<File name="Application" fileName="application.log">
<PatternLayout header="File: ${main:--file}">
<Pattern>%d %m%n</Pattern>
</PatternLayout>
</File>

Marker Lookup

Marker Lookup使得可以在比如路由appender这样的组件上使用markers,$${marker:}可以获取到MarkerFactory.getMarker生成的Markder。

系统属性 Lookup

既然在应用内外定义系统属性已经很平常了,那么就应该可以通过一个Lookup来访问它们。

<Appenders>
<File name="ApplicationLog" fileName="${sys:logPath}/app.log"/>
</Appenders>

Map Lookup

MapLookup有以下几个目的:
(1)可以访问配置文件中的属性properties,不需要前缀,比如${fileName}};
(2)从LogEvent中的MapMessage获取值,需要map:前缀,比如:$${map:type};
(3)获取通过MapLookup.setMainArguments(String[])设置的参数。

<Routing name="Routing">
<Routes pattern="$${map:type}">
<Route>
<RollingFile name="Rolling-${map:type}" fileName="${filename}"
filePattern="target/rolling1/test1-${map:type}.%i.log.gz">
<PatternLayout>
<pattern>%d %p %c{1.} [%t] %m%n</pattern>
</PatternLayout>
<SizeBasedTriggeringPolicy size="500" />
</RollingFile>
</Route>
</Routes>
</Routing>

结构化数据 Lookup

跟MapLookup很相似,它会从StructuredDataMessages中获取数据,返回值包含value、id和type字段。以下示例中,与MapLookup不同的是,type是StructuredDataMessage的一个属性;而在MapLookup中,type只是Map里面一个数据项而已:

<Routing name="Routing">
<Routes pattern="$${sd:type}">
<Route>
<RollingFile name="Rolling-${sd:type}" fileName="${filename}"
filePattern="target/rolling1/test1-${sd:type}.%i.log.gz">
<PatternLayout>
<pattern>%d %p %c{1.} [%t] %m%n</pattern>
</PatternLayout>
<SizeBasedTriggeringPolicy size="500" />
</RollingFile>
</Route>
</Routes>
</Routing>

Web Lookup

WebLookup负责获取与ServletContext相关的变量,也可以获取初始化的参数值。常见变量示例:
(1)attr.name:返回指定名称的ServletContext属性。
(2)contextPath:Web应用的上下文路径。
(3)rootDir:返回调用getRealPath的结果。
(4)serverInfo:返回servlet容器的名称和版本信息。
(5)servletContextName:返回Web应用的名称。
当指定一个关键字时,Log4j2会首先从ServletContext查找,如果没找到,再从初始化参数中查找。

<Appenders>
<File name="ApplicationLog" fileName="${web:rootDir}/app.log"/>
</Appenders>