据我了解,您正在寻找一种方法来自定义 JSONLayout 的 JSON 输出格式,其方式类似于通过指定“转换模式”来自定义 PatternLayout。
我相信答案是您不能以同样的方式自定义JSONLayout。您可以选择要包含在消息中的各种信息。例如,documentation 显示类似 properties 的参数:
如果为 true,则附加程序在生成的 JSON 中包含线程上下文映射。默认为 false。
因此您可以设置各种参数以包含某些类型的信息,但您无法直接控制包含的特定项目。
您可以做的是使用ObjectMessage 和 JSON 库来生成 JSON 消息。但是,这会在 JSON 中生成 JSON(假设您仍希望通过这种方法使用 JSONLayout)。下面是一些示例代码来说明:
具有生成日志消息的main方法的类:
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 对象)中,因为现在您只是转储地图的内容。
使用相同 java 代码的示例输出,布局更改为PatternLayout,如上所述:
{"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"}}