查找
查找提供了一种在任意位置向 Log4j 配置添加值的方法。它们是实现 StrLookup 接口的特定类型插件。有关如何在配置文件中使用查找的信息,请参阅 配置 页面中 属性替换 部分。
上下文映射查找
ContextMapLookup 允许应用程序将数据存储在 Log4j ThreadContext 映射中,然后在 Log4j 配置中检索这些值。在下面的示例中,应用程序将在 ThreadContext 映射中使用键“loginId”存储当前用户的登录 ID。在初始配置处理期间,第一个“$”将被删除。PatternLayout 支持使用查找进行插值,然后将为每个事件解析变量。请注意,模式“%X{loginId}”将实现相同的结果。
<File name="Application" fileName="application.log"> <PatternLayout> <pattern>%d %p %c{1.} [%t] $${ctx:loginId} %m%n</pattern> </PatternLayout> </File>
日期查找
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 查找
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 支持 中列出的要求约束。
环境查找
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 提供对配置中日志事件中字段的访问权限。
键 | 描述 |
---|---|
Exception | 如果事件中包含异常,则返回异常的简单类名。 |
Level | 返回事件的日志记录级别。 |
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 查找
JavaLookup 允许使用 java:
前缀以方便的预格式化字符串检索 Java 环境信息。
键 | 描述 |
---|---|
version |
简短的 Java 版本,例如
|
runtime |
Java 运行时版本,例如
|
vm |
Java VM 版本,例如
|
os |
操作系统版本,例如
|
locale |
系统区域设置和文件编码信息,例如
|
hw |
硬件信息,例如
|
例如
<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.enableJndiLookup=true
设置为系统属性或相应的环境变量,才能使此查找正常工作。请参阅 enableJndiLookup 系统属性。
JndiLookup 允许通过 JNDI 检索变量。默认情况下,键将以 java:comp/env/ 为前缀,但是如果键包含“:”,则不会添加任何前缀。
JNDI 查找仅支持 java 协议或无协议(如以下示例所示)。
<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 上不可用。
JVM 输入参数查找(JMX)
使用 JMX 映射 JVM 输入参数(但不是 main 参数)以获取 JVM 参数。
使用前缀 jvmrunargs
访问 JVM 参数。
请参阅 java.lang.management.RuntimeMXBean.getInputArguments() 的 Javadoc。
Java 的 JMX 模块在 Android 或 Google App Engine 上不可用。
Kubernetes 查找
KubernetesLookup 可用于从应用程序正在运行的容器的 Kubernetes 环境中查找属性。
Log4j Kubernetes 提供对以下容器属性的访问权限accountName | 服务帐户名称 |
clusterName | 应用程序部署到的集群的名称 |
containerId | 分配给容器的完整 ID |
containerName | 分配给容器的名称 |
host | 分配给主机操作系统的名称 |
hostIp | 主机的 IP 地址 |
imageId | 分配给容器映像的 ID |
imageName | 分配给容器映像的名称 |
labels | 所有标签,以列表格式 |
labels.app | 应用程序名称 |
labels.podTemplateHash | Pod 的模板哈希值 |
masterUrl | 用于访问 API 服务器的 URL |
namespaceId | 各种 Kubernetes 组件所在的命名空间的 ID |
namespaceName | 各种 Kubernetes 组件所在的命名空间 |
podId | Pod 的 IP 号码 |
podIp | Pod 的 IP 地址 |
podName | Pod 的名称 |
<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>
小写查找
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}
例如,假设 static void main String[] 参数为
--file foo.txt --verbose -x bar
那么以下替换是可能的
表达式 | 结果 |
---|---|
${main:0} |
|
${main:1} |
|
${main:2} |
|
${main:3} |
|
${main:4} |
|
${main:\--file} |
|
${main:\-x} |
|
${main:bar} |
|
${main:\--quiet:-true} |
|
示例用法
<File name="Application" fileName="application.log"> <PatternLayout header="File: ${main:--file}"> <Pattern>%d %m%n</Pattern> </PatternLayout> </File>
Map 查找
MapLookup 具有多种用途。
- 为配置文件中声明的属性提供基础。
- 从 LogEvents 中的 MapMessages 检索值。
第一项仅仅意味着 MapLookup 用于替换在配置文件中定义的属性。 这些变量在没有前缀的情况下指定 - 例如 ${name}
。 第二种用法允许从当前 MapMessage 中替换值,如果当前日志事件包含 MapMessage。 在下面的示例中,RoutingAppender 将为 MapMessage 中名为“type”的键的每个唯一值使用不同的 RollingFileAppender。 请注意,以这种方式使用时,应在属性声明中声明“type”的值,以在消息不是 MapMessage 或 MapMessage 不包含键的情况下提供默认值。 有关如何设置默认值的详细信息,请参阅 属性替换 部分的 配置 页面。
<Routing name="Routing"> <Routes pattern="$${map:type}"> <Route> <RollingFile name="Rolling-${map:type}" fileName="target/rolling1/test1-${map:type}.log" 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>
标记查找
标记查找允许您在有趣的配置中使用标记,例如路由追加器。 考虑以下 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
。
资源包查找
资源包查找从资源包中检索值(请参阅 Java 文档)。 格式为 ${dollar}{bundle:BundleName:BundleKey}
。 包名称遵循包命名约定,例如:${dollar}{bundle:com.domain.Messages:MyKey}
。
<File name="Application" fileName="application-${spring:profiles.active[0]}.log"> <PatternLayout> <pattern>%d %p %c{1.} [%t] $${bundle:MyBundle:MyKey} %m%n</pattern> </PatternLayout> </File>
Spring Boot 查找
Spring Boot 查找从 Spring 配置中检索 Spring 属性的值,以及活动和默认配置文件的值。 指定“profiles.active”键将返回活动配置文件,而指定“profiles.default”键将返回默认配置文件。 默认和活动配置文件可以是数组。 如果存在多个配置文件,则将以逗号分隔列表的形式返回。 要从数组中检索单个项目,请将“[{index}]”附加到键。 例如,要返回列表中的第一个活动配置文件,请指定“profiles.active[0]”。
此查找将在 Spring Boot 初始化应用程序日志记录之前返回 null 值。 Spring Boot 查找需要将 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>
系统属性查找
由于在应用程序内部和外部使用系统属性定义值非常普遍,因此它们可以通过查找访问是自然而然的。 由于系统属性通常在应用程序外部定义,因此通常会看到类似以下内容
<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>
大写查找
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 查找
WebLookup 允许应用程序检索与 ServletContext 关联的变量。 除了能够检索 ServletContext 中的各种字段之外,WebLookup 还支持查找存储为属性或配置为初始化参数的值。 下表列出了可以检索的各种键
键 | 描述 |
---|---|
attr.name | 返回具有指定名称的 ServletContext 属性 |
contextPath | Web 应用程序的上下文路径 |
contextPathName | Web 应用程序上下文路径中第一个以“/”字符分隔的标记。 |
effectiveMajorVersion | 获取此 ServletContext 代表的应用程序所基于的 Servlet 规范的主要版本。 |
effectiveMinorVersion | 获取此 ServletContext 代表的应用程序所基于的 Servlet 规范的次要版本。 |
initParam.name | 返回具有指定名称的 ServletContext 初始化参数 |
majorVersion | 返回此 servlet 容器支持的 Servlet API 的主要版本。 |
minorVersion | 返回此 servlet 容器支持的 Servlet API 的次要版本。 |
rootDir | 返回使用“/”的值调用 getRealPath 的结果。 |
serverInfo | 返回 servlet 正在运行的 servlet 容器的名称和版本。 |
servletContextName | 返回 Web 应用程序的名称,如部署描述符的 display-name 元素中定义的那样 |
任何其他指定的键名将首先检查是否存在具有该名称的 ServletContext 属性,然后检查是否存在具有该名称的初始化参数。 如果找到键,则将返回相应的值。
<Appenders> <File name="ApplicationLog" fileName="${web:rootDir}/app.log"/> </Appenders>