Lookups

查找提供了一种在任意位置向 Log4j 配置添加值的方法。它们是实现StrLookup接口的特定类型的插件。有关如何在配置文件中使用查找的信息,请参见Configuration页面的Property Substitution部分。

上下文 Map 查找

ContextMapLookup 允许应用程序将数据存储在 Log4j ThreadContextMap 中,然后在 Log4j 配置中检索值。在下面的示例中,应用程序将使用键“ loginId”将当前用户的登录 ID 存储在 ThreadContext Map 中。在初始配置过程中,第一个“ $”将被删除。 PatternLayout 支持使用 Lookups 进行插值,然后将解析每个事件的变量。请注意,模式“%X{loginId}”将获得相同的结果。

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

Date Lookup

DateLookup 与其他查询有些不同,因为它不使用键来定位项目。相反,该键可用于指定对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分配给容器的完整 ID。
containerName分配给容器的名称。
imageId分配给图像的 ID。
imageName分配给图像的名称。
shortContainerId容器 ID 的前 12 个字符。
shortImageId图片 ID 的前 12 个字符。
<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>

此查询要遵守Log4j Docker 支持列出的要求

Environment Lookup

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 提供对配置中日志事件内字段的访问。

KeyDescription
Exception如果事件中包含一个,则返回 Exception 的简单类名。
Level返回事件的日志记录级别。
Logger返回 Logger 的名称。
Marker返回与日志事件关联的标记的名称(如果存在)。
Message返回格式化的消息字符串。
ThreadId返回与日志事件关联的线程 ID。
ThreadName返回与日志事件关联的线程的名称。
Timestamp返回事件发生的时间(以毫秒为单位)。

在此示例中,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 Lookup

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

KeyDescription
version简短的 Java 版本,例如:

Java 版本 1.7.0_67
runtimeJava 运行时版本,例如:
Oracle 公司的 Java(TM)SE 运行时环境(内部版本 1.7.0_67-b01)
vmJava VM 版本,例如:
Java HotSpot(TM)64 位服务器 VM(内部版本 24.65-b04,混合模式)
osos 版本,例如:
Windows 7 6.1 Service Pack 1,体系结构:amd64-64
locale硬件信息,例如:
默认语言环境:en_US,平台编码:Cp1252
hw硬件信息,例如:
处理器:4,体系结构:amd64-64,指令集:amd64

For example:

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

Jndi Lookup

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

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

Java 的 JNDI 模块在 Android 上不可用.

JVMImporting 参数查找(JMX)

使用 JMXMapJVMImporting 参数(而不是主参数)来获取 JVM 参数。

使用前缀 jvmrunargs 访问 JVM 参数。

有关java.lang.management.RuntimeMXBean.getInputArguments()的信息,请参见 Javadocs。

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

Kubernetes Lookup

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

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

accountName服务帐号名称
clusterName应用程序部署所在的集群的名称
containerId分配给容器的完整 ID
containerName分配给容器的名称
host分配给主机 os 的名称
hostIp主机的 IP 地址
imageId分配给容器图像的 ID
imageName分配给容器图像的名称
labels列表中格式化的所有标签
labesl.app应用名称
labels.podTemplateHash窗格的模板哈希值
masterUrl用于访问 API 服务器的 URL
namespaceId各种 kubernetes 组件位于其中的名称空间的 ID
namespaceName各种 kubernetes 组件位于其中的名称空间
podId吊舱的 IP 地址
podIp吊舱的 IP 地址
podName吊舱名称
<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 Kubernetes 支持列出的配置要求的约束

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>

主参数查找(应用程序)

此查询要求您手动将应用程序的主要参数提供给 Log4j:

import org.apache.logging.log4j.core.lookup.MainMapLookup;

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

如果已设置主要参数,则此查询允许应用程序从日志记录配置中检索这些主要参数值。 main:前缀后面的键可以是参数列表中从 0 开始的索引,也可以是字符串,其中${main:myString}被主参数列表中 myString 后面的值替代。

注意:许多应用程序使用前划线来标识命令参数。指定${main:--file}将导致查找失败,因为它将查找名为“ main”且默认值为“ -file”的变量。为了避免这种情况,必须在$:{main:--file}后面加上“:”,以将 Lookup 名称与键分开,并在其后加上反斜杠作为转义字符。

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

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

然后可以进行以下替换:

ExpressionResult
${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

Example usage:

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

Map Lookup

MapLookup 有多种用途。

第一项只是意味着 MapLookup 用于替换配置文件中定义的属性。这些变量没有前缀指定-例如${name}。第二种用法允许替换当前MapMessage中的值(如果其中一个是当前日志事件的一部分)。在下面的示例中,RoutingAppender 将对 MapMessage 中名为“ type”的键的每个唯一值使用不同的 RollingFileAppender。请注意,以这种方式使用时,应在属性声明中声明“类型”的值以提供默认值,以防消息不是 MapMessage 或 MapMessage 不包含密钥。有关如何设置默认值的信息,请参见Configuration页的Property Substitution部分。

<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>

Marker Lookup

标记查找使您可以在有趣的配置(例如路由附加程序)中使用标记。考虑以下基于标记的 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");

请注意,配置的关键部分是模式:“ $${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”将返回默认配置文件。默认配置文件和活动配置文件可以是一个数组。如果存在多个配置文件,它们将以逗号分隔的列表形式返回。要从数组中检索单个项目,请在键上附加“ [\]”。例如,要返回列表中的第一个活动配置文件,请指定“ profiles.active [0]”。

该查找将返回空值,直到 Spring Boot 初始化应用程序日志记录为止。

<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 的名称部分(不包括企业编号)和 type 字段。下面的示例与 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>

系统属性查询

由于使用系统属性在应用程序内部和外部定义值是很常见的,因此自然应该可以通过查找来访问它们。由于系统属性通常是在应用程序外部定义的,因此很常见的情况是:

<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>

Upper Lookup

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

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

Web Lookup

WebLookup 允许应用程序检索与 ServletContext 关联的变量。除了能够检索 ServletContext 中的各个字段外,WebLookup 还支持查找存储为属性或配置为初始化参数的值。下表列出了可以检索的各种密钥:

KeyDescription
attr.name返回具有指定名称的 ServletContext 属性
contextPathWeb 应用程序的上下文路径
contextPathNameWeb 应用程序上下文路径中的第一个标记以“ /”字符分隔。
effectiveMajorVersion获取此 ServletContext 表示的应用程序所基于的 Servlet 规范的主要版本。
effectiveMinorVersion获取此 ServletContext 表示的应用程序所基于的 Servlet 规范的次要版本。
initParam.name返回具有指定名称的 ServletContext 初始化参数
majorVersion返回此 Servlet 容器支持的 Servlet API 的主要版本。
minorVersion返回此 Servlet 容器支持的 Servlet API 的次要版本。
rootDir返回使用值“ /”调用 getRealPath 的结果。
serverInfo返回运行 servlet 的 servlet 容器的名称和版本。
servletContextName返回部署 Descriptors 的 display-name 元素中定义的 Web 应用程序的名称

首先将检查指定的任何其他键名称,以查看该名称是否存在 ServletContext 属性,然后将检查该名称的初始化参数是否存在。如果找到键,则将返回相应的值。

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