“ 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的主要功能就是提供另外一種方式以添加某些特殊的值到日志中,以最大化松散耦合地提供可配置属性供使用者以约定的格式进行调用。
以下列举了两個主要使用的位置;當然不仅仅如此,log4j2允许你在任何需要的地方使用约定格式来获取环境中的指定配置信息。
<properties>
<!-- 之后我們就可以以 ${logPath}來引用该属性值 -->
<property name="logPath">${sys:catalina.home}/xmlogs</property>
</properties>
<!-- 这里的${hostName} 是由log4j2默认提供的, 其值为程序所在的服务器的主机名 -->
<!-- 至於${thread:threadName}, 將是本次我們所提供一個自定义lookup示例 -->
<PatternLayout pattern="[${hostName}];[${thread:threadName}];[%X{user}];[$${ctx:user}];[$${date:YYYY-MM/dd}]" />
关于log4j2的详细使用说明,请参看官网开发文档。
我们分析一下lookup机制,都会在什么地方级别的日志中出现。首先我们要了解一点日志等级,在log4j2中, 共有8个级别,按照从低到高为:ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF。
程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少 。
详细代码可以看这里
也就是说,在不管什么级别的日志下都可以出发lookup。但是为什么有些级别的日志下却不可以触发呢?那是因为你的日志级别设置的太高,导致log4j根本就没打印日志内容。
在org.apache.logging.log4j.core.pattern.MessagePatternConverter#format
中,会按字符检测每条日志,一旦发现某条日志中包含$ {
,则触发替换机制,也就是将表达式内的内容替换成真实的内容,其中config.getStrSubstitutor().replace(event, value)
执行下一步替换操作,关键代码如图
org.apache.logging.log4j.core.lookup.StrSubstitutor#substitute(org.apache.logging.log4j.core.LogEvent, java.lang.StringBuilder, int, int, java.util.List<java.lang.String>)
中,其实就是一个简单的字符串提取,然后找到lookup的内容并替换。函数的文档如下
没啥说的,一个简单的字符串查找函数,学过数据结构的都会,不详细介绍了。
在函数的这个地方,执行变量解析,如图
在这个函数,执行查找,也就是根据变量的协议,关键代码+文档如图
剩下就是一个简单的字符串查找函数,从字符串中提取类似于url的结构去解析,关键代码如下
值得注意的是,log4j2支持很多协议,例如通过ldap查找变量,通过docker查找变量,详细参考这里https://www.docs4dev.com/docs/zh/log4j2/2.x/all/manual-lookups.html
代码结构如图
由以上类层次结构图可以看出
接下來我們來探索一些稍微深入的內容,以及一些細節性的內容。
12 篇文章
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!