【问题标题】:Log4j Log to STDOUT then format to JSON layout for LogstashLog4j 记录到 STDOUT,然后格式化为 Logstash 的 JSON 布局
【发布时间】:2018-07-18 23:55:48
【问题描述】:

我有一个在 Kubernetes 集群和 EFK 堆栈中运行的 Spring Boot 应用程序(如 ELK,但使用 Fluentd 代替 Logstash,它被用作轻量级的替代方案从所有 kubernetes pod 收集日志并将它们发送到 elasticsearch)。

为了使日志适应 JSON 输出,我使用了 logstash-logback-encoder 库:

<dependency>
  <groupId>net.logstash.logback</groupId>
  <artifactId>logstash-logback-encoder</artifactId>
  <version>4.11</version>
</dependency>

开箱即用,我将日志转换为 JSON(这很棒)。

我登录到 STDOUT,所有内容都被提取并发送到 Elasticsearch。 在 Spring Boot 应用程序中不需要特殊的日志配置。

但问题我现在遇到的问题是,在从 Kubernetes pod 的 STDOUT 实时读取我的日志时,使用所有 JSON 格式很难读取它们。

例子:

{"@timestamp":"2018-02-08T12:49:06.080+01:00","@version":1,"message":"Mapped \"{[/error],produces=[text/html]}\" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)","logger_name":"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping","thread_name":"main","level":"INFO","level_value":20000}
{"@timestamp":"2018-02-08T12:49:06.080+01:00","@version":1,"message":"Mapped \"{[/error]}\" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)","logger_name":"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping","thread_name":"main","level":"INFO","level_value":20000}
{"@timestamp":"2018-02-08T12:49:06.098+01:00","@version":1,"message":"Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]","logger_name":"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping","thread_name":"main","level":"INFO","level_value":20000}
{"@timestamp":"2018-02-08T12:49:06.098+01:00","@version":1,"message":"Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]","logger_name":"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping","thread_name":"main","level":"INFO","level_value":20000}
{"@timestamp":"2018-02-08T12:49:06.137+01:00","@version":1,"message":"Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]","logger_name":"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping","thread_name":"main","level":"INFO","level_value":20000}
{"@timestamp":"2018-02-08T12:49:06.268+01:00","@version":1,"message":"Registering beans for JMX exposure on startup","logger_name":"org.springframework.jmx.export.annotation.AnnotationMBeanExporter","thread_name":"main","level":"INFO","level_value":20000}
{"@timestamp":"2018-02-08T12:49:06.333+01:00","@version":1,"message":"Initializing ProtocolHandler [\"http-nio-8080\"]","logger_name":"org.apache.coyote.http11.Http11NioProtocol","thread_name":"main","level":"INFO","level_value":20000}
{"@timestamp":"2018-02-08T12:49:06.355+01:00","@version":1,"message":"Starting ProtocolHandler [\"http-nio-8080\"]","logger_name":"org.apache.coyote.http11.Http11NioProtocol","thread_name":"main","level":"INFO","level_value":20000}

我要做的是以“普通非 JSON”格式登录到 STDOUT,然后以 JSON 格式将日志发送到 Fluentd。

我正在尝试配置两个日志附加器(一个用于 STDOUT,另一个用于 Fluentd 的 JSON 格式)但我很确定这会复制数据(Fluentd 将获得 JSON 格式和 STDOUT)。

我的 B 计划是构建一个用于部署的映像(不使用 JSON 格式),另一个用于生产,但这更像是 Z 计划,因为我也想在生产中监控这些 pod。

我的问题是如何使用可能的一个日志附加程序或不复制 Fluentd 中的数据来做到这一点。有没有我没有想到的不同方法?

【问题讨论】:

    标签: spring log4j fluentd


    【解决方案1】:

    尽管我很想提出一个解决方案,但最后我还是使用了jqjson parser 在 cli 上查看我的日志。我这样做是为了避免重复日志数据,不必创建文件,也不必专门配置 fluentd 以从文件中读取日志。

    【讨论】:

      【解决方案2】:

      我假设您使用的是 Logback,而不是您标记的 Log4j,因为您链接到的 logstash 库似乎是为 Logback 编写的。

      最简单的解决方案可能是将 fluentd 配置为从文件读取日志并将 JSON 附加程序重定向到该文件。

      有一个关于尾部输入插件的article,但基本上你可以这样配置它:

      logback.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <configuration>
      
        <!-- JSON appender for log collection -->
        <appender name="json" class="ch.qos.logback.core.rolling.RollingFileAppender">
          <file>/some/path/to/your/file.log</file>
          <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>/some/path/to/your/file.log.%d{yyyy-MM-dd}</fileNamePattern>
            <maxHistory>30</maxHistory>
          </rollingPolicy>
          <encoder class="net.logstash.logback.encoder.LogstashEncoder" />
        </appender>
      
        <!-- Console appender for humans -->
        <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
          <!-- Set threshold for the console log here if you want the
            log collection to get all log messages regardless of level -->
          <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
              <level>INFO</level>
          </filter>
          <!-- encoders are assigned the type
            ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
          <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
          </encoder>
        </appender>
      
        <!-- Tie it all together -->
        <root level="all">
          <appender-ref ref="json" />
          <appender-ref ref="console" />
        </root>
      </configuration>
      

      流利

      <source>
        @type tail
        path /some/path/to/your/file.log
        pos_file /some/path/to/your/file.log
        format json
      </source>
      

      根据文档,fluentd在完成旧文件后会跟随翻转并从新文件的开头开始。

      如果您希望控制台输出与常规 Spring Boot 应用程序相同,您可以从 their configuration 复制模式

      【讨论】:

        猜你喜欢
        • 2016-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-13
        • 2022-01-24
        • 1970-01-01
        相关资源
        最近更新 更多