我正在使用Dropwizard 1.3.2,它通过Logback使用SLF4J进行日志记录。我正在编写日志,以便摄取到ElasticSearch中,所以我想使用JSON日志,并制作一些Kibana仪表盘。但我真的希望每条日志消息不止一个JSON项--如果我记录一个有十个字段的状态更新,我理想的情况是记录对象,并让JSON字段在JSON日志中显示为顶层条目。我确实让MDC工作了,但那是非常笨拙的,而且不能使对象扁平化。
这原来是很困难的! 我怎么才能做到这一点呢?我让它用JSON记录,但我不能很好地记录多个JSON字段!
我做过的事情。
我的Dropwizard配置有这个appender。
appenders:
- type: console
target: stdout
layout:
type: json
timestampFormat: "ISO_INSTANT"
prettyPrint: false
appendLineSeparator: true
additionalFields:
keyOne: "value one"
keyTwo: "value two"
flattenMdc: true
额外的字段出现了,但这些值似乎在配置文件中是固定的,不会改变。有一个 "customFieldNames",但没有关于如何使用它的文档,无论我在那里放什么,我都得到一个 "没有String-argument constructorfactory方法从String值反序列化 "的错误。(文档中有一个"@timestamp "的示例值,但没有解释,甚至连这个都会产生错误。他们也有像"(requestTime:request_time, userAgent:user_agent) "这样的例子,但同样没有文档,我也不能让类似的东西工作,我试过的所有东西都会产生上述错误。
我确实让MDC工作了,但是把每个项目都插入MDC中,然后再清除它,这似乎很愚蠢。
而且我可以反序列化一个对象,并将其记录为嵌套的JSON,但这看起来也很奇怪。
我看到的关于这个问题的所有答案都是旧的--有人有什么建议可以告诉我如何在Dropwizard里面很好地完成这个任务吗?
你可以在Dropwizard中明确地使用logback,并使用 定制记录仪工厂,然后将其设置为 logstash-logback-encoder并将其配置为向JSON应用器写入。
JSON编码器可能是这样的。
<included>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<pattern>
<pattern>
{
"id": "%uniqueId",
"relative_ns": "#asLong{%nanoTime}",
"tse_ms": "#asLong{%tse}",
"start_ms": "#asLong{%startTime}",
"cpu": "%cpu",
"mem": "%mem",
"load": "%loadavg"
}
</pattern>
</pattern>
<timestamp>
<!-- UTC is the best server consistent timezone -->
<timeZone>${encoders.json.timeZone}</timeZone>
<pattern>${encoders.json.timestampPattern}</pattern>
</timestamp>
<version/>
<message/>
<loggerName/>
<threadName/>
<logLevel/>
<logLevelValue/><!-- numeric value is useful for filtering >= -->
<stackHash/>
<mdc/>
<logstashMarkers/>
<arguments/>
<provider class="com.tersesystems.logback.exceptionmapping.json.ExceptionArgumentsProvider">
<fieldName>exception</fieldName>
</provider>
<stackTrace>
<!--
https://github.com/logstash/logstash-logback-encoder#customizing-stack-traces
-->
<throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
<rootCauseFirst>${encoders.json.shortenedThrowableConverter.rootCauseFirst}</rootCauseFirst>
<inlineHash>${encoders.json.shortenedThrowableConverter.inlineHash}</inlineHash>
</throwableConverter>
</stackTrace>
</providers>
</encoder>
</included>
并产生这样的输出。
{"id":"FfwJtsNHYSw6O0Qbm7EAAA","relative_ns":20921024,"tse_ms":1584163814965,"start_ms":null,"@timestamp":"2020-03-14T05:30:14.965Z","@version":"1","message":"Creating Pool for datasource 'logging'","logger_name":"play.api.db.HikariCPConnectionPool","thread_name":"play-dev-mode-akka.actor.default-dispatcher-7","level":"INFO","level_value":20000}