微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 append 而不是 LogstashMarker

如何解决使用 append 而不是 LogstashMarker

我在我们的环境中偶然发现了丢失的日志消息。

我们在 Java 应用程序中使用 ELK 堆栈和带有 logstash-logback-encoder 的 logback。为了进行结构化查询,我们使用 LogstashMarkers 将结构化参数附加到日志中。对于丢失的日志消息,它是一个字符串,其中包含一个 JSON。

一些日志消息完全丢失。不仅没有保存标记,而且还保存了完整的日志消息。它们在 Kibana 中不可见。我们的应用程序或 logstash 服务器的日志中没有错误

我可以用最少的代码创建一个示例存储库并将其发布到 GitHub:https://github.com/seism0saurus/logging-issue

要运行它,您需要一个 logstash 服务器和 netcat。 该项目中的记录器配置为使用控制台附加程序,因此我们有一个参考,即真正记录了哪些消息。 此外,localhost:8081 上的 netcat 服务器有一个 appender,logstash 服务器有一个 appender。两者具有相同的配置。只是地址不同。所以我很确定消息会发送到logstash服务器,如果它发送到netcat。

下面是主类的代码

@SpringBootApplication
public class LoggingIssueApplication {

    private static final Logger LOGGER = getLogger("customLogger");
    private static final String MESSAGE = "{  \"ordernumber\": \"Test1\",\"shippingmethod\": \"homeDelivery\",\"customer\": {    \"id\": \"1337\",\"salutation\": \"Mr\",\"name\": \"seism0saurus\",\"birthdate\": \"1900-05-01\",\"email\": \"test@seism0saurus.de\",\"phone\": \"\"  },\"billingAddress\": {    \"name\": \"seism0saurus\",\"address\": \"Teststreet 5\",\"address2\": \"\",\"postcode\": \"90451\",\"city\": \"Nürnberg\",\"country\": \"Deutschland\",\"countrycode\": \"DEU\"  },\"shippingAddress\": {    \"name\": \"seism0saurus\",\"totalItems\": 1,\"items\": [    {      \"position\": 53,\"bundlenumber\": 53,\"itemnumber\": \"900508\",\"itemdescription\": \"Dinosaur Cookies\",\"quantity\": 4,\"saleType\": \"KL\",\"saleItemType\": \"\",\"grossAmount\": 40.0,\"discounts\": [      ]    }  ]}";

    public static void main(String[] args) {
        SpringApplication.run(LoggingIssueApplication.class,args);
    }

    @EventListener(ApplicationReadyEvent.class)
    public void testAppender() throws InterruptedException {

        LOGGER.warn("1 - Log without marker and message as parameter: {}",MESSAGE);

        LogstashMarker payloadMarker = Markers.append("payload",MESSAGE);
        LOGGER.warn(payloadMarker,"2 - Log with payload marker without parameter");
        LOGGER.warn(payloadMarker,"3 - Log with payload marker and message as parameter: {}",MESSAGE);

        LogstashMarker rawMarker = Markers.appendRaw("raw",MESSAGE);
        LOGGER.warn(rawMarker,"4 - Log with raw marker without parameter");

        //Needed,so the loggers can finish their job before the application is shut down.
        Thread.sleep(5000);
    }
}

这是logstash appender:

  <appender name="nc" class="net.logstash.logback.appender.LogstashTcpsocketAppender">
    <destination>localhost:8081</destination>
    <keepAliveDuration>5 minutes</keepAliveDuration>
    <listener class="net.logstash.logback.appender.listener.FailureSummaryLoggingAppenderListener"/>

    <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
      <providers>
        <mdc/>
        <context/>
        <version/>
        <logLevel/>
        <logLevelValue/>
        <loggerName/>

        <pattern>
          <pattern>
            {
            "serviceName": "logging-issue","environment": "dev","errorMessage": "%ex{0}"
            }
          </pattern>
        </pattern>

        <threadName/>
        <message/>
        <logstashMarkers/>
        <arguments/>
        <stackTrace/>
      </providers>
    </encoder>
  </appender>

当我运行应用程序时,我收到了预期的 4 条日志消息。所有 4 个都出现在控制台和 netcat 服务器中。但是只有数字 1 和 4 出现在 kibana 中。 因此,我认为处理 Markers.appendMarkers.appendRaw 存在差异。 MESSAGE一个包含 JSON 的字符串。但我希望,我不必检查字符串内容来决定调用哪个方法

logstash 服务器的日志中没有错误信息。 这似乎不是连接错误、未知或无法访问的主机或缓冲区已满。我复制了所有这些案例,它们在日志中留下了有意义的错误消息。

你知道吗,这里发生了什么?我是否必须检查我想放入 Marker 的字符串的内容以防止丢失完整的日志消息?

编辑: 我获得了有关该问题的更多信息。我本地机器上 docker 中的一个 logstash 实例确实接收了所有日志,并使用以下管道将它们写入文件

input {
  tcp {
    port => 9000
    codec => json_lines
  }
}

output {
  file {
    path => "/mounted_dir/logstash.out"
    codec => line {
      format => "%{message}"
    }
  }
}

编辑 2: 基于 https://jaxenter.de/elastic-stack-containern-docker-86374 我构建了一个完整的 ELK 堆栈进行比较。它不会丢失任何日志消息。 因此,我们的管理员构建了 ELK 堆栈的问题所在。你有什么想法吗?

解决方法

我们发现了问题。为了帮助遇到这个问题的其他人,我将在这里解释问题和解决方案。

日志消息已成功传输到logstash和elasticsearch。所以这些日志中没有错误。 我们找不到日志条目的原因是“有效负载”字段。我们有多个服务,其中之一是发送一个对象而不是一个字符串。这会导致映射冲突并且无法访问日志消息。 error message

我们的解决方案是定义显式映射并引入命名约定。现在我们有一个文本字段 payload 和一个对象字段 payloadAsObject。我们的所有服务都使用此约定。

过去有问题的日志条目已经足够了,所以我们可以删除旧索引并解决冲突。但是有可能在不停机的情况下重新索引数据。例如这个:https://medium.com/craftsmenltd/rebuild-elasticsearch-index-without-downtime-168363829ea4

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。