Search documentation

Find a page in the Andurel docs.

Telemetry

Generated applications include structured logging, metrics, traces, and HTTP instrumentation through OpenTelemetry via github.com/mbvlabs/andurel/pkg/telemetry.

Process-local wiring

Both cmd/app and cmd/queue include the application-owned telemetry module. Fx starts and stops exporters with each process. Composition roots call telemetry.New with service identity and With* options from config.Telemetry. Do not call otel.SetTracerProvider or slog.SetDefault; use the injected *telemetry.Telemetry and package helpers that read it from context.

1tel, err := telemetry.New(ctx, cfg.ServiceName, cfg.ServiceVersion,
2    telemetry.WithConsole(),
3    telemetry.WithLogLevel(slog.LevelInfo),
4    telemetry.WithOTLPTraces(cfg.OTLPTracesEndpoint, cfg.OTLPHeaders),
5    telemetry.WithOTLPMetrics(cfg.OTLPMetricsEndpoint, cfg.OTLPHeaders),
6    telemetry.WithOTLPLogs(cfg.OTLPLogsEndpoint, cfg.OTLPHeaders),
7    telemetry.WithTraceSampleRate(cfg.TraceSampleRate),
8    telemetry.WithBatchConfig(cfg.BatchSize, cfg.BatchTimeout, cfg.QueueSize),
9)

Attach the provider to request or job contexts so helpers resolve it:

1ctx = tel.Context(ctx)

Export configuration

1TELEMETRY_SERVICE_NAME=orbit
2TELEMETRY_SERVICE_VERSION=1.0.0
3OTLP_LOGS_ENDPOINT=
4OTLP_METRICS_ENDPOINT=https://collector.example.com
5OTLP_TRACES_ENDPOINT=https://collector.example.com
6OTLP_HEADERS=Authorization=Bearer token
7TRACE_SAMPLE_RATE=1.0
8TELEMETRY_BATCH_SIZE=512
9TELEMETRY_BATCH_TIMEOUT_MS=5000

The generated provider validates service identity, batch settings, and the trace sample rate (0 through 1) before exporters start. Empty OTLP endpoints disable that signal export. See Configuration.

Spans in controllers and services

Controllers start a child span from Echo and write it back onto the request:

 1func (s Sessions) Create(etx *echo.Context) error {
 2    ctx, span := telemetry.From(etx, "sessions.create")
 3    defer span.End()
 4
 5    user, err := s.identity.AuthenticateUser(ctx, data)
 6    if err != nil {
 7        telemetry.Error(ctx, "failed to authenticate user", "error", err)
 8        return err
 9    }
10
11    telemetry.Set(ctx, "user.id", user.ID.String())
12    telemetry.Info(ctx, "session created", "user.id", user.ID.String())
13    return nil
14}

Services use Start with slog-shaped attributes:

1ctx, span := telemetry.Start(ctx, "products.archive", "product.id", id)
2defer span.End()
3
4if err := p.repo.Archive(ctx, id); err != nil {
5    return telemetry.Fail(ctx, err)
6}
Helper Role
From(etx, name) Span from *echo.Context; updates request context
Start(ctx, name, key, val, ...) Span with attributes
Set(ctx, key, val, ...) Attributes on the current span
Fail(ctx, err) Record error + error status; returns err
Debug / Info / Warn / Error Log through the telemetry pipeline and add a span event

Prefer stable route templates and identifiers over raw URLs or unbounded user input. Never put passwords, tokens, complete email bodies, or secrets into attributes. pgx instrumentation follows DB_OPEN_TELEMETRY when enabled on the storage pool.