go 使用opentelemetry来实现简单链路追踪
package main
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/sdk/resource"
tracesdk "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
"log"
"time"
)
const (
service = "trace-demo"
environment = "production"
id = 1
)
// tracerProvider returns an OpenTelemetry TracerProvider configured to use
// the Jaeger exporter that will send spans to the provided url. The returned
// TracerProvider will also use a Resource configured with all the information
// about the application.
func tracerProvider(url string) (*tracesdk.TracerProvider, error) {
// 创建 Jaeger 导出器
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
if err != nil {
return nil, err
}
tp := tracesdk.NewTracerProvider(
// Always be sure to batch in production.
tracesdk.WithBatcher(exp),
// Record information about this application in a Resource.
tracesdk.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String(service),
attribute.String("environment", environment), // 不清楚有啥用 去掉也没问题
attribute.Int64("ID", id), // 不清楚有啥用 去掉也没问题
)),
)
return tp, nil
}
func main() {
// 用来创建 Jaeger 导出器
tp, err := tracerProvider("http://192.168.16.196:14268/api/traces") // ip地址记得要换
if err != nil {
log.Fatal(err)
}
// 注册我们的 TracerProvider 为全局的 所以任何导入
// 将来的 instrumentation 将默认使用它
otel.SetTracerProvider(tp)
// 创建 子 context 用来传递给 子协程 用于 通信 底层实现的是 channel cancel 用于关闭用
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 当应用程序退出时,干净地关闭和刷新遥测
defer func(ctx context.Context) {
// 在关闭应用程序时,不要使其挂起
ctx, cancel := context.WithTimeout(ctx, time.Second*5) // 从创建后 超过5秒后 关闭
defer cancel()
if err := tp.Shutdown(ctx); err != nil { // Shutdown按注册span处理器的顺序关闭它们
log.Fatal(err)
}
}(ctx)
tr := tp.Tracer("component-main") // 创建链路追踪
//ctx, span := tr.Start(context.Background(), "foo")
ctx, span := tr.Start(ctx, "foo") // 开启链路追踪 修改了 他的源码 如果这里传递 全新的context 上面的代码是不是就没有用了?
defer span.End()
bar(ctx)
}
func bar(ctx context.Context) {
// Use the global TracerProvider.
tr := otel.Tracer("component-bar")
_, span := tr.Start(ctx, "bar")
span.SetAttributes(attribute.Key("testset").String("value"))
defer span.End()
// Do bar...
}