Files
cms-server/tracer/otel_tracer.go
Asai Neko 37f06fe98a
All checks were successful
Server Check Build (NixCN CMS) TeamCity build finished
Add RetryConfig for OtelTracer
Signed-off-by: Asai Neko <sugar@sne.moe>
2026-02-19 12:00:45 +08:00

116 lines
3.0 KiB
Go

package tracer
import (
"context"
"log/slog"
"time"
"github.com/spf13/viper"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/log/global"
"go.opentelemetry.io/otel/propagation"
sdklog "go.opentelemetry.io/otel/sdk/log"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
)
func Init(ctx context.Context) func(context.Context) error {
endpoint := viper.GetString("tracer.otel_controller_endpoint")
if endpoint == "" {
endpoint = "localhost:4317"
}
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceNameKey.String(viper.GetString("server.service_name")),
),
)
if err != nil {
slog.Error("[OTEL] Failed to create resource", "err", err)
}
retryConfig := otlptracegrpc.RetryConfig{
Enabled: true,
InitialInterval: 1 * time.Second,
MaxInterval: 10 * time.Second,
}
// Trace Exporter
traceExporter, err := otlptracegrpc.New(ctx,
otlptracegrpc.WithEndpoint(endpoint),
otlptracegrpc.WithInsecure(),
otlptracegrpc.WithRetry(retryConfig),
)
if err != nil {
slog.Error("[OTEL] Failed to create trace exporter", "err", err)
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(traceExporter),
sdktrace.WithResource(res),
sdktrace.WithSampler(sdktrace.AlwaysSample()),
)
otel.SetTracerProvider(tp)
// Metric Exporter
metricExporter, err := otlpmetricgrpc.New(ctx,
otlpmetricgrpc.WithEndpoint(endpoint),
otlpmetricgrpc.WithInsecure(),
otlpmetricgrpc.WithRetry(otlpmetricgrpc.RetryConfig(retryConfig)),
)
if err != nil {
slog.Error("[OTEL] Failed to create metric exporter", "err", err)
}
mp := sdkmetric.NewMeterProvider(
sdkmetric.WithResource(res),
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(metricExporter,
sdkmetric.WithInterval(5*time.Second))),
)
otel.SetMeterProvider(mp)
// Log Exporter
logExporter, err := otlploggrpc.New(ctx,
otlploggrpc.WithEndpoint(endpoint),
otlploggrpc.WithInsecure(),
otlploggrpc.WithRetry(otlploggrpc.RetryConfig(retryConfig)),
)
if err != nil {
slog.Error("[OTEL] Failed to create log exporter", "err", err)
}
lp := sdklog.NewLoggerProvider(
sdklog.WithResource(res),
sdklog.WithProcessor(sdklog.NewBatchProcessor(logExporter)),
)
global.SetLoggerProvider(lp)
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
propagation.TraceContext{},
propagation.Baggage{},
))
return func(shutCtx context.Context) error {
var errs []error
if err := tp.Shutdown(shutCtx); err != nil {
errs = append(errs, err)
}
if err := mp.Shutdown(shutCtx); err != nil {
errs = append(errs, err)
}
if err := lp.Shutdown(shutCtx); err != nil {
errs = append(errs, err)
}
if len(errs) > 0 {
return errs[0]
}
return nil
}
}