package telemetry import ( "context" "log/slog" "os" "git.kmsign.ru/royalcat/tstor/pkg/rlog" "github.com/agoda-com/opentelemetry-go/otelslog" "github.com/agoda-com/opentelemetry-logs-go/exporters/otlp/otlplogs" "github.com/agoda-com/opentelemetry-logs-go/exporters/otlp/otlplogs/otlplogshttp" logsdk "github.com/agoda-com/opentelemetry-logs-go/sdk/logs" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/exporters/prometheus" "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.24.0" ) type Client struct { log *slog.Logger tracerProvider *trace.TracerProvider metricProvider *metric.MeterProvider loggerProvider *logsdk.LoggerProvider } func (client *Client) Shutdown(ctx context.Context) { log := rlog.FunctionLog(client.log, "Shutdown") if client.metricProvider == nil { err := client.metricProvider.Shutdown(ctx) if err != nil { log.Error("error shutting down metric provider", rlog.Err(err)) } } if client.tracerProvider == nil { err := client.tracerProvider.Shutdown(ctx) if err != nil { log.Error("error shutting down tracer provider", rlog.Err(err)) } } if client.loggerProvider == nil { err := client.loggerProvider.Shutdown(ctx) if err != nil { log.Error("error shutting down logger provider", rlog.Err(err)) } } } const appName = "tstor" func Setup(ctx context.Context, endpoint string) (*Client, error) { log := rlog.ComponentLog("telemetry") client := &Client{ log: log, } otel.SetErrorHandler(otel.ErrorHandlerFunc(func(cause error) { log.Error("otel error", rlog.Err(cause)) })) hostName, _ := os.Hostname() r, err := resource.Merge( resource.Default(), resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceName(appName), semconv.HostName(hostName), ), ) if err != nil { return nil, err } metricExporter, err := prometheus.New(prometheus.WithNamespace(appName)) if err != nil { return nil, err } client.metricProvider = metric.NewMeterProvider( metric.WithReader(metricExporter), metric.WithResource(r), ) otel.SetMeterProvider(client.metricProvider) log.Info("prometheus metrics provider initialized") traceExporter, err := otlptracehttp.New(ctx, otlptracehttp.WithEndpoint(endpoint), otlptracehttp.WithRetry(otlptracehttp.RetryConfig{ Enabled: false, }), ) if err != nil { return nil, err } client.tracerProvider = trace.NewTracerProvider( trace.WithBatcher(traceExporter), trace.WithResource(r), ) otel.SetTracerProvider(client.tracerProvider) log.Info("otel tracing provider initialized") logExporter, err := otlplogs.NewExporter(ctx, otlplogs.WithClient( otlplogshttp.NewClient(otlplogshttp.WithEndpoint(endpoint)), ), ) if err != nil { return nil, err } client.loggerProvider = logsdk.NewLoggerProvider( logsdk.WithBatcher(logExporter), logsdk.WithResource(r), ) rlog.AddHandler(otelslog.NewOtelHandler(client.loggerProvider, &otelslog.HandlerOptions{ Level: slog.LevelDebug, }), ) client.log = slog.Default() return client, nil }