2025-04-13 11:45:37 +08:00

85 lines
2.3 KiB
Go

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.WithProcess(),
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
}