Инициализация OTEL в go

Как можно раньше в коде следует выполнить блок инициализации телеметрии.

Базовая инициализация

package main
 
import (
	"context"
	"fmt"
	"log"
	"time"
 
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
	"go.opentelemetry.io/otel/sdk/resource"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)
 
const (
	TRACER_NAME = "demo_service"
)
 
func InstallExportPipeline() (func(context.Context) error, error) {
	traceClient := otlptracegrpc.NewClient(
		otlptracegrpc.WithInsecure(),
		otlptracegrpc.WithEndpoint("0.0.0.0:4317"),
	)
 
	sctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()
 
	traceExp, err := otlptrace.New(sctx, traceClient)
	if err != nil {
		log.Fatal(err)
	}
 
	if err != nil {
		return nil, fmt.Errorf("creating stdout exporter: %w", err)
	}
 
	res, err := resource.New(context.Background(),
		resource.WithFromEnv(),
		resource.WithProcess(),
		resource.WithTelemetrySDK(),
		resource.WithHost(),
		resource.WithAttributes(
			semconv.ServiceNameKey.String(TRACER_NAME),
		),
	)
	if err != nil {
		log.Fatal(err)
	}
 
	tracerProvider := sdktrace.NewTracerProvider(
		sdktrace.WithBatcher(traceExp),
		sdktrace.WithResource(res),
	)
	otel.SetTracerProvider(tracerProvider)
 
	return tracerProvider.Shutdown, nil
}

Использование в основном коде

const (
        TRACER_NAME = "demo_service"
)
 
var tracer = otel.Tracer(TRACER_NAME)
 
func main() {
	ctx := context.Background()
	shutdown, err := InstallExportPipeline()
	if err != nil {
		log.Fatal(err)
	}

Ну а далее от этого глобального tracer’а уже можно создавать спаны и жонглировать ими через контекст:

newCtx, span := tracer.Start(r.Context(), "/")
defer span.End()