Configure SDKs with OTEL_* Environment Variables
Set the service name, exporters, sampling, and limits for any language using standard variables.
OpenTelemetry SDKs share a common set of environment variables, so the same configuration works for Java, Python, Node.js, .NET, and others. This is the most common way to configure an application, and it fits containers and Kubernetes perfectly, since the platform sets the environment. This guide covers the variables you will use most.
Each language SDK implements the specification to its own pace, so verify less common variables in the documentation for your language.
The essentials
export OTEL_SERVICE_NAME=checkout
export OTEL_RESOURCE_ATTRIBUTES=service.version=1.4.2,deployment.environment.name=staging
export OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_SERVICE_NAMEsetsservice.name, the most important attribute, because backends group everything by it. If unset, you get anunknown_servicename. It takes precedence overservice.nameinsideOTEL_RESOURCE_ATTRIBUTES.OTEL_RESOURCE_ATTRIBUTESis a comma-separated list ofkey=valuepairs describing the service, such as its version and environment.OTEL_EXPORTER_OTLP_ENDPOINTis where telemetry goes. Point it at a Collector.OTEL_EXPORTER_OTLP_PROTOCOLisgrpc,http/protobuf, orhttp/json.
Endpoints and protocols: the port must match
The defaults are http://localhost:4318 for HTTP and http://localhost:4317 for gRPC. For the HTTP protocols, the SDK appends v1/traces, v1/metrics, and v1/logs to the base endpoint. If you set a per-signal endpoint, such as OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, it is used exactly as given with nothing appended.
The most common mistake is a mismatch: sending gRPC to port 4318 or HTTP to port 4317. Pick the protocol and the port together. The default protocol in the specification is http/protobuf, but some SDKs default to gRPC, so set it explicitly.
Exporter selection
export OTEL_TRACES_EXPORTER=otlp # default
export OTEL_METRICS_EXPORTER=otlp # default
export OTEL_LOGS_EXPORTER=otlp # default
Values include otlp, console (print to the terminal, handy for debugging), and none to turn a signal off. Some languages support others, such as prometheus for metrics or zipkin for traces.
OTLP exporter options
export OTEL_EXPORTER_OTLP_HEADERS="authorization=Bearer abc123,x-tenant=team-a"
export OTEL_EXPORTER_OTLP_TIMEOUT=10000 # milliseconds in most SDKs
export OTEL_EXPORTER_OTLP_COMPRESSION=gzip
export OTEL_EXPORTER_OTLP_CERTIFICATE=/etc/ssl/ca.pem
export OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE=/etc/ssl/client.pem
export OTEL_EXPORTER_OTLP_CLIENT_KEY=/etc/ssl/client.key
Every one of these has per-signal variants, such as OTEL_EXPORTER_OTLP_TRACES_TIMEOUT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, which take precedence over the base variable. HEADERS is a comma-separated list of key=value pairs, and all values are strings. Use an https:// endpoint for TLS, and the certificate variables for private certificate authorities or mutual TLS.
Propagation and sampling
export OTEL_PROPAGATORS=tracecontext,baggage # default
export OTEL_TRACES_SAMPLER=parentbased_traceidratio
export OTEL_TRACES_SAMPLER_ARG=0.1
OTEL_PROPAGATORSdecides which headers carry trace context between services. The default istracecontext,baggage(W3C). All services in a request path must use compatible propagators, or traces break at the boundary. Addb3or others only when you must interoperate with older systems.OTEL_TRACES_SAMPLERdefaults toparentbased_always_on, which records everything and follows the caller’s decision. For head sampling,parentbased_traceidratiowithOTEL_TRACES_SAMPLER_ARG=0.1keeps about ten percent of new traces while respecting a parent’s decision. The sampling guide covers when to sample in the Collector instead.
Batching and limits
Batch settings control memory use and export frequency. Defaults from the specification:
| Variable | Default |
|---|---|
OTEL_BSP_SCHEDULE_DELAY | 5000 ms |
OTEL_BSP_MAX_QUEUE_SIZE | 2048 |
OTEL_BSP_MAX_EXPORT_BATCH_SIZE | 512 |
OTEL_BSP_EXPORT_TIMEOUT | 30000 ms |
OTEL_BLRP_SCHEDULE_DELAY | 1000 ms |
OTEL_METRIC_EXPORT_INTERVAL | 60000 ms |
OTEL_ATTRIBUTE_COUNT_LIMIT | 128 |
OTEL_SPAN_EVENT_COUNT_LIMIT | 128 |
BSP is the span batch processor and BLRP is the log record batch processor. Raise the queue size if you see dropped spans under load, and lower the metric interval during testing (for example 10000) so you don’t wait a minute for a data point.
Operational switches
export OTEL_SDK_DISABLED=true # turn telemetry off without removing instrumentation
export OTEL_LOG_LEVEL=debug # the SDK's own diagnostic log level (default info)
OTEL_SDK_DISABLED is a quick kill switch. Debug logging is verbose, so don’t leave it on in production.
Putting it in Docker Compose and Kubernetes
Compose:
services:
checkout:
image: myorg/checkout:1.4.2
environment:
OTEL_SERVICE_NAME: checkout
OTEL_RESOURCE_ATTRIBUTES: service.version=1.4.2,deployment.environment.name=staging
OTEL_EXPORTER_OTLP_ENDPOINT: http://otel-collector:4318
OTEL_EXPORTER_OTLP_PROTOCOL: http/protobuf
OTEL_TRACES_SAMPLER: parentbased_traceidratio
OTEL_TRACES_SAMPLER_ARG: "0.25"
Kubernetes:
env:
- name: OTEL_SERVICE_NAME
value: checkout
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: http://otel-collector.observability.svc.cluster.local:4318
- name: OTEL_RESOURCE_ATTRIBUTES
value: k8s.pod.name=$(POD_NAME),deployment.environment.name=staging
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
The Operator guide shows how to inject these automatically, with an Instrumentation resource, so application teams don’t set them by hand.
Order of precedence and gotchas
- Configuration in code usually wins over environment variables, and per-signal variables win over general ones.
- A variable that isn’t recognized by your SDK is silently ignored. Check the language’s configuration page when a setting seems to do nothing.
- Don’t put secrets in
OTEL_RESOURCE_ATTRIBUTES. It becomes a label on every piece of telemetry. - When an endpoint contains a path (for example behind a proxy), use the per-signal endpoint variables so nothing is appended.
- Keep the variable list in one place per service (a Compose file or a Helm values file), so changes are reviewed.
For the full list, see the SDK environment variable specification and the OTLP exporter configuration.
Popular Guides
-
OpenTelemetry Explained: SDKs, OTLP, and the Collector Understand the moving parts and the three places configuration lives before you write any YAML. -
The Collector Configuration Model: Components, Pipelines, and Providers Learn the rules of the Collector's YAML: naming, pipelines, connectors, merging files, and environment variables. -
Instrument Apps Without Code Changes: Java, Python, and Node.js Attach OpenTelemetry agents with environment variables and command-line flags only. -
Make the Collector Production-Ready: Memory Limits, Batching, and Retries Configure processors, queues, and persistent storage so telemetry survives overload and outages. -
Deploy the Collector on Kubernetes with Helm Install the official chart, use presets for logs and metrics, and override the config through values files. -
Troubleshoot the Collector and SDKs A systematic checklist for when telemetry doesn't arrive: debug exporter, health checks, internal metrics, and common mistakes.