技术阅读摘要 - 2.OpenTelemetry技术概览

简介: 本系列的第二讲,我原先计划聊一下OpenTracing这个技术,但计划赶不上变化,我发现OpenTracing的官网上已经声明:这部分的技术将迁移到OpenTelemetry。

概览

本系列的第二讲,我原先计划聊一下OpenTracing这个技术,但计划赶不上变化,我发现OpenTracing的官网上已经声明:这部分的技术将迁移到OpenTelemetry。

从OpenTelemetry的官方定义来看: An observability framework for cloud-native software,它的重点在于两块:

  1. 可观察性:通过metrics、logs和traces数据,观察软件的运行情况
  2. 云原生:适配云原生理念

OpenTelemetry的图标采用了一个望远镜,可见其核心在于可观察性。

官方资料

核心概念

我们先引用官方对自身的定义:OpenTelemetry is a set of APIs, SDKs, tooling and integrations that are designed for the creation and management of telemetry data such as traces, metrics, and logs.

这句话指明了OpenTelemetry实现的3个重点数据:traces、metrics、logs。我们从简单到复杂,逐个讲述一下:

Logs

日志:依赖程序自身的打印。可通过ELK/EFK等工具采集到统一的平台并展示。

Metrics

指标:程序将运行中关键的一些指标数据保存下来,常通过RPC的方式Pull/Push到统一的平台。

常见的如请求数、请求延迟、请求成功率等,也可进行一定的计算后获得更复杂的复合指标。

Traces

分布式追踪:遵循Dapper等协议,获取一个请求在整个系统中的调用链路。

常见的如根据一个HTTP请求的requestID,获取其各个RPC、数据库、缓存等关键链路中的详情。

技术标准

到今天,OpenTelemetry还没有完全落地,但这不妨碍我们看清未来的发展方向。

Metrics以Prometheus为标准,Traces以Jaeger为标准,而Logs暂时还没有明确的标准,但业界基本以ELK或EFK为技术实现。而我们常会把Traces和Logs这两点结合起来,通过在应用程序的打印日志中添加对应的Traces,来更好地排查整个数据链路。

但这样还不够,Opentelemetry期望的是将三者都关联起来,而引入了Context这个概念。熟悉Go语言的同学都清楚,context被定义为上下文,用于程序中传递数据。而Opentelemetry将这个概念进一步扩大,包括了RPC请求、多线程、跨语言、异步调用等各种复杂场景。

OpenTelemetry的推进工作非常困难,但其带来的价值是不言而喻的。今天,我们依旧以Go语言为例,试试窥一斑而见全豹,对这个技术有个基本掌握。

Go语言示例

现状

参考官方在Go Package上的声明,Traces处于稳定状态,Metrics处于Alpha测试版本,而Logs则处于冻结状态。

可见日志的优先级放在了Traces和Metrics之后。从最终实现来说,只要确定了Traces和Metrics的具体标准,Logs的实现并没有那么复杂。

1. 创建Exporter

OpenTelemetry要求程序中收集到的数据,都通过一定的途径发送给外部,如控制台、外部存储、端口等,所以就有了Exporter这个概念。

这里以一个简单的控制台Exporter为例:

traceExporter, err := stdouttrace.New(
  stdouttrace.WithPrettyPrint(),
)
if err != nil {
  log.Fatalf("failed to initialize stdouttrace export pipeline: %v", err)
}

2. 创建Trace Provider

Traces这部分的概念比较多,这里先只讲解一个 - span。在分布式系统中,存在上下游的概念、也就是调用和被调用的关系,在分布式追踪系统中就将它们区分为不同的span。

示例代码初始化了Traces Provider,用于Traces相关的功能:

ctx := context.Background()
bsp := sdktrace.NewBatchSpanProcessor(traceExporter)
tp := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(bsp))

// Handle this error in a sensible manner 
defer func() { _ = tp.Shutdown(ctx) }()
如果要深入了解分布式追踪技术,建议搜索Dapper论文或网上的相关资料。

3. 创建Meter Provider

类似Traces,Metrics也需要一个Provider,但它的名字叫做Meter Provider。

我们看一下代码:

metricExporter, err := stdoutmetric.New(
  stdoutmetric.WithPrettyPrint(),
)

pusher := controller.New(
  processor.New(
    simple.NewWithExactDistribution(),
    metricExporter,
  ),
  controller.WithExporter(metricExporter),
  controller.WithCollectPeriod(5*time.Second),
)

err = pusher.Start(ctx)

// Handle this error in a sensible manner where possible
defer func() { _ = pusher.Stop(ctx) }()

抛开初始化部分,其中还包含了2个关键性的内容:

  1. 程序指标的计算部分
  2. metrics的发送方式采用了push,周期为5s

4. 设置全局选项

这部分的内容不多,也很容易理解,但在实际工程中的价值很大:让调用者更方便!

otel.SetTracerProvider(tp)
global.SetMeterProvider(pusher.MeterProvider())
propagator := propagation.NewCompositeTextMapPropagator(propagation.Baggage{},propagation.TraceContext{})
otel.SetTextMapPropagator(propagator)

这里面做的事情很简单,就是将我们程序中自己创建的trace provider和meter provider设置到官方包中,也就是替换了官方包中的全局变量。接下来,我们想使用provider时,就统一调用官方包即可,不再需要引用本地的变量

并不是所有的场景都适合把变量存放到统一的package下,可以延伸思考下~

举个例子,github.com/spf13/viper配置库只支持全局单个对象Viper,而我们程序中要创建多个对象,这时就不适用。

5. 创建Metric Instruments

// 设置关键属性
lemonsKey := attribute.Key("ex.com/lemons")
anotherKey := attribute.Key("ex.com/another")

commonAttributes := []attribute.KeyValue{lemonsKey.Int(10), attribute.String("A", "1"), attribute.String("B", "2"), attribute.String("C", "3")}

// 创建一个Meter实例
meter := global.Meter("ex.com/basic")

// 异步的Observer:通过函数回调
observerCallback := func(_ context.Context, result metric.Float64ObserverResult) {
  result.Observe(1, commonAttributes...)
}
_ = metric.Must(meter).NewFloat64ValueObserver("ex.com.one", observerCallback,metric.WithDescription("A ValueObserver set to 1.0"))

// 同步的Recorder:创建一个变量,按需使用
valueRecorder := metric.Must(meter).NewFloat64ValueRecorder("ex.com.two")
boundRecorder := valueRecorder.Bind(commonAttributes...)
defer boundRecorder.Unbind()

6. 综合示例

// 创建一个Tracer
tracer := otel.Tracer("ex.com/basic")

// 创建了一个包含2个member的baggage,并结合到Go里的context
foo, _ := baggage.NewMember("ex.com.foo", "foo1")
bar, _ := baggage.NewMember("ex.com.bar", "bar1")
bag, _ := baggage.New(foo, bar)
ctx = baggage.ContextWithBaggage(ctx, bag)

// 以下为一个具体调用的示例,多层嵌套
func(ctx context.Context) {
  // 根据传入的ctx,创建一个span
  var span trace.Span
  ctx, span = tracer.Start(ctx, "operation")
  defer span.End()

  span.AddEvent("Nice operation!", trace.WithAttributes(attribute.Int("bogons", 100)))
  span.SetAttributes(anotherKey.String("yes"))

  meter.RecordBatch(
    ctx,
    commonAttributes,
    valueRecorder.Measurement(2.0),
  )

  func(ctx context.Context) {
    // 根据传入的ctx,创建一个子span
    var span trace.Span
    ctx, span = tracer.Start(ctx, "Sub operation...")
    defer span.End()

    span.SetAttributes(lemonsKey.String("five"))
    span.AddEvent("Sub span event")
    boundRecorder.Record(ctx, 1.3)
  }(ctx)
}(ctx)

链接

总结

从现状来看,OpenTelemetry仍处于初期阶段,使用起来并不那么方便。我们应该把重点放在标准上:

从官方文档 - https: //opentelemetry.io/docs/go/exporting_data/ 中可以看出,OpenTelemetry有标准的OTLP Exporter,但目前这块更多的是一个标准,而不是一个具体实践。

针对当前已落地的技术,重要参考就是Jaeger和Prometheus。

目录
相关文章
|
SQL 存储 监控
深入可观测底层:OpenTelemetry 链路传递核心原理
本文会系统讲解链路传递一些基本概念,同时结合案例讲解链路传递的过程。
3820 1
深入可观测底层:OpenTelemetry 链路传递核心原理
|
存储 Web App开发 JSON
OpenTelemetry Log规范解读
本文主要介绍OpenTelemetry Log规范,这一规范来自于Google、Microsoft、AWS、Splunk、DataDog、ES、Fluntd等众多优秀的公司和项目成员,其中有很多点是我们在平时开发、运维需要关注的知识和经验,值得大家一观。
7864 0
OpenTelemetry Log规范解读
|
存储 Prometheus Kubernetes
OpenTelemetry 简析
OpenTelemetry 是 CNCF 的一个可观测性项目,旨在提供可观测性领域的标准化方案,解决观测数据的数据模型、采集、处理、导出等的标准化问题,提供与三方 vendor 无关的服务。 2021.02.10,OpenTelemetry 的 tracing spec 达到 1.0 版本 (link),基于这个里程碑,笔者对 OpenTelemetry 进行了探索,判断在可观测性领域带来的价值和发展前景。 下面给出笔者对 OpenTelemetry 的理解,抛砖引玉。由于笔者能力有限,理解不当的地方请大家指正。
OpenTelemetry 简析
|
5月前
|
监控 Cloud Native Java
阿里云可观测联合 Datadog 发布 OpenTelemetry Go 自动插桩工具
阿里云联合社区推出 OpenTelemetry Go 编译时自动插桩方案,基于 -toolexec 实现零代码修改的链路追踪与监控,支持 HTTP、gRPC 等常用框架,低开销、高兼容,助力 Go 应用无缝接入可观测体系。
416 2
|
6月前
|
运维 Prometheus 数据可视化
如何一键接入opentelemetry项目,实现可观测分析
本文揭秘如何通过Databuff实现OpenTelemetry的无缝接管,无需改造现有Collector,10分钟完成部署,实现服务与资源间的因果可观测性,呈现云网空间地图,助力运维智能化。
|
7月前
|
运维 Prometheus 监控
监控体系大一统:OpenTelemetry 就是运维人的“鸿蒙”
监控体系大一统:OpenTelemetry 就是运维人的“鸿蒙”
859 11
|
JSON 监控 Java
日志与追踪的完美融合:OpenTelemetry MDC 实践指南
日志与追踪的完美融合:OpenTelemetry MDC 实践指南
1034 24
|
存储 Prometheus 监控
当 OpenTelemetry 遇上阿里云 Prometheus
本文以构建系统可观测为切入点,对比 OpenTelemetry 与 Prometheus 的相同与差异,重点介绍如何将应用的 OpenTelemetry 指标接入 Prometheus 及背后原理以及介绍阿里云可观测监控 Prometheus 版拥抱 OpenTelemetry及相关落地实践案例。
94678 104
|
Prometheus Cloud Native Java
OpenTelemetry: 经得起考验的工具
OpenTelemetry: 经得起考验的工具
2849 2
|
存储 Prometheus Cloud Native
分布式系统架构6:链路追踪
本文深入探讨了分布式系统中的链路追踪理论,涵盖追踪与跨度的概念、追踪系统的模块划分及数据收集的三种方式。链路追踪旨在解决复杂分布式系统中请求流转路径不清晰的问题,帮助快速定位故障和性能瓶颈。文中介绍了基于日志、服务探针和边车代理的数据收集方法,并简述了OpenTracing、OpenCensus和OpenTelemetry等链路追踪协议的发展历程及其特点。通过理解这些概念,可以更好地掌握开源链路追踪框架的使用。
1616 41