OpenTelemetry Environment Variables Reference

Environment variables configure the OpenTelemetry SDK without touching code. Every SDK reads the same names, so the same deployment manifest works across a polyglot fleet, and moving from a local Collector to a hosted backend is a configuration change rather than a rebuild.

Code-level configuration overrides environment variables. If a setting appears to be ignored, something in the code is setting it explicitly.

Quick start

Four variables cover most deployments:

shell
export OTEL_SERVICE_NAME=checkout-api
export OTEL_RESOURCE_ATTRIBUTES=service.version=1.2.3,deployment.environment.name=production
export OTEL_EXPORTER_OTLP_ENDPOINT=https://api.uptrace.dev:4317
export OTEL_EXPORTER_OTLP_HEADERS=uptrace-dsn=https://<secret>@api.uptrace.dev?grpc=4317

Service identity

VariableDefaultDescription
OTEL_SERVICE_NAMEunknown_serviceLogical service name. The primary key for grouping telemetry
OTEL_RESOURCE_ATTRIBUTESComma-separated key=value resource attributes

OTEL_SERVICE_NAME takes precedence over a service.name set inside OTEL_RESOURCE_ATTRIBUTES.

Set the name to something stable across deploys. Anything containing a pod name, a container id, or a build number splits one service into many in every dashboard.

shell
export OTEL_RESOURCE_ATTRIBUTES=service.version=1.2.3,deployment.environment.name=production,service.namespace=shop

Use semantic conventions for the keys. Note deployment.environment.name — the older deployment.environment was renamed.

Exporter

VariableDefaultDescription
OTEL_EXPORTER_OTLP_ENDPOINThttp://localhost:4317 (gRPC), http://localhost:4318 (HTTP)Where to send telemetry
OTEL_EXPORTER_OTLP_PROTOCOLhttp/protobufgrpc, http/protobuf, or http/json
OTEL_EXPORTER_OTLP_HEADERSkey1=value1,key2=value2. Usually authentication
OTEL_EXPORTER_OTLP_TIMEOUT10000Milliseconds to wait for each batch export
OTEL_EXPORTER_OTLP_COMPRESSIONnone or gzip

The default protocol in the specification is http/protobuf, but individual SDKs have defaulted to grpc at various points. Set it explicitly rather than relying on the default.

The endpoint path trap

The generic and signal-specific endpoint variables behave differently over HTTP, and this catches people regularly:

VariableBehavior over HTTP
OTEL_EXPORTER_OTLP_ENDPOINTThe signal path is appendedv1/traces, v1/metrics, v1/logs
OTEL_EXPORTER_OTLP_TRACES_ENDPOINTUsed as-is. You must include /v1/traces yourself
shell
# Generic: the SDK sends to https://collector.example.com/v1/traces
export OTEL_EXPORTER_OTLP_ENDPOINT=https://collector.example.com

# Signal-specific: the full path is required
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://collector.example.com/v1/traces

Setting the signal-specific variable to a bare host produces exports to / and a 404 from the receiver.

Per-signal overrides exist for every setting: OTEL_EXPORTER_OTLP_TRACES_HEADERS, OTEL_EXPORTER_OTLP_METRICS_TIMEOUT, OTEL_EXPORTER_OTLP_LOGS_PROTOCOL, and so on. They override the generic variable for that signal only.

Selecting exporters

VariableDefaultValues
OTEL_TRACES_EXPORTERotlpotlp, zipkin, console, none
OTEL_METRICS_EXPORTERotlpotlp, prometheus, console, none
OTEL_LOGS_EXPORTERotlpotlp, console, none

console prints spans to stdout, which is the fastest way to confirm instrumentation works before a backend is involved. none disables a signal without removing its instrumentation.

Some agents ship with OTEL_LOGS_EXPORTER defaulting to none. If traces arrive and logs do not, check this first.

TLS

VariableDescription
OTEL_EXPORTER_OTLP_CERTIFICATEPath to the CA certificate for verifying the server
OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATEPath to the client certificate, for mTLS
OTEL_EXPORTER_OTLP_CLIENT_KEYPath to the client private key, for mTLS
OTEL_EXPORTER_OTLP_INSECUREtrue disables transport security. Local Collectors only

Sampling

VariableDefaultDescription
OTEL_TRACES_SAMPLERparentbased_always_onSampler name
OTEL_TRACES_SAMPLER_ARGArgument, meaning depends on the sampler

Accepted samplers: always_on, always_off, traceidratio, parentbased_always_on, parentbased_always_off, parentbased_traceidratio, jaeger_remote, parentbased_jaeger_remote.

shell
export OTEL_TRACES_SAMPLER=parentbased_traceidratio
export OTEL_TRACES_SAMPLER_ARG=0.1   # keep 10%

Prefer the parentbased_ variants. Without them each service decides independently and traces come out fragmented. See sampling.

Propagation

VariableDefaultDescription
OTEL_PROPAGATORStracecontext,baggageComma-separated propagator list

Values: tracecontext, baggage, b3, b3multi, jaeger, xray, ottrace, none. Listing several builds a composite that extracts whichever format arrives and injects all of them — which is how you migrate formats without breaking traces. See context propagation.

Batching

Spans and logs are buffered and exported in batches. These control the buffer.

VariableDefaultDescription
OTEL_BSP_SCHEDULE_DELAY5000Milliseconds between span batch exports
OTEL_BSP_EXPORT_TIMEOUT30000Milliseconds allowed per span export
OTEL_BSP_MAX_QUEUE_SIZE2048Spans buffered before new ones are dropped
OTEL_BSP_MAX_EXPORT_BATCH_SIZE512Spans per export request
OTEL_BLRP_SCHEDULE_DELAY1000Same, for log records
OTEL_BLRP_EXPORT_TIMEOUT30000
OTEL_BLRP_MAX_QUEUE_SIZE2048
OTEL_BLRP_MAX_EXPORT_BATCH_SIZE512
OTEL_METRIC_EXPORT_INTERVAL60000Milliseconds between metric exports

The queue size is the one to watch. When it fills, spans are dropped silently — the symptom is missing spans under load with no errors anywhere. Raise OTEL_BSP_MAX_QUEUE_SIZE for high-throughput services, and remember it is a memory ceiling: queue size times average span size.

Limits

Guards against a single pathological span exhausting memory or being rejected by the backend.

VariableDefaultDescription
OTEL_ATTRIBUTE_COUNT_LIMIT128Attributes per span, log record, or resource
OTEL_ATTRIBUTE_VALUE_LENGTH_LIMITunlimitedCharacters per attribute value
OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT128Overrides the global limit for spans
OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMITunlimitedOverrides the global value limit for spans
OTEL_SPAN_EVENT_COUNT_LIMIT128Events per span
OTEL_SPAN_LINK_COUNT_LIMIT128Links per span

Truncation is silent. If attribute values are being cut off at a suspiciously round number, a length limit is set somewhere.

Setting OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT is worthwhile when instrumentation records SQL statements or request bodies — a single unbounded value can dwarf the rest of the span.

Disabling

VariableDefaultDescription
OTEL_SDK_DISABLEDfalsetrue turns the SDK into a no-op for all signals

Useful for tests and for turning instrumentation off in an incident without redeploying. Instrumentation calls still execute, so overhead is reduced rather than eliminated.

Removed and deprecated

Configuration copied from older tutorials often includes variables that no longer do anything:

VariableStatus
OTEL_EXPORTER_JAEGER_ENDPOINTRemoved. The Jaeger exporter is gone from the SDKs
OTEL_EXPORTER_JAEGER_USERRemoved
OTEL_EXPORTER_JAEGER_PASSWORDRemoved
jaeger value for OTEL_PROPAGATORSDeprecated, still functional for legacy interop

Jaeger has accepted OTLP natively for years, so exporting to it means pointing OTEL_EXPORTER_OTLP_ENDPOINT at Jaeger's OTLP port. There is no Jaeger-specific configuration any more.

Per-environment configuration

Development — see everything, locally:

shell
export OTEL_SERVICE_NAME=checkout-api
export OTEL_RESOURCE_ATTRIBUTES=deployment.environment.name=development
export OTEL_TRACES_SAMPLER=always_on
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_EXPORTER_OTLP_INSECURE=true

Swap the exporter to console to check instrumentation without running a Collector at all:

shell
export OTEL_TRACES_EXPORTER=console

Production — sample, batch larger, secure the transport:

shell
export OTEL_SERVICE_NAME=checkout-api
export OTEL_RESOURCE_ATTRIBUTES=service.version=1.2.3,deployment.environment.name=production
export OTEL_EXPORTER_OTLP_ENDPOINT=https://api.uptrace.dev:4317
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_HEADERS=uptrace-dsn=https://<secret>@api.uptrace.dev?grpc=4317
export OTEL_EXPORTER_OTLP_COMPRESSION=gzip
export OTEL_TRACES_SAMPLER=parentbased_traceidratio
export OTEL_TRACES_SAMPLER_ARG=0.1
export OTEL_BSP_MAX_QUEUE_SIZE=4096

OTEL_EXPORTER_OTLP_HEADERS carries credentials. Inject it from a secret store rather than committing it to a manifest.

What's next?