Quick start
Export is off by default. SetOTEL_ENABLED=true and point the exporter at
your collector:
opentelemetry enabled at startup together with the selected
exporters. Exporters are asynchronous: the gateway starts even when the
collector is down and retries in the background.
Without
OTEL_EXPORTER_OTLP_ENDPOINT the SDK sends to
http://localhost:4318 (http/protobuf) or localhost:4317 (grpc).Configuration
OTEL_ENABLED is the only GoModel-specific switch. Everything else follows
the standard
OpenTelemetry environment variables,
so GoModel is configured exactly like any other instrumented service. The
common settings are also available under opentelemetry: in
config.yaml; a variable set in the environment
wins over the YAML value.
A typical production setup:
What is exported
HTTP server spans and metrics
Every request gets aSERVER span named after its route (for example
POST /v1/chat/completions) with the standard http.request.method,
http.route, http.response.status_code, and url.scheme attributes, plus the
http.server.request.duration histogram and the request and response body size
histograms.
Trace context from the caller is honored, so a gateway span appears as a child
of the calling application’s span whenever the client sends traceparent (or
whichever headers OTEL_PROPAGATORS selects).
/health, /health/ready, the Prometheus endpoint (METRICS_ENDPOINT), and
/debug/pprof are excluded: they are polled, and would otherwise dominate the
trace volume.
Provider call spans and GenAI metrics
Each logical call to a model provider is instrumented with:
Metrics are histograms in seconds, carrying the same attributes:
A buffered call produces a
CLIENT span named <operation> <model>, such as
chat gpt-5, nested under the HTTP server span. Retries and failovers to
another provider are separate calls and therefore separate spans, so a request
that failed over shows exactly which provider failed and which one answered.
Streaming calls do not get a client span: the gateway can only observe when
the stream was established, not when the model finished, and a span ending at
the headers would misreport latency. The enclosing HTTP server span still
covers the full stream lifetime as seen by the client. A stream that fails to
establish, or ends before delivering its first chunk, gets a retrospective
failure span, so errors are always traced.
Privacy
The exporter is designed so that telemetry can go to a third-party backend without leaking what flows through the gateway:- Request and response bodies, prompts, completions, and tool calls are never attached to spans or metrics.
- Credentials and upstream error messages are never exported; failures carry only a status code or an error class.
client.address,network.peer.*,server.address,server.port, anduser_agent.originalare stripped from HTTP spans, and host-derived dimensions are excluded from HTTP metrics so a client cannot inflate metric cardinality through theHostheader.
Reloading
gomodel --reload (SIGHUP) rebuilds the OpenTelemetry pipeline with the
current environment, so exporter, sampling, and propagation changes apply
without a restart. The previous pipeline is flushed before it is discarded.
Local collector example
A minimaldocker-compose.yml that shows traces in Jaeger:
http://localhost:16686.