3

我正在使用 Dropwizard 1.3.2,它使用 SLF4J over Logback 进行日志记录。我正在为 ElasticSearch 的摄取编写日志,所以我想我会使用 JSON 日志记录并制作一些 Kibana 仪表板。但我真的希望每条日志消息不止一个 JSON 项目 - 如果我正在记录一个包含十个字段的状态更新,理想情况下我希望记录该对象并将 JSON 字段显示为 JSON 日志中的顶级条目。我确实让 MDC 工作,但这非常笨拙并且不会使对象变平。

事实证明这很困难!我怎样才能做到这一点?我让它在 JSON 中记录,但我不能很好地记录多个 JSON 字段!

我做过的事情:

我的 Dropwizard 配置有这个附加程序:

  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”,但没有关于如何使用它的文档,无论我在那里放什么,我都会得到一个“没有字符串参数构造函数/工厂方法来反序列化字符串值”错误。(文档有一个示例值“@timestamp”但没有解释,即使这样也会产生错误。他们也有像“(requestTime:request_time,userAgent:user_agent)”这样的例子,但同样,没有记录,我什么也做不了类似的工作,我尝试过的一切都会产生上述错误。

我确实让 MDC 工作,但是将每个项目插入 MDC 然后清除它似乎很愚蠢。

而且我可以反序列化一个对象并将其记录为嵌套的 JSON,但这似乎也很奇怪。

我在这方面看到的所有答案都是旧的 - 有人对如何在 Dropwizard 中很好地做到这一点有任何建议吗?

4

1 回答 1

0

您可以使用自定义 logger factory在 Dropwizard 中显式使用 logback ,然后使用logstash-logback-encoder进行设置,并将其配置为写入 JSON appender。

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>

Github 上的文件

并产生如下输出:

{"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}
于 2020-05-03T01:42:10.430 回答