Preface
OpenTelemetry 是一个可观测性工具,通过标准化的 API 和 SDK,提供了跨语言、跨平台的分布式追踪、日志和指标收集和分析能力。OpenTelemetry 的目标是让开发者更容易地维护和监测他们的应用程序。
本文将介绍 OpenTelemetry 的一些基本概念和用法,帮助读者快速入门。
1. 安装 OpenTelemetry
首先,需要安装 OpenTelemetry 的 SDK。这里以 Golang 为例,介绍如何安装 OpenTelemetry Go SDK。
1
|
go get go.opentelemetry.io/otel
|
通过运行上述命令,可以下载并安装 OpenTelemetry Go SDK。
2. 配置 OpenTelemetry Collector
OpenTelemetry Collector 是一个数据收集器,它可以收集不同类型的数据并发送到指定的目的地。在使用 OpenTelemetry 进行分布式追踪时,通常需要将追踪数据发送到 Zipkin 或 Jaeger 等追踪系统中。
安装并配置 OpenTelemetry Collector 的详细步骤可以参考官方文档 Installation。
3. 创建 Span
在 Go 语言中,可以通过调用 OpenTelemetry SDK 的 TracerProvider 对象来创建 Span。Span 表示从应用程序中发出的命名工作单元,比如一个函数调用、一次网络请求等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package main
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"
)
func main() {
// 初始化 TracerProvider
provider := otel.GetTracerProvider()
// 创建 Tracer 对象
tracer := provider.Tracer("example-tracer")
// 创建 Span
ctx, span := tracer.Start(context.Background(), "example-span")
defer span.End()
// 执行业务逻辑
// ...
// 可以通过 Span 对象设置一些属性和事件
span.SetAttribute("example-attribute", "hello world!")
span.AddEvent("example-event")
}
|
通过调用 TracerProvider
对象的 Tracer
方法创建一个 Tracer
对象,然后使用 Tracer
对象的 Start
方法创建一个 Span
对象,并设置 Span
的名称。
最后,在使用完 Span
对象后需要通过 End
方法结束 Span
对象。
4. 追踪信息传递
OpenTelemetry 支持在分布式系统中传递追踪信息,以便完整地跟踪分布式系统中的请求。
在 Go 语言中,可以通过使用 OpenTelemetry 的 otelpropagation
包,将追踪信息添加到请求上下文中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
// 在处理 HTTP 请求时传递追踪信息
package main
import (
"net/http"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
)
func main() {
// 初始化 TracerProvider
provider := otel.GetTracerProvider()
// 创建 Tracer 对象
tracer := provider.Tracer("example-tracer")
// 处理 HTTP 请求
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// 从请求中获取追踪信息
ctx := propagation.ExtractHTTP(r.Context(), propagation.HeaderCarrier(r.Header))
// 创建 Span
_, span := tracer.Start(ctx, "example-span")
defer span.End()
// 执行业务逻辑
// ...
// 可以通过 Span 对象设置一些属性和事件
span.SetAttribute("example-attribute", "hello world!")
span.AddEvent("example-event")
})
// 启动 HTTP 服务
http.ListenAndServe(":8080", nil)
}
|
在处理 HTTP 请求时,可以通过调用 propagation.ExtractHTTP
方法,从 HTTP 请求中获取
4.1 业务自定义 span
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import (
"context"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)
// WithSpan create span if sampled
func WithSpan(ctx context.Context, spanName string, key string, val interface{}) {
if trace.SpanContextFromContext(ctx).IsSampled() {
_, span := telemetry.Start(ctx, spanName)
defer span.End()
span.AddEvent("custom", trace.WithAttributes(
attribute.Key(key).String(traces.DefaulMsgMarshaler(val)),
))
// 增加自定义 tags
span.SetAttributes("自定义Key", "自定义Value")
span.SetStatus(codes.Error, "timeout")
}
}
|
4.2 在当前的 span 上追加 event
1
2
3
4
5
6
7
8
9
|
// AddEvent add event
func AddEvent(ctx context.Context, req interface{}, rsp interface{}) {
if span := trace.SpanFromContext(ctx); span.SpanContext().IsSampled() {
span.AddEvent("msg", trace.WithAttributes(
attribute.Key("req").String(traces.DefaulMsgMarshaler(req)),
attribute.Key("rsp").String(traces.DefaulMsgMarshaler(rsp)),
))
}
}
|