Lookups 查找

查找提供了一种在任意位置向Log4j配置添加值的方法。它们是实现StrLookup接口的一种特殊类型的Plugin。

有关如何在配置文件中使用查找的信息,可在“配置”页的“属性替换”部分找到。

上下文映射查找

contextmapllookup允许应用程序将数据存储在Log4j ThreadContext Map中,然后检索Log4j配置中的值。

在下面的示例中,应用程序将使用键“loginId”将当前用户的登录id存储在ThreadContext Map中。

在初始配置处理过程中,第一个’$’将被删除。PatternLayout通过查找支持插值,然后为每个事件解析变量。注意,模式“%X{loginId}”将获得相同的结果。

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

日期查询

datellookup 与其他查找有些不同,因为它不使用键来定位项。

相反,该键可用于指定对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>

Docker Lookup 码头工人查找

DockerLookup可以用于从运行应用程序的Docker容器中查找属性。

Log4j Docker提供了对以下容器属性的访问:

标识 解释
containerId The full id assigned to the container.
containerName The name assigned to the container.
imageId The id assigned to the image.
imageName The name assigned to the image.
shortContainerId The first 12 characters of the container id.
shortImageId The first 12 characters of the image id.
<JsonLayout properties="true" compact="true" eventEol="true">
  <KeyValuePair key="containerId" value="${docker:containerId}"/>
  <KeyValuePair key="containerName" value="${docker:containerName}"/>
  <KeyValuePair key="imageName" value="${docker:imageName}"/>
</JsonLayout>

环境中查找

EnvironmentLookup允许系统在全局文件(如/etc/profile)或应用程序的启动脚本中配置环境变量,然后从日志配置中检索这些变量。

下面的示例包括应用程序日志中当前登录的用户的名称。

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

此查找还支持默认值语法。在下面的示例中,当USER环境变量未定义时,将使用默认值jdoe:

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

EventLookup

EventLookup 提供了对配置日志事件中的字段的访问。

Key Description
Exception Returns the simple class name of the Exception, if one is included in the event.
Level Returns the logging Level of the event.
Logger Returns the name of the Logger.
Marker Returns the name of the Marker associated with the log event, if one is present.
Message Returns the formatted Message string.
ThreadId Returns the thread id associated with the log event.
ThreadName Returns the name of the thread associate with the log event.
Timestamp Returns the time in milliseconds when the event occurred.

在本例中,RoutingAppender根据日志事件中出现的名为“AUDIT”的标记来选择路由。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" name="RoutingTest">
  <Appenders>
    <Console name="STDOUT" target="SYSTEM_OUT" />
    <Flume name="AuditLogger" compress="true">
      <Agent host="192.168.10.101" port="8800"/>
      <Agent host="192.168.10.102" port="8800"/>
      <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/>
    </Flume>
    <Routing name="Routing">
      <Routes>
        <Route pattern="$${event:Marker}">
          <RollingFile
              name="Rolling-${mdc:UserId}"
              fileName="${mdc:UserId}.log"
              filePattern="${mdc:UserId}.%i.log.gz">
            <PatternLayout>
              <pattern>%d %p %c{1.} [%t] %m%n</pattern>
            </PatternLayout>
            <SizeBasedTriggeringPolicy size="500" />
          </RollingFile>
        </Route>
        <Route ref="AuditLogger" key="AUDIT"/>
        <Route ref="STDOUT" key="STDOUT"/>
      </Routes>
      <IdlePurgePolicy timeToLive="15" timeUnit="minutes"/>
    </Routing>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Routing" />
    </Root>
  </Loggers>
</Configuration>

Java查找

javallookup 允许使用Java:前缀以方便的预格式化字符串形式检索Java环境信息。

Key Description
version The short Java version, like: Java version 1.7.0_67
runtime The Java runtime version, like: Java(TM) SE Runtime Environment (build 1.7.0_67-b01) from Oracle Corporation
vm The Java VM version, like: Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
os The OS version, like: Windows 7 6.1 Service Pack 1, architecture: amd64-64
locale System locale and file encoding information, like: default locale: en_US, platform encoding: Cp1252
hw Hardware information, like: processors: 4, architecture: amd64-64, instruction sets: amd64

eg:

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

Jndi查找

从Log4j 2.17.0开始,JNDI操作需要log4j2。enablejndillookup =true设置为系统属性或相应的环境变量,以使此查找发挥作用。请参阅enablejndillookup系统属性。

jndillookup允许通过JNDI检索变量。默认情况下,键将以java:comp/env/作为前缀,但是如果键包含“:”,则不会添加前缀。

JNDI Lookup只支持java协议或不支持任何协议(如下面的示例所示)。

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

Java’s JNDI module is not available on Android.

JVM输入参数查找(JMX)

映射JVM输入参数——但不是主参数——使用JMX获取JVM参数。

使用前缀jvmrunargs访问JVM参数。

请参阅javadoc中的java.lang.management. runtimemxbean . getinpuarguments()。

Java的JMX模块在Android或Google App Engine上不可用。

Kubernetes查找

KubernetesLookup可以用于从Kubernetes环境中查找应用程序所在容器的属性。

Log4j Kubernetes提供了对以下容器属性的访问:

accountName	The service account name
clusterName	The name of the cluster the application is deployed in
containerId	The full id assigned to the container
containerName	The name assigned to the container
host	The name assigned to the host operating system
hostIp	The host's ip address
imageId	The id assigned to the container image
imageName	The name assigned to the container image
labels	All labels formatted in a list
labels.app	The application name
labels.podTemplateHash	The pod's template hash value
masterUrl	The URL used to access the API server
namespaceId	The id of the namespace the various kubernetes components are located within
namespaceName	The namespace the various kubernetes components are located within
podId	The pod's ip number
podIp	The pod's ip address
podName	The name of the pod

eg:

<GelfLayout includeStackTrace="true" host="${hostName}" includeThreadContext="true" includeNullDelimiter="true"
            compressionType="OFF">
  <ThreadContextIncludes>requestId,sessionId,loginId,userId,ipAddress,callingHost</ThreadContextIncludes>
  <MessagePattern>%d [%t] %-5p %X{requestId, sessionId, loginId, userId, ipAddress} %C{1.}.%M:%L - %m%n</MessagePattern>
  <KeyValuePair key="docker.containerId" value="${docker:containerId:-}"/>
  <KeyValuePair key="application" value="$${lower:${spring:spring.application.name}}"/>
  <KeyValuePair key="kubernetes.serviceAccountName" value="${k8s:accountName:-}"/>
  <KeyValuePair key="kubernetes.clusterName" value="${k8s:clusterName:-}/>
  <KeyValuePair key="kubernetes.containerId" value="${k8s:containerId:-}"/>
  <KeyValuePair key="kubernetes.containerName" value="${k8s:containerName:-}"/>
  <KeyValuePair key="kubernetes.host" value="${k8s:host:-}"/>
  <KeyValuePair key="kubernetes.labels.app" value="${k8s:labels.app:-}"/>
  <KeyValuePair key="kubernetes.labels.pod-template-hash" value="${k8s:labels.podTemplateHash:-}"/>
  <KeyValuePair key="kubernetes.master_url" value="${k8s:masterUrl:-}"/>
  <KeyValuePair key="kubernetes.namespaceId" value="${k8s:namespaceId:-}"/>
  <KeyValuePair key="kubernetes.namespaceName" value="${k8s:namespaceName:-}"/>
  <KeyValuePair key="kubernetes.podID" value="${k8s:podId:-}"/>
  <KeyValuePair key="kubernetes.podIP" value="${k8s:podIp:-}"/>
  <KeyValuePair key="kubernetes.podName" value="${k8s:podName:-}"/>
  <KeyValuePair key="kubernetes.imageId" value="${k8s:imageId:-}"/>
  <KeyValuePair key="kubernetes.imageName" value="${k8s:imageName:-}"/>
</GelfLayout>

Log4j配置位置查找

Log4j配置属性。表达式 ${log4j:configLocation}${log4j:configParentLocation} 分别提供了log4j配置文件及其父文件夹的绝对路径。

下面的示例使用此查找将日志文件放置在相对于log4j配置文件的目录中。

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

Lower Lookup

LowerLookup 将传入的参数转换为小写。该值可能是嵌套查找的结果。

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

UpperLookup

UpperLookup 将传入的参数转换为大写。该值可能是嵌套查找的结果。

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

查找主参数(应用程序)

此查找需要您手动向Log4j提供应用程序的主要参数:

import org.apache.logging.log4j.core.lookup.MainMapLookup;
 
public static void main(String args[]) {
  MainMapLookup.setMainArguments(args);
  ...
}

如果设置了主要参数,则此查找允许应用程序从日志配置中检索这些主要参数值。

main: prefix 后面的键可以是一个基于0的参数列表索引,也可以是一个字符串,其中 ${main:myString} 被替换为主参数列表中myString后面的值。

注意:许多应用程序使用前导破折号来标识命令参数。指定 ${main:\--file} 将导致查找失败,因为它将查找一个名为“main”的变量,其默认值为“-file”。

为了避免这种情况,分隔查找名称和键的”:”必须后跟一个反斜杠作为转义字符,如 ${main:\--file}

例如,假设静态void main String[]参数如下:

--file foo.txt --verbose -x bar

那么以下替换是可能的:

Expression	Result
${main:0}	--file

${main:1}	 foo.txt

${main:2}	 --verbose

${main:3}	 -x

${main:4}	 bar

${main:\--file}	 foo.txt

${main:\-x}	 bar

${main:bar}	 null

${main:\--quiet:-true}	 true

eg:

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

MAP LookUp

MapLookup有几个用途。

  • 为配置文件中声明的属性提供基。

  • 从LogEvents中的MapMessages中检索值。

第一项仅仅意味着使用mapllookup替换配置文件中定义的属性。这些变量没有前缀,例如${name}。

第二种用法允许替换当前MapMessage中的值(如果其中一个值是当前日志事件的一部分)。在下面的示例中,RoutingAppender将对MapMessage中名为“type”的键的每个唯一值使用不同的RollingFileAppender。

注意,当以这种方式使用时,应该在属性声明中声明“type”的值,以便在消息不是MapMessage或MapMessage不包含键的情况下提供默认值。有关如何设置默认值的信息,请参阅“配置”页的“属性替换”部分。

标记查找

标记查找允许您在路由追加器等有趣的配置中使用标记。考虑以下基于标记记录到不同文件的YAML配置和代码:

Configuration:
  status: debug
 
  Appenders:
    Console:
    RandomAccessFile:
      - name: SQL_APPENDER
        fileName: logs/sql.log
        PatternLayout:
          Pattern: "%d{ISO8601_BASIC} %-5level %logger{1} %X %msg%n"
      - name: PAYLOAD_APPENDER
        fileName: logs/payload.log
        PatternLayout:
          Pattern: "%d{ISO8601_BASIC} %-5level %logger{1} %X %msg%n"
      - name: PERFORMANCE_APPENDER
        fileName: logs/performance.log
        PatternLayout:
          Pattern: "%d{ISO8601_BASIC} %-5level %logger{1} %X %msg%n"
 
    Routing:
      name: ROUTING_APPENDER
      Routes:
        pattern: "$${marker:}"
        Route:
        - key: PERFORMANCE
          ref: PERFORMANCE_APPENDER
        - key: PAYLOAD
          ref: PAYLOAD_APPENDER
        - key: SQL
          ref: SQL_APPENDER
 
  Loggers:
    Root:
      level: trace
      AppenderRef:
        - ref: ROUTING_APPENDER
public static final Marker SQL = MarkerFactory.getMarker("SQL");
public static final Marker PAYLOAD = MarkerFactory.getMarker("PAYLOAD");
public static final Marker PERFORMANCE = MarkerFactory.getMarker("PERFORMANCE");
 
final Logger logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
 
logger.info(SQL, "Message in Sql.log");
logger.info(PAYLOAD, "Message in Payload.log");
logger.info(PERFORMANCE, "Message in Performance.log");

注意,配置的关键部分是pattern: “$${marker:}”。这将生成三个日志文件,每个文件都有一个特定标记的日志事件。

Log4j将带SQL标记的日志事件路由到SQL.log,带PAYLOAD标记的日志事件路由到PAYLOAD .log,以此类推。

您可以使用符号”${marker:name}”和”$${marker:name}”来检查是否存在以name为标记名的标记。如果标记存在,则表达式返回名称,否则返回null。

Spring Boot查找

Spring Boot Lookup从Spring配置中检索Spring属性的值,以及活动和默认配置文件的值。指定“profiles”的键。

“Active”将返回活动配置文件,而“profiles.default”键将返回默认配置文件。默认配置文件和活动配置文件可以是一个数组。

如果存在多个配置文件,它们将作为逗号分隔的列表返回。要从数组中检索单个项,请在键后面添加“[{index}]”。

例如,要返回列表中的第一个活动概要文件,指定“profiles.active[0]”。

在Spring Boot初始化应用程序日志之前,这个Lookup将返回空值。Spring Boot Lookup需要将log4j-spring-boot jar作为依赖项包含。

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

此查找要求应用程序中包含log4j-spring-cloud-config-client。

结构化数据查询

StructuredDataLookup 与MapLookup非常相似,因为它将从StructuredDataMessages中检索值。

除了Map值之外,它还将返回id的名称部分(不包括企业编号)和类型字段。

下面的示例与MapMessage的示例之间的主要区别在于,“type”是StructuredDataMessage的一个属性,而“type”必须是MapMessage中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>

系统属性查询

由于通过使用System Properties在应用程序内部和外部定义值是非常常见的,因此通过Lookup可以访问它们是很自然的。

由于系统属性通常是在应用程序之外定义的,因此经常会看到如下内容:

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

此查找还支持默认值语法。在下面的示例中,当logPath系统属性未定义时,使用默认值/var/logs:

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

web 查找

WebLookup允许应用程序检索与ServletContext关联的变量。

除了能够检索ServletContext中的各种字段外,WebLookup还支持查找作为属性存储或配置为初始化参数的值。

下表列出了可以检索的各种键:

Key Description
attr.name Returns the ServletContext attribute with the specified name
contextPath The context path of the web application
contextPathName The first token in the context path of the web application splitting on “/” characters.
effectiveMajorVersion Gets the major version of the Servlet specification that the application represented by this ServletContext is based on.
effectiveMinorVersion Gets the minor version of the Servlet specification that the application represented by this ServletContext is based on.
initParam.name Returns the ServletContext initialization parameter with the specified name
majorVersion Returns the major version of the Servlet API that this servlet container supports.
minorVersion Returns the minor version of the Servlet API that this servlet container supports.
rootDir Returns the result of calling getRealPath with a value of “/”.
serverInfo Returns the name and version of the servlet container on which the servlet is running.
servletContextName Returns the name of the web application as defined in the display-name element of the deployment descriptor

将首先检查指定的任何其他键名,以查看是否存在带有该名称的ServletContext属性,然后检查是否存在该名称的初始化参数。

如果找到了键,则返回相应的值。

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

参考资料

https://logging.apache.org/log4j/2.x/manual/lookups.html