OpenTelemetry OpenTelemetry

Configure SDKs with OTEL_* Environment Variables

Set the service name, exporters, sampling, and limits for any language using standard variables.

10 min Beginner

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_NAME sets service.name, the most important attribute, because backends group everything by it. If unset, you get an unknown_service name. It takes precedence over service.name inside OTEL_RESOURCE_ATTRIBUTES.
  • OTEL_RESOURCE_ATTRIBUTES is a comma-separated list of key=value pairs describing the service, such as its version and environment.
  • OTEL_EXPORTER_OTLP_ENDPOINT is where telemetry goes. Point it at a Collector.
  • OTEL_EXPORTER_OTLP_PROTOCOL is grpc, http/protobuf, or http/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_PROPAGATORS decides which headers carry trace context between services. The default is tracecontext,baggage (W3C). All services in a request path must use compatible propagators, or traces break at the boundary. Add b3 or others only when you must interoperate with older systems.
  • OTEL_TRACES_SAMPLER defaults to parentbased_always_on, which records everything and follows the caller’s decision. For head sampling, parentbased_traceidratio with OTEL_TRACES_SAMPLER_ARG=0.1 keeps 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:

VariableDefault
OTEL_BSP_SCHEDULE_DELAY5000 ms
OTEL_BSP_MAX_QUEUE_SIZE2048
OTEL_BSP_MAX_EXPORT_BATCH_SIZE512
OTEL_BSP_EXPORT_TIMEOUT30000 ms
OTEL_BLRP_SCHEDULE_DELAY1000 ms
OTEL_METRIC_EXPORT_INTERVAL60000 ms
OTEL_ATTRIBUTE_COUNT_LIMIT128
OTEL_SPAN_EVENT_COUNT_LIMIT128

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