我有一个Spring Boot (2.2.6)应用程序,它使用Log4j2(与Slf4j一起)。Log4j 被配置为使用 json 布局,最终我想在 Datadog 中摄取日志。为此,"serviceName "作为json中的一个字段非常重要。
现在根据log4j文档 (https:/logging.apache.orglog4j2.xmanuallayouts.html#JSONLayout。)可以添加一个带有'KeyValuePair'标签的自定义字段,这样就可以了。不幸的是,这打破了弹簧日志的正常结构。
Log4j2.xml配置。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<!-- Write logs to stdout, JSON, one line per log event -->
<Console name="Console" target="SYSTEM_OUT">
<JSONLayout compact="true" eventEol="true" includeStacktrace="true" locationInfo="true"
stacktraceAsString="true" properties="true">
<KeyValuePair key="serviceName" value="$${env:APPLICATION_NAME:-local}-sidecar"/> <!-- fine w/o this line -->
</JSONLayout>
</Console>
</Appenders>
<Loggers>
<Logger name="my.service" level="debug" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.springframework" level="info" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.apache" level="info" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
日志 wo 自定义字段:
{
"thread": "main",
"level": "INFO",
"loggerName": "com.nginxtrafficsidecar.ApplicationKt",
"message": "Starting ApplicationKt on xxx with PID 17300 (C:\\Users\\Felix\\Documents\\code\\nginx-traffic-sidecar\\build\\classes\\kotlin\\main started by Felix in C:\\Users\\Felix\\Documents\\code\\nginx-traffic-sidecar)",
"endOfBatch": false,
"loggerFqcn": "org.apache.commons.logging.LogAdapter$Log4jLog",
"threadId": 1,
"instant": {
"epochSecond": 1587975181,
"nanoOfSecond": 331370300
},
"source": {
"class": "org.springframework.boot.StartupInfoLogger",
"method": "logStarting",
"file": "StartupInfoLogger.java",
"line": 55,
"classLoaderName": "app"
},
"contextMap": {},
"threadPriority": 5
}
日志 w 自定义字段
{
"logEvent": "Starting ApplicationKt on xxx with PID 9732 (C:\\Users\\Felix\\Documents\\code\\nginx-traffic-sidecar\\build\\classes\\kotlin\\main started by Felix in C:\\Users\\Felix\\Documents\\code\\nginx-traffic-sidecar)",
"serviceName": "local-sidecar"
}
Spring docu提到这可能会对logback产生作用,但不会对log4j产生作用 (https:/docs.spring.iospring-bootdocscurrentreferencehtmlspring-boot-features.html#boot-features-custom-log-configuration。,章末))
我已经搜索过了,但找不到任何有用的东西。有什么办法可以让我在保留所有来自Spring的字段的同时,在json日志中添加一个自定义字段?
谢谢,Felix
JsonLayout
使用 Jackson Annotations
内部代码。jackson-annotations-2.10.3.jar
jackson-core-2.10.3.jar
jackson-databind-2.10.3.jar
<JsonLayout>...</JsonLayout>
在你的配置中(在我的例子中是log4j2.xml),像下面这样。<JsonLayout>
<KeyValuePair key="testKey" value="testValue"/>
</JsonLayout>
替换 key
和 value
到你想使用的东西。在我的例子中 key
是 "testKey "和 value
是 "测试值"
它是我的完整的示例代码和xml配置信息.代码。
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
public class LogTest{
private static final Logger logger = LogManager.getLogger(LogTest.class.getName());
public static void main(String[] args) {
ThreadContext.put("logFileName", "testFile1" );
logger.info("log printed! - testFile1");
ThreadContext.put("logFileName", "testFile2" );
logger.info("log printed! - testFile2");
ThreadContext.remove("logFileName");
}
}
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Routing name="RoutingAppender">
<Routes pattern="${ctx:logFileName}">
<Route>
<RollingFile name="Rolling-${ctx:logFileName}"
fileName="./logs/${ctx:logFileName}.log"
filePattern="./logs/${ctx:logFileName}.%i.log.gz">
<JsonLayout>
<KeyValuePair key="testKey" value="testValue"/>
</JsonLayout>
<SizeBasedTriggeringPolicy size="512" />
</RollingFile>
</Route>
</Routes>
</Routing>
</Appenders>
<Loggers>
<Root level="all">
<AppenderRef ref="RoutingAppender" />
</Root>
</Loggers>
</Configuration>
产出
{
"instant" : {
"epochSecond" : 1588590944,
"nanoOfSecond" : 469000000
},
"thread" : "main",
"level" : "INFO",
"loggerName" : "com.test.LogTest",
"message" : "log printed! - testFile2",
"endOfBatch" : false,
"loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
"threadId" : 1,
"threadPriority" : 5,
"testKey" : "testValue"
}