elasticsearch 在将完整日志发送到logstash/elasticsearch之前将一半日志发送到RabbitMQ的方法
我有两个函数,每个函数都创建特定于一个事务的日志;它是一个多线程应用程序,因此func1的函数项对于所做的事务可以是随机的,但对于单个事务,它将仅通过func1、func2和func3顺序elasticsearch 在将完整日志发送到logstash/elasticsearch之前将一半日志发送到RabbitMQ的方法,elasticsearch,rabbitmq,logstash,apache-kafka,logstash-forwarder,elasticsearch,Rabbitmq,Logstash,Apache Kafka,Logstash Forwarder,我有两个函数,每个函数都创建特定于一个事务的日志;它是一个多线程应用程序,因此func1的函数项对于所做的事务可以是随机的,但对于单个事务,它将仅通过func1、func2和func3顺序 func1(transactionId) { log("%d Now in func1", transactionId); } func2(transactionId) { log("%d Now in func2", transactionId); } func3(transacti
func1(transactionId) {
log("%d Now in func1", transactionId);
}
func2(transactionId) {
log("%d Now in func2", transactionId);
}
func3(transactionId) {
log("%d Now in func3", transactionId);
}
现在,我想一次只为每笔交易写一次logstash;就是
1 Now in func1 Now in func2 Now in fun3
最后,这需要转到elasticsearch
我正在考虑将半个事务日志写入RabbitMQ临时队列,然后在完成事务后,将其提交给RabbitMQ生产者队列,以将消息发送到logstash
像
commit2RMQ执行logstash的时间应收到特定于要写入elasticsearch的事务的完整消息
问题:
尝试聚合与单个事务相关的不同日志行并不是一个简单的问题,特别是如果您将消息队列系统添加到混合中,作为要聚合的日志的中间存储。我会走另一条路,不涉及其他子系统,比如RabbitMQ 此外,如果试图将多个日志行连接成一个日志行,则会丢失每个日志行可以提供的详细信息,例如每个函数执行所需的时间。如果
func2
分别func3
引发异常,会发生什么情况?您是否应该存储仅由func1
组成的部分日志,分别只存储func1
和func2
我将要写的内容可能可以转换为任何语言和任何日志解决方案,但为了便于说明,我假设您的程序是用Java编写的,您使用的是Log4J
因此,我将利用(MDC)在每个日志行中存储事务ID(以及可能的其他数据,如用户名等)。这样,您就可以轻松地检索与单个事务相关的所有日志行。这样做的好处是,您不必聚合任何内容,只需提供足够的上下文信息,以便Kibana稍后可以为您完成
在伪代码中,您将事务ID直接添加到消息中。使用MDC而不是将ID记录到消息中的优点是,它可以避免在Logstash中解析所有消息,从而重新发现创建日志行时已经知道的事务ID
因此,在您的代码中,只要您有一个事务ID,就可以将其添加到当前的每线程日志上下文中,如下所示:
import org.apache.log4j.MDC;
...
func1(transactionId) {
// add the transaction ID to the logging context
MDC.put("transactionID", transactionId);
log("Now in func1");
}
func2(transactionId) {
log("Now in func2");
}
func3(transactionId) {
log("Now in func3");
}
然后在Log4J配置文件中,您可以使用%X{transactionID}
模式指定appender来存储它,在本例中,我将在线程名称之后添加它,但您可以将它放在任何您喜欢的地方:
log4j.appender.consoleAppender.layout.ConversionPattern = %d [%t] [%X{transactionID}] %5p %c - %m%n
您的日志将类似于以下内容:
2015-09-28T05:07:28.425Z [http-8084-2] [625562271762] INFO YourClass - Now in func1
2015-09-28T05:07:29.776Z [http-8084-2] [625562271762] INFO YourClass - Now in func2
2015-09-28T05:07:30.652Z [http-8084-2] [625562271762] INFO YourClass - Now in func3
^
|
the transaction ID is here
当您有这样的日志行时,通过Logstashgrok
过滤器检索事务ID并将其存储在日志存储索引中自己的transactionID
字段中就很容易了。在Kibana中,您可以搜索事务ID并按时间戳desc排序,这样就可以显示该事务的所有上下文
试试看 尝试聚合与单个事务相关的不同日志行不是一个简单的问题,特别是如果您将消息队列系统添加到混合中,作为要聚合的日志的中间存储。我会走另一条路,不涉及其他子系统,比如RabbitMQ 此外,如果试图将多个日志行连接成一个日志行,则会丢失每个日志行可以提供的详细信息,例如每个函数执行所需的时间。如果
func2
分别func3
引发异常,会发生什么情况?您是否应该存储仅由func1
组成的部分日志,分别只存储func1
和func2
我将要写的内容可能可以转换为任何语言和任何日志解决方案,但为了便于说明,我假设您的程序是用Java编写的,您使用的是Log4J
因此,我将利用(MDC)在每个日志行中存储事务ID(以及可能的其他数据,如用户名等)。这样,您就可以轻松地检索与单个事务相关的所有日志行。这样做的好处是,您不必聚合任何内容,只需提供足够的上下文信息,以便Kibana稍后可以为您完成
在伪代码中,您将事务ID直接添加到消息中。使用MDC而不是将ID记录到消息中的优点是,它可以避免在Logstash中解析所有消息,从而重新发现创建日志行时已经知道的事务ID
因此,在您的代码中,只要您有一个事务ID,就可以将其添加到当前的每线程日志上下文中,如下所示:
import org.apache.log4j.MDC;
...
func1(transactionId) {
// add the transaction ID to the logging context
MDC.put("transactionID", transactionId);
log("Now in func1");
}
func2(transactionId) {
log("Now in func2");
}
func3(transactionId) {
log("Now in func3");
}
然后在Log4J配置文件中,您可以使用%X{transactionID}
模式指定appender来存储它,在本例中,我将在线程名称之后添加它,但您可以将它放在任何您喜欢的地方:
log4j.appender.consoleAppender.layout.ConversionPattern = %d [%t] [%X{transactionID}] %5p %c - %m%n
您的日志将类似于以下内容:
2015-09-28T05:07:28.425Z [http-8084-2] [625562271762] INFO YourClass - Now in func1
2015-09-28T05:07:29.776Z [http-8084-2] [625562271762] INFO YourClass - Now in func2
2015-09-28T05:07:30.652Z [http-8084-2] [625562271762] INFO YourClass - Now in func3
^
|
the transaction ID is here
当你有日志行李