使用 OpenTelemetry 在 Google Cloud Run 上跟踪传播

Posted

技术标签:

【中文标题】使用 OpenTelemetry 在 Google Cloud Run 上跟踪传播【英文标题】:Trace Propagation on Google Cloud Run with OpenTelemetry 【发布时间】:2021-05-27 04:22:06 【问题描述】:

我有一个 Flask 应用程序与 Python gRPC 服务通信,两者都部署在 Google Cloud Run 上。检测应用程序后,我可以在 Google Trace 上看到跟踪,但它们似乎都有不同的跟踪 ID,这意味着两个服务之间的跟踪没有链接在一起。这是我的设置代码,用于在每侧设置 grpc/Flask 仪器跟踪两个服务:

import logging
from opentelemetry import trace
from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleExportSpanProcessor
from opentelemetry.propagators import set_global_textmap
from opentelemetry.tools.cloud_trace_propagator import CloudTraceFormatPropagator
from google.auth.exceptions import DefaultCredentialsError

logger = logging.getLogger(__name__)

def setup_tracing():
    """
    Setup Tracing on Google Cloud. The Service Account Roles must have `Cloud Trace Agent`
    Role added for traces to be ingested.
    """

    trace.set_tracer_provider(TracerProvider())
    try:
        # If running on Google Cloud, will use instance metadata service account credentials to initialize
        trace.get_tracer_provider().add_span_processor(
            SimpleExportSpanProcessor(CloudTraceSpanExporter())
        )
        # Using the X-Cloud-Trace-Context header
        set_global_textmap(CloudTraceFormatPropagator())

        logger.info("Tracing Setup. Exporting Traces to Google Cloud.")
    except DefaultCredentialsError:
        # Not running on Google Cloud so will use console exporter
        from opentelemetry.sdk.trace.export import ConsoleSpanExporter
        trace.get_tracer_provider().add_span_processor(
            SimpleExportSpanProcessor(ConsoleSpanExporter())
        )
        logger.info("Tracing Setup. Exporting Traces to Console.")

在本地,我可以使用 ConsoleSpanExporter 看到两个服务上的 Trace ID 匹配,但是在 Google Cloud Run 上,它们显然不会在 Google Trace 上产生单独的跟踪,所以我想知道 Networking 是否删除了服务之间的标头还是发生了其他事情,这意味着跟踪 ID 没有被传播?

作为额外说明,我还注意到 Cloud Run 的 Trace/Span ID 前面的负载均衡器没有使用 CloudTraceSpanFormatPropagator() 进行传播,这也使我的日志变得混乱,因为日志没有嵌套在一起用于请求.

【问题讨论】:

您的问题和答案非常有帮助,因为我尝试将跟踪添加到类似的设置中 - 感谢您如此彻底!我也遇到了跟踪传播的问题(***.com/questions/69440929/…),尽管您发现的错误已得到修复。这是一个很长的镜头,但如果你有机会看看我的问题,我会非常感激,因为感觉这方面的文档仍然有些缺乏! 【参考方案1】:

经过数小时的调试,结果发现它是关于 Python gRPC 客户端工具的糟糕文档。对于不安全的(本地主机)通道,文档有效并且客户端被检测。对于安全通道(根据 Google Cloud Run 的要求),您需要传入 channel_type='secure'。我不确定为什么会这样设计并在模块上提出问题:https://github.com/open-telemetry/opentelemetry-python-contrib/issues/365

此外,您需要使用 X-Cloud-Trace-Context 标头来确保您的跟踪使用与 Google Cloud 上运行的负载平衡器和 AppServer 相同的跟踪 ID,并在 Google Trace 中链接,但其传播器的默认实现使用不能在 gRPC 元数据键中使用的大写字母,因此会引发验证错误。我参加了下面的课程并将其全部设为小写,现在一切正常:

https://github.com/GoogleCloudPlatform/opentelemetry-operations-python/blob/master/opentelemetry-tools-google-cloud/src/opentelemetry/tools/cloud_trace_propagator.py

最后,我在将我的日志链接到 Google Cloud 日志上的跟踪时遇到了一个长期存在的问题,文档说使用 Hex Trace ID 和 Hex Span ID,但它们不起作用,因为我使用了错误的 OpenTelemetry 函数来格式化他们。然而,这段代码可以工作,我现在可以在 Google Trace 的跟踪列表视图中看到我的日志和我的跟踪!

from opentelemetry import trace
from opentelemetry.trace.span import get_hexadecimal_trace_id, get_hexadecimal_span_id

        current_span = trace.get_current_span()
        if current_span:
            trace_id = current_span.get_span_context().trace_id
            span_id = current_span.get_span_context().span_id
            if trace_id and span_id:
                logging_fields['logging.googleapis.com/trace'] = f"projects/self.gce_project/traces/get_hexadecimal_trace_id(trace_id)"
                logging_fields['logging.googleapis.com/spanId'] = f"get_hexadecimal_span_id(span_id)"
                logging_fields['logging.googleapis.com/trace_sampled'] = True

花了一段时间,但我想是我在一个新的、没有很好记录的(在这个领域)谷歌云服务上选择了一个 Alpha(刚刚变成 Beta)框架 (OpenTelemetry) 的错。但是有了这些修复,现在一切正常,并且更容易调试问题并查看完整的端到端请求!

【讨论】:

以上是关于使用 OpenTelemetry 在 Google Cloud Run 上跟踪传播的主要内容,如果未能解决你的问题,请参考以下文章

Google Cloud Trace Opentelemetry Java 示例代码未显示在 Google Cloud Trace 仪表板上

如何将 OpenTelemetry Java 代理生成的跟踪导出到 Google Cloud Trace?

如何在 gRPC 服务器存根中从 ctx 创建 OpenTelemetry span

OpenTelemetry 实现方案

Observability:OpenTelemetry 在 Elastic APM 中的集成

OpenTelemetry 收集器都有哪些用例?