如何解决使用 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.append
和 Markers.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。所以这些日志中没有错误。 我们找不到日志条目的原因是“有效负载”字段。我们有多个服务,其中之一是发送一个对象而不是一个字符串。这会导致映射冲突并且无法访问日志消息。
我们的解决方案是定义显式映射并引入命名约定。现在我们有一个文本字段 payload 和一个对象字段 payloadAsObject。我们的所有服务都使用此约定。
过去有问题的日志条目已经足够了,所以我们可以删除旧索引并解决冲突。但是有可能在不停机的情况下重新索引数据。例如这个:https://medium.com/craftsmenltd/rebuild-elasticsearch-index-without-downtime-168363829ea4
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。