日志关联编辑

日志关联 允许您导航到属于特定跟踪的所有日志,反之亦然:对于特定日志,查看它是在哪个上下文中记录的以及用户提供了哪些参数。

为了将应用程序中的日志与 Elastic APM Go 代理捕获的事务相关联,您的日志必须包含以下一个或多个标识符

为了将日志与服务和环境相关联,日志还应包含以下字段

手动日志关联编辑

如果代理提供的日志记录集成不适合或不适用于您的应用程序,则可以使用代理的 API 手动注入跟踪 ID。您可以采用两种主要方法,具体取决于您使用的是结构化日志记录还是非结构化日志记录。

手动日志关联(结构化)编辑

为了将结构化日志与跟踪和服务相关联,应将 上面 定义的字段添加到日志中。

给定一个事务对象,您可以使用 apm.Transaction.TraceContext 方法获取其跟踪 ID 和事务 ID。类似地,给定一个 span 对象,您可以使用 apm.Span.TraceContext 获取其 span ID。

如果您使用上下文 API 来启动事务和 span,则可以使用 apm.TransactionFromContext 获取上下文的当前事务,并使用 apm.SpanFromContext 获取当前 span。请注意,如果未对事务进行采样,则 apm.TransactionFromContext 将返回 nil。类似地,代理可能会丢弃 span,因此 apm.SpanFromContext 也可能返回 nil

labels := make(map[string]string)
tx := apm.TransactionFromContext(ctx)
if tx != nil {
	traceContext := tx.TraceContext()
	labels["trace.id"] = traceContext.Trace.String()
	labels["transaction.id"] = traceContext.Span.String()
	if span := apm.SpanFromContext(ctx); span != nil {
		labels["span.id"] = span.TraceContext().Span
	}
}

按照本文使用 Filebeat 摄取 JSON 编码的日志:如何使用 Elastic APM Go 代理检测您的 Go 应用程序

手动日志关联(非结构化)编辑

为了将非结构化日志(例如,基本的 printf 风格的日志记录,如标准库的 log 包)与跟踪和服务相关联,您需要在日志消息中包含跟踪 ID。然后,使用 Filebeat 提取它们。

如果您已经有一个事务或 span 对象,请使用 Transaction.TraceContextSpan.TraceContext 方法。跟踪、事务和 span ID 类型都提供 String 方法,这些方法产生它们的规范十六进制编码字符串表示形式。

traceContext := tx.TraceContext()
spanID := span.TraceContext().Span
log.Printf("ERROR [trace.id=%s transaction.id=%s span.id=%s] an error occurred", traceContext.Trace, traceContext.Span, spanID)

相反,如果您正在处理上下文对象,您可能更喜欢使用 TraceFormatter 函数。例如,您可以将其作为参数提供给 log.Printf,如下所示

log.Printf("ERROR [%+v] an error occurred", apm.TraceFormatter(ctx))

这将打印如下所示的日志消息

2019/09/17 14:48:02 ERROR [trace.id=cd04f33b9c0c35ae8abe77e799f126b7 transaction.id=cd04f33b9c0c35ae span.id=960834f4538880a4] an error occurred

为了使日志关联正常工作,必须从日志消息中提取跟踪 ID 并将其存储在 Elasticsearch 文档中的单独字段中。这可以通过 使用摄取管道解析数据 来实现,特别是通过使用 grok 处理器

{
  "description": "...",
  "processors": [
    {
      "grok": {
        "field": "message",
        "patterns": ["%{YEAR}/%{MONTHNUM}/%{MONTHDAY} %{TIME} %{LOGLEVEL:log.level} \\[trace.id=%{TRACE_ID:trace.id}(?: transaction.id=%{SPAN_ID:transaction.id})?(?: span.id=%{SPAN_ID:span.id})?\\] %{GREEDYDATA:message}"],
        "pattern_definitions": {
          "TRACE_ID": "[0-9A-Fa-f]{32}",
          "SPAN_ID": "[0-9A-Fa-f]{16}"
        }
      }
    }
  ]
}