# einherjar/telemetry [![version](https://img.shields.io/badge/version-v1.0.0-5C4EE5?style=flat-square)](https://code.nochebuena.dev/einherjar/telemetry) [![license](https://img.shields.io/badge/license-AGPL--3.0-22863A?style=flat-square)](LICENSE) [![go](https://img.shields.io/badge/Go-1.26+-00ADD8?style=flat-square&logo=go&logoColor=white)](https://go.dev) > Huginn and Muninn fly each day over the world. They see everything. They report back. `code.nochebuena.dev/einherjar/telemetry` is the OpenTelemetry bootstrap component of the Einherjar framework. It initializes traces, metrics, and structured logs via OTLP over gRPC — vendor-neutral, compatible with Grafana, Jaeger, Tempo, Datadog, and Honeycomb. A console mode is available for local development without a collector. Telemetry is **not** a `lifecycle.Component`. It must be initialized before the launcher and shut down after all components stop — the returned shutdown function handles this cleanly with a `defer`. --- ## Usage ### Production (OTLP/gRPC) ```go import ( "code.nochebuena.dev/einherjar/telemetry" "code.nochebuena.dev/einherjar/core/launcher" "code.nochebuena.dev/einherjar/core/logz" ) ctx := context.Background() logger := logz.New(logz.Config{JSON: true}) // Initialize telemetry BEFORE the launcher. // Defer the shutdown BEFORE launcher.Run() so it fires after the launcher stops. shutdown, err := telemetry.New(ctx, telemetry.DefaultConfig()) if err != nil { logger.Error("telemetry init failed", err) os.Exit(1) } defer shutdown(ctx) lc := launcher.New(logger) lc.Append(db, cache, srv) lc.Run() ``` ### Development (console / structured log output) No collector required. Spans and metrics are emitted to the configured `logging.Logger`. ```go shutdown, err := telemetry.NewConsole(ctx, logger, telemetry.DefaultConsoleConfig()) if err != nil { logger.Error("telemetry init failed", err) os.Exit(1) } defer shutdown(ctx) ``` --- ## Environment variables ### Production (`telemetry.New`) | Variable | Required | Default | Description | |---|---|---|---| | `EINHERJAR_OTEL_SERVICE_NAME` | Yes | — | Service name reported to the collector | | `EINHERJAR_OTEL_EXPORTER_ENDPOINT` | Yes | — | OTLP gRPC endpoint (e.g. `otel-collector:4317`) | | `EINHERJAR_OTEL_SERVICE_VERSION` | No | `unknown` | Service version tag | | `EINHERJAR_OTEL_ENVIRONMENT` | No | `development` | Deployment environment tag | | `EINHERJAR_OTEL_EXPORTER_INSECURE` | No | `false` | Disable TLS for the exporter (dev/local) | ### Development (`telemetry.NewConsole`) | Variable | Required | Default | Description | |---|---|---|---| | `EINHERJAR_OTEL_SERVICE_NAME` | Yes | — | Service name | | `EINHERJAR_OTEL_SERVICE_VERSION` | No | `unknown` | Service version tag | | `EINHERJAR_OTEL_ENVIRONMENT` | No | `development` | Deployment environment tag | --- ## Dependency graph ``` contracts (zero dependencies) ↑ core ↑ telemetry (contracts, core, otel SDK + OTLP exporters) ↑ your app (initialized before launcher.Run) ``` --- ## Verification ```bash cd telemetry/ go build ./... go vet ./... go test ./... gofmt -l . ``` --- > *Odin gave an eye for wisdom.* > *Observability is the eye that watches the living system.*