package telemetry import ( "context" "errors" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlptrace" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.30.0" ) func InitTelemetry(ctx context.Context) (shutdown func(context.Context) error, err error) { var shutdownFuncs []func(context.Context) error // shutdown 会调用通过 shutdownFuncs 注册的清理函数。 // 调用产生的错误会被合并。 // 每个注册的清理函数将被调用一次。 shutdown = func(ctx context.Context) error { var err error for _, fn := range shutdownFuncs { err = errors.Join(err, fn(ctx)) } shutdownFuncs = nil return err } // handleErr 调用 shutdown 进行清理,并确保返回所有错误信息。 handleErr := func(inErr error) { err = errors.Join(inErr, shutdown(ctx)) } // 设置传播器 prop := newPropagator() otel.SetTextMapPropagator(prop) // 设置 trace provider. tracerProvider, err := newJaegerTraceProvider(ctx) if err != nil { handleErr(err) return } shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) otel.SetTracerProvider(tracerProvider) return } func newPropagator() propagation.TextMapPropagator { return propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{}, ) } func newJaegerTraceProvider(ctx context.Context) (*trace.TracerProvider, error) { // 创建一个使用 HTTP 协议连接本机Jaeger的 Exporter res, err := resource.New(ctx, resource.WithFromEnv(), resource.WithTelemetrySDK(), resource.WithHost(), resource.WithAttributes( // 在可观测链路 OpenTelemetry 版后端显示的服务名称。 semconv.ServiceNameKey.String("VPT"), ), ) if err != nil { return nil, err } traceClientHttp := otlptracehttp.NewClient( otlptracehttp.WithEndpointURL("https://oltp.jerryyan.top/v1/traces")) otlptracehttp.WithCompression(1) traceExp, err := otlptrace.New(ctx, traceClientHttp) bsp := trace.NewBatchSpanProcessor(traceExp) tracerProvider := trace.NewTracerProvider( trace.WithSampler(trace.AlwaysSample()), trace.WithResource(res), trace.WithSpanProcessor(bsp), ) return tracerProvider, nil }