一、OpenTelemetry

  1. OpenTracing介绍

因此,我们的Tracing技术方案以OpenTelemetry为实施标准,协议标准的一些Golang实现开源项目:

  1. https://github.com/open-telemetry/opentelemetry-go

其他第三方的框架和系统(如Jaeger/Prometheus/Grafana等)也会按照标准化的规范来对接OpenTelemetry,使得系统的开发和维护成本大大降低。

二、重要概念

我们先看看OpenTelemetry的架构图,我们这里不会完整介绍,只会介绍其中大家常用的几个概念。关于OpenTelemetry的内部技术架构设计介绍,可以参考 ,关于语义约定请参考:https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md

链路跟踪-背景知识 - 图2

主要负责创建Tracer,一般是需要第三方的分布式链路跟踪管理平台提供具体的实现。默认情况是一个空的TracerProvider (NoopTracerProvider),虽然也能创建Tracer但是内部其实不会执行具体的数据流传输逻辑。

Tracer

Tracer表示一次完整的追踪链路,tracer由一个或多个span组成。下图示例表示了一个由8span组成的tracer:

时间轴的展现方式会更容易理解:

  1. ––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time
  2. [Span A···················································]
  3. [Span B··············································]
  4. [Span D··········································]
  5. [Span C········································]
  6. [Span E·······] [Span F··] [Span G··] [Span H··]

Span是一条追踪链路中的基本组成要素,一个span表示一个独立的工作单元,比如可以表示一次函数调用,一次http请求等等。span会记录如下基本要素:

  • 服务名称(operation name
  • 服务的开始时间和结束时间
  • K/V形式的Tags
  • K/V形式的Logs
  • SpanContext

Span是这么多对象中使用频率最高的,因此创建也非常简便,例如:

  1. gtrace.NewSpan(ctx, spanName, opts...)

Attributes

AttributesK/V键值对的形式保存用户自定义标签,主要用于链路追踪结果的查询过滤。例如: http.method="GET",http.status_code=200。其中key值必须为字符串,value必须是字符串,布尔型或者数值型。 span中的Attributes仅自己可见,不会随着 SpanContext传递给后续span。 设置Attributes方式例如:

EventsAttributes类似,也是K/V键值对形式。与Attributes不同的是,Events还会记录写入Events的时间,因此Events主要用于记录某些事件发生的时间。Eventskey值同样必须为字符串,但对value类型则没有限制。例如:

  1. span.AddEvent("http.request", trace.WithAttributes(
  2. label.Any("http.request.header", headers),
  3. label.Any("http.request.baggage", gtrace.GetBaggageMap(ctx)),
  4. label.String("http.request.body", bodyContent),

SpanContext

SpanContext携带着一些用于跨服务通信的(跨进程)数据,主要包含:

  • 足够在系统中标识该span的信息,比如:span_id, trace_id
  • Baggage - 为整条追踪连保存跨服务(跨进程)的K/V格式的用户自定义数据。BaggageAttributes 类似,也是 K/V 键值对。与 Attributes 不同的是:

    • keyvalue都只能是字符串格式
    • Baggage不仅当前span可见,其会随着SpanContext传递给后续所有的子span。要小心谨慎的使用Baggage - 因为在所有的span中传递这些会带来不小的网络和CPU开销。

Propagator传播器用于端对端的数据编码/解码,例如:ClientServer端的数据传输,TraceIdSpanIdBaggage也是需要通过传播器来管理数据传输。业务端开发者往往对Propagator无感知,只有中间件/拦截器的开发者需要知道它的作用。OpenTelemetry的标准协议实现库提供了常用的TextMapPropagator,用于常见的文本数据端到端传输。此外,为保证TextMapPropagator中的传输数据兼容性,不应当带有特殊字符,具体请参考:https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md

GoFrame框架通过gtrace模块使用了以下传播器对象,并全局设置到了OpenTelemetry中:

三、支持组件

包括但不限于以下核心组件:

  • Http Client

HTTP客户端自动启用了链路跟踪特性,具体使用示例请参考后续示例章节。

  • Http Server

HTTP服务端自动启用了链路跟踪特性,具体使用示例请参考后续示例章节。

  • gRPC Client

gRPC客户端自动启用了链路跟踪特性,具体使用示例请参考后续示例章节。

  • gRPC Server

gRPC服务端自动启用了链路跟踪特性,具体使用示例请参考后续示例章节。

  • Logging

日志内容中需要注入当前请求的TraceId,以方便通过日志快速查找定位问题点。该特性是由glog组件实现,这需要开发者在输出日志的时候调用Ctx链式操作方法将context.Context上下文变量传递到当前输出日志操作链路中,没有传递context.Context上下文变量,就会丢失日志内容中的TraceId

  • ORM

数据库的执行是很重要的链路环节,Orm组件需要将自身的执行情况投递到链路中,作为执行链路的一部分。

  • Redis

Redis的执行也是很重要的链路环节,Redis需要将自身的执行情况投递到链路中,作为执行链路的一部分。

  • Utils

四、参考资料