据我所知,您正在寻找一种类似于通过指定“转换模式”来自定义“PatternLayout”的方式来自定义JSONLayout的JSON输出格式的方法。 我认为答案是您无法以相同的方式自定义JSONLayout。 您可以选择要包含在消息中的各个信息。例如,文档显示了像属性之类的参数。因此,您可以设置各种参数以包括某些类型的信息,但您无法直接控制包括的特定项目。相反,您可以使用ObjectMessage以及JSON库生成JSON消息。 但是,这将在JSON内部生成JSON(假设您仍希望在此方法中使用JSONLayout)。以下是一些示例代码:
package example;
import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONObject;
public class JsonMessageExample {
private static final Logger log = LogManager.getLogger();
public static void main(String[] args) {
Map<String,String> msgMap = new HashMap<>();
msgMap.put("myKey", "myValue");
JSONObject message = new JSONObject(msgMap);
log.info(message);
}
}
log4j2.xml 配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<JSONLayout/>
</Console>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
以上输出内容如下:
{
"timeMillis" : 1510429852038,
"thread" : "main",
"level" : "INFO",
"loggerName" : "example.JsonMessageExample",
"message" : "{\"myKey\":\"myValue\"}",
"endOfBatch" : false,
"loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
"threadId" : 1,
"threadPriority" : 5
}
正如您所看到的,消息名值对有一个JSON字符串的值。为了解析这个,您需要将外部对象解析为JSON,取出消息字段,然后再将其值解析为JSON。
然而,如果您使用另一种布局,比如非常基本的`PatternLayout`,像这样:
<PatternLayout pattern="%m%n"/>
。
您将能够生成一个级别的JSON输出,因此只需解析一次。但是,您需要编写自己的逻辑来获取所有需要的消息数据,并将其放入映射(和JSON对象)中,因为现在您只是简单地倾倒映射的内容。
使用更改为`PatternLayout`的相同Java代码的示例输出如下:
{"myKey":"myValue"}
编辑:
甚至可以像以下这样做,如果您想使用`PatternLayout`的“转换模式”以JSON格式输出日志,并且不必编写某些特定内容的逻辑:
<PatternLayout>
<pattern>{"timeMillis":"%d{UNIX_MILLIS}","thread":"%t","level":"%p","loggerName":"%c","message":%m}%n</pattern>
</PatternLayout>
样例输出:
{"timeMillis":"1510455694601","thread":"main","level":"INFO","loggerName":"example.JsonMessageExample","message":{"myKey":"myValue"}}