我已经实现了以下插件来为log4j日志创建自定义Json布局。我不确定如何在插件中实现上下文查找。例如,应用程序将某些密钥放在MDC中,并在log4j.xml中使用以下配置,必须将其写入日志中。
<KeyValuePair key="customerId" value="$${customerId}" />.
插件
@Plugin(name = "CustomJsonLayout", category = "Core", elementType = "layout", printObject = true)
public class CustomJsonLayout extends AbstractStringLayout {
private final ObjectMapper objectMapper;
CustomJsonLayout(Charset charset) {
super(charset);
SimpleModule module = new SimpleModule();
module.addSerializer(LogEvent.class, new LogEventSerializer());
module.addSerializer(ReadOnlyStringMap.class, new ContextDataSerializer() {
});
objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
}
@Override
public String toSerializable(LogEvent logEvent) {
try {
return objectMapper.writeValueAsString(logEvent);
} catch (JsonProcessingException e) {
throw new IllegalStateException(e);
}
}
private static class LogEventSerializer extends StdSerializer<LogEvent> {
LogEventSerializer() {
super(LogEvent.class);
}
@Override
public void serialize(LogEvent value, JsonGenerator gen, SerializerProvider provider) throws IOException {
String pattern = "yyyy-MM-dd HH:mm:ss.SSS";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
String date = simpleDateFormat.format(new Date(value.getTimeMillis()));
gen.writeStartObject();
gen.writeStringField("timestamp", date);
gen.writeStringField("component", MicroService.getAppName());
gen.writeStringField("severity", value.getLevel().name());
gen.writeObjectField("msg", value.getMessage().getFormattedMessage());
gen.writeEndObject();
gen.writeRaw("\n");
}
}
@PluginBuilderFactory
public static <B extends Builder<B>> B newBuilder() {
return new Builder<B>().asBuilder();
}
public static class Builder<B extends Builder<B>> extends org.apache.logging.log4j.core.layout.AbstractStringLayout.Builder<B> implements org.apache.logging.log4j.core.util.Builder<CustomJsonLayout> {
Builder() {
this.setCharset(StandardCharsets.UTF_8);
}
public CustomJsonLayout build() {
return new CustomJsonLayout(this.getCharset());
}
}
}