技术阅读摘要 - 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。

目录
相关文章
|
7天前
|
机器学习/深度学习 人工智能 搜索推荐
PaSa:字节跳动开源学术论文检索智能体,自动调用搜索引擎、浏览相关论文并追踪引文网络
PaSa 是字节跳动推出的基于强化学习的学术论文检索智能体,能够自动调用搜索引擎、阅读论文并追踪引文网络,帮助用户快速获取精准的学术文献。
84 14
可控细节的长文档摘要,探索开源LLM工具与实践
本文通过将文档分为几部分来解决这个问题,然后分段生成摘要。在对大语言模型进行多次查询后,可以重建完整的摘要。通过控制文本块的数量及其大小,我们最终可以控制输出中的细节级别。
|
6月前
|
人工智能 监控 数据库
LLM 应用可观测性:从 Trace 视角展开的探索与实践之旅
基于大语言模型的应用在性能、成本、效果等方面存在一系列实际痛点,本文通过分析 LLM 应用模式以及关注点差异来阐明可观测技术挑战,近期阿里云可观测推出了面向 LLM 应用的可观测解决方案以及最佳实践,一起来了解下吧。
18675 28
LLM 应用可观测性:从 Trace 视角展开的探索与实践之旅
|
5月前
|
人工智能 自然语言处理 文字识别
秒懂全文:盘点13个各具特色的AI智能阅读助手工具
在当今信息爆炸的时代,AI阅读工具正在革新我们的阅读方式,成为了提高效率、优化阅读体验的关键。这类AI阅读辅助工具,只需要上传文件或者输入链接,便可以直接以聊天对话的形式进行一键总结和智能问答,满足用户AI PDF 阅读、AI文档问答分析、AI音视频总结等多种实用需求,高效提炼信息要点精华,建立属于自己的AI知识管理和信息管理工作流。对此,根据阅读场景,精选了 13 个具有代表性、各具特点的高质量 AI 阅读助手助理。 具体如何选择,见文末总结。
601 1
秒懂全文:盘点13个各具特色的AI智能阅读助手工具
|
8月前
|
存储 机器学习/深度学习 人工智能
【LangChain系列】第八篇:文档问答简介及实践
【5月更文挑战第22天】本文探讨了如何使用大型语言模型(LLM)进行文档问答,通过结合LLM与外部数据源提高灵活性。 LangChain库被介绍为简化这一过程的工具,它涵盖了嵌入、向量存储和不同类型的检索问答链,如Stuff、Map-reduce、Refine和Map-rerank。文章通过示例展示了如何使用LLM从CSV文件中提取信息并以Markdown格式展示
361 2
|
7月前
|
文字识别 算法 API
视觉智能开放平台产品使用合集之如何使用视频拆条功能
视觉智能开放平台是指提供一系列基于视觉识别技术的API和服务的平台,这些服务通常包括图像识别、人脸识别、物体检测、文字识别、场景理解等。企业或开发者可以通过调用这些API,快速将视觉智能功能集成到自己的应用或服务中,而无需从零开始研发相关算法和技术。以下是一些常见的视觉智能开放平台产品及其应用场景的概览。
|
8月前
|
Java 程序员 数据安全/隐私保护
二、Java性能概述
二、Java性能概述
70 3
|
8月前
|
数据可视化 前端开发 数据库
CodeWave智能开发平台--02--目标:文档快速阅读--02新手入门
CodeWave智能开发平台--02--目标:文档快速阅读--02新手入门
|
并行计算 前端开发 JavaScript
前端3D技术概述(1)
前端3D技术概述
2103 2
|
机器学习/深度学习 前端开发 图形学
前端3D技术概述(2)
前端3D技术概述
192 0