我已使用此配置文件配置log4j 2以将MapMessage
写入控制台:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="ERROR">
<Properties>
<Property name="disableThreadContext">true</Property>
<Property name="disableThreadContextStack">true</Property>
<Property name="disableThreadContextMap">true</Property>
<Property name="log4j2.disable.jmx">true</Property>
</Properties>
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT">
<JsonLayout locationInfo="true" complete="false" />
</Console>
</Appenders>
<Loggers>
<logger name="ir.cvas.logger" level="info" />
<Root level="warn">
<AppenderRef ref="CONSOLE"/>
</Root>
</Loggers>
</Configuration>
此配置的输出如下:
{
"timeMillis" : 1404902036494,
"thread" : "main",
"level" : "ERROR",
"loggerName" : "ir.cvas.log4j.json.Main",
"message" : "description=\"I'm so fucked...\" id=\"12312312312312321\"",
"endOfBatch" : false,
"loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
"source" : {
"class" : "ir.cvas.log4j.json.Main",
"method" : "main",
"file" : "Main.java",
"line" : 24
}
}
endOfBatch
和loggerFqcn
。有可能吗?MapMessage
的转换方式。我想要像Json对象而不是单个字符串,像这样:"message": { "description"="I'm so fucked...", "id"="12312312312312321" }
或者至少压平MapMessage
个字段来记录消息。有人可以帮忙吗?
答案 0 :(得分:2)
您可以自定义JacksonFactory
类,以便仅包含日志条目中所需的字段名称。 JacksonFactory
中的默认实现仅排除日志条目中的两个字段,即位置和属性(也基于参数属性和源)。但是,如果要排除更多字段,可以添加更多字段名称以排除要排除的属性集,以下是示例
ObjectWriter newWriter(final boolean locationInfo, final boolean properties, final boolean compact) {
final SimpleFilterProvider filters = new SimpleFilterProvider();
final Set<String> except = new HashSet<>(5);
if (!locationInfo) {
except.add(this.getPropertNameForSource());
}
if (!properties) {
except.add(this.getPropertNameForContextMap());
}
except.add(this.getPropertNameForNanoTime());
except.add("loggerFqcn");
except.add("endOfBatch");
filters.addFilter(Log4jLogEvent.class.getName(), SimpleBeanPropertyFilter.serializeAllExcept(except));
final ObjectWriter writer = this.newObjectMapper().writer(compact ? this.newCompactPrinter() : this.newPrettyPrinter());
return writer.with(filters);
}
答案 1 :(得分:0)
我的回答基于this manual reference。
1)显然,JSONLayout采用的唯一参数是charset,compact,complete,properties和locationInfo。不幸的是,根据我的有限研究,删除endOfBatch和loggerFqcn似乎不可行。 (但这很奇怪,因为参考手册中的示例输出不包括这些字段。)
2)这几乎肯定不可能。 log4j中的日志条目的概念涉及字符串消息,可能是throwable,日志级别和一些其他静态事物。如果不编写自定义类,则无法使用自定义字段。 This SO question描述了这样做,尽管出于该问题的目的,最终使用了MDC。由于您希望每个条目中的自定义字段不同,因此MDC无法满足您的需求。我不确定你的意思是“扁平化”。
3)不幸的是,它看起来并不像它可用。 PatternLayout更加可定制; AFAIK你必须自己定制JSONLayout。
答案 2 :(得分:0)
可以使用Log4j扩展名执行此操作。有关示例,请参阅https://github.com/metamx/sumologic-log4j2-appender/blob/master/src/main/java/com/sumologic/log4j/core/SumoJsonLayout.java#L117-L237。基本上,您可以使用任何杰克逊注释来扩展LogEvent
,以便自定义打印出来的内容,但是您需要某种布局才能将事件强制转换为自定义字段命名的事件对象。
答案 3 :(得分:0)
Pom.xml:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-layout-template-json</artifactId>
<version>2.14.1</version>
</dependency>
log4j2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<JsonTemplateLayout eventTemplateUri="classpath:JsonTemplateLayout.json" />
</Console>
</Appenders>
<Loggers>
<Logger name="com.logging.a.b" level="error" additivity="false">
<AppenderRef ref="console" />
</Logger>
</Loggers>
</Configuration>
src/main/resources/JsonTemplateLayout.json:
{
"version": "1.1",
"hostName": "${hostName}",
"field1": "${env:JAVA_HOME}",
"field2": "${sys:os.name}",
"time": {
"$resolver": "timestamp",
"pattern": {
"format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
"timeZone": "UTC"
}
},
"level": {
"$resolver": "level",
"field": "name"
},
"loggerName": {
"$resolver": "logger",
"field": "name"
},
"message": {
"$resolver": "message",
"stringified": true
},
"source": {
"class": {
"$resolver": "source",
"field": "className"
},
"method": {
"$resolver": "source",
"field": "methodName"
},
"file": {
"$resolver": "source",
"field": "fileName"
},
"line": {
"$resolver": "source",
"field": "lineNumber"
}
},
}
您可以通过更改上述模板文件来添加和删除字段,或更改字段名称。 在此处查看更多示例:json template file