是否有建议的方法可以通过logback将Spring Boot引导至JSON格式日志

时间:2018-12-11 18:41:27

标签: spring-boot logging logback spring-logback logz.io

使用spring boot 2.1.1.RELEASE可以通过提供一个logback-spring.xml文件,如下所示将日志格式化为JSON:

<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
        <layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
            <timestampFormat>yyyy-MM-dd'T'HH:mm:ss.SSSX</timestampFormat>
            <timestampFormatTimezoneId>Etc/UTC</timestampFormatTimezoneId>
            <jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
                <prettyPrint>true</prettyPrint>
            </jsonFormatter>
        </layout>
    </encoder>
</appender>

<root level="INFO">
    <appender-ref ref="stdout" />
</root>

并添加到pom.xml

<dependency>
            <groupId>ch.qos.logback.contrib</groupId>
            <artifactId>logback-json-classic</artifactId>
            <version>0.1.5</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback.contrib</groupId>
            <artifactId>logback-jackson</artifactId>
            <version>0.1.5</version>
        </dependency>

确实会导致类似以下消息:

{
  "timestamp" : "2018-12-11T18:20:25.641Z",
  "level" : "INFO",
  "thread" : "main",
  "logger" : "com.netflix.config.sources.URLConfigurationSource",
  "message" : "To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.",
  "context" : "default"
}

为什么?

我正在试用logz.io,当日志以JSON格式格式化时,它似乎表现得更好,某些运货人在处理多行日志时遇到了麻烦,就像我们在Java堆栈跟踪中看到的那样;当以JSON格式格式化时,它可以自动解析诸如levelmessage,如果有MDC数据,它将自动获取。

对于将日志传送到logzio的几种方法,例如他们的docker映像和使用rsyslog而不使用JSON格式的日志消息,我有一些不太好的经验。

问题在于这种方法

对于控制台附加来说可以正常工作,但是spring boot提供了logging.file=test.loglogging.level.com.example=WARNlogging.pattern.console之类的功能。我确实可以从spring-boot-2.1.1.RELEASE.jar!/org/springframework/boot/logging/logback/base.xml导入托管配置,而托管配置又依次导入console-appender.xml and file-appender.xml`。

控制台附加程序的示例

<included>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>
</included>

文件附加器的示例

<included>
    <appender name="FILE"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
        <file>${LOG_FILE}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
            <maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize>
            <maxHistory>${LOG_FILE_MAX_HISTORY:-0}</maxHistory>
        </rollingPolicy>
    </appender>
</included>

这两个正是我支持属性的spring配置所需要的,但是它们不包含我需要的编码器/布局。

在我的初始测试中,似乎不能简单地将我的追加器命名为相同的追加器并提供布局。例如:

<configuration>

    <include resource="org/springframework/boot/logging/logback/base.xml"/>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
                <timestampFormat>yyyy-MM-dd'T'HH:mm:ss.SSSX</timestampFormat>
                <timestampFormatTimezoneId>Etc/UTC</timestampFormatTimezoneId>
                <jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
                    <prettyPrint>true</prettyPrint>
                </jsonFormatter>
            </layout>
        </encoder>
    </appender>



    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>

导致消息以JSON和纯文本格式记录。

我确实可以将这3个文件的内容复制并粘贴到我的自定义配置中,而不是完全导入它们。然后,我可以覆盖我要自定义的内容。

但是,随着春天的发展和可能增加功能的新版本的发布,我将永远强迫自己保持,复制和粘贴新文件并进行更改和测试。

有什么更好的办法吗?

  • 仅对附加程序进行附加更改,而不是完全重新定义它们,例如保留春季的配置,但提供我自己的编码器或布局,以供这些附加程序使用。
  • 完全通过属性将spring配置为JSON日志,而无需任何配置-我对此表示怀疑:S

脚注:logzio确实提供了a dependency可以导入的功能,但是我不喜欢将日志记录提供程序直接耦合到代码中的想法。我觉得,如果伺服器恰巧将JSON日志生成到stdout或文件中,那么任何提供程序都可以轻松地处理这些日志并将其发送到某个目的地。

3 个答案:

答案 0 :(得分:1)

我使用如下所示的方法,一直运行良好。

Spring Boot的建议是命名文件logback-spring.xml并将其放置在src/main/resources/下,这使我们能够在回溯中使用spring配置文件。 因此,在下面的文件中,您将看到对于LOCAL配置文件,您可以以标准方式登录,但是对于服务器或容器上的部署,则可以使用其他日志记录策略。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [YourApp:%thread:%X{X-B3-TraceId}:%X{X-B3-SpanId}] %logger{40} - %msg%n
            </pattern>
        </encoder>
    </appender>
    <appender name="jsonstdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
            <providers>
                <timestamp>
                    <timeZone>EST</timeZone>
                </timestamp>
                <pattern>
                    <pattern>
                        {
                        "level": "%level",
                        "service": "YourApp",
                        "traceId": "%X{X-B3-TraceId:-}",
                        "spanId": "%X{X-B3-SpanId:-}",
                        "thread": "%thread",
                        "class": "%logger{40}",
                        "message": "%message"
                        }
                    </pattern>
                </pattern>
                <stackTrace>
                    <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
                        <maxDepthPerThrowable>30</maxDepthPerThrowable>
                        <maxLength>2048</maxLength>
                        <shortenedClassNameLength>20</shortenedClassNameLength>
                        <rootCauseFirst>true</rootCauseFirst>
                    </throwableConverter>
                </stackTrace>
            </providers>
        </encoder>
    </appender>
    <root level="info">
    <springProfile name="LOCAL">
      <appender-ref ref="stdout" />
    </springProfile>
    <springProfile name="!LOCAL">
      <appender-ref ref="jsonstdout" />
    </springProfile>
  </root>

</configuration>

答案 1 :(得分:0)

我没有使用任何依赖项。 只需通过application.yml完成,仅此而已。 该解决方案也解决了多行日志问题。

logging:
  pattern:
    console: "{\"time\": \"%d\", \"level\": \"%p\", \"correlation-id\": \"%X{X-Correlation-Id}\", \"source\": \"%logger{63}:%L\", \"message\": \"%replace(%m%wEx{6}){'[\r\n]+', '\\n'}%nopex\"}%n"

答案 2 :(得分:0)

听起来您需要从此处https://github.com/spring-projects/spring-boot/tree/v2.1.1.RELEASE/spring-boot-project/spring-boot/src/main/resources/org/springframework/boot/logging/logback将4个文件中的3个修改粘贴复制到您的配置中。

好消息是您不需要复制粘贴https://github.com/spring-projects/spring-boot/blob/v2.1.1.RELEASE/spring-boot-project/spring-boot/src/main/resources/org/springframework/boot/logging/logback/defaults.xml

可以像这样<include resource="org/springframework/boot/logging/logback/default.xml"/>

这将为您提供一些Spring的默认配置,而无需复制和粘贴