How to Configure OpenTelemetry Tracing with Headroom: Complete Setup Guide

Headroom provides an optional OpenTelemetry tracing façade that exports spans to Langfuse via OTLP when you install the otel extra, set the required environment variables, and call configure_langfuse_tracing() at startup.

Headroom ships with a lightweight tracing abstraction that remains in-process by default. To export distributed traces to an OpenTelemetry-compatible collector, you must enable the optional otel dependency and configure the Langfuse exporter using environment variables. This guide covers the complete configuration flow based on the Headroom source code.

Install the OpenTelemetry Extra

Begin by installing Headroom with the optional OpenTelemetry dependencies. The otel extra, defined in [pyproject.toml](https://github.com/chopratejas/headroom/blob/main/pyproject.toml) (line 153), pulls in the OpenTelemetry SDK and HTTP OTLP exporter.

pip install "headroom-ai[otel]"

Without this extra, Headroom falls back to a no-op tracer that discards spans locally.

Configure Environment Variables

Tracing is driven entirely by environment variables. The LangfuseTracingConfig.from_env() method (lines 54-77) reads these values to construct the OTLP endpoint and authentication headers.

Set the following variables before starting your application:

  • HEADROOM_LANGFUSE_ENABLED – Set to true to activate the exporter.
  • LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY – Authentication credentials for the Langfuse collector.
  • LANGFUSE_BASE_URL (or LANGFUSE_OTEL_HOST) – The base URL of your Langfuse instance (e.g., https://cloud.langfuse.com).
  • HEADROOM_LANGFUSE_SERVICE_NAME – The service name that appears in trace metadata (defaults to headroom).
  • HEADROOM_LANGFUSE_RESOURCE_ATTRIBUTES – Optional comma-separated key=value pairs added as resource attributes (e.g., region=us-east,team=nlp).

These variables configure the OTLP endpoint at /api/public/otel/v1/traces and the HTTP Basic Authentication header required by Langfuse.

Activate the Exporter

Initialize the tracing system once at application startup. The configure_langfuse_tracing() function creates a TracerProvider, attaches a BatchSpanProcessor with an OTLPSpanExporter, and replaces the global Headroom tracer.

from headroom.observability.tracing import configure_langfone_tracing

# Reads env vars and configures the global tracer

configure_langfuse_tracing()

If the otel extra is missing or required environment variables are absent, the function falls back to a no-op tracer and logs a warning (lines 149-158 of tracing.py).

Create and Export Spans

Once configured, use the get_headroom_tracer() function to obtain the tracer instance and start spans. The HeadroomTracer delegates to the underlying OpenTelemetry tracer, ensuring all spans export to the configured Langfuse endpoint.

from headroom.observability.tracing import get_headroom_tracer

tracer = get_headroom_tracer()

def process_request():
    with tracer.start_as_current_span("process_request", attributes={"user_id": "12345"}):
        # Your business logic here

        pass

Standard OpenTelemetry context propagation applies, so nested spans automatically become children of the current active span.

Advanced Configuration and Lifecycle Management

Inspect Tracing Status

Verify the current configuration using get_langfuse_tracing_status() (lines 94-106):

from headroom.observability.tracing import get_langfuse_tracing_status

status = get_langfuse_tracing_status()
print(status)

# Output: {'configured': True, 'enabled': True, 'service_name': 'headroom', ...}

Clean Shutdown

Ensure all pending spans flush before process exit by calling shutdown_headroom_tracing() (lines 191-205):

import atexit
from headroom.observability.tracing import shutdown_headroom_tracing

atexit.register(shutdown_headroom_tracing)

Complete Example

Here is a minimal working example that combines installation, configuration, and instrumentation:

import os
from headroom.observability.tracing import (
    configure_langfuse_tracing,
    get_headroom_tracer,
    shutdown_headroom_tracing
)

# 1. Configure environment

os.environ["HEADROOM_LANGFUSE_ENABLED"] = "true"
os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-..."
os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-..."
os.environ["HEADROOM_LANGFUSE_RESOURCE_ATTRIBUTES"] = "env=production,service=ai-gateway"

# 2. Initialize tracing

configure_langfuse_tracing()

# 3. Use the tracer

tracer = get_headroom_tracer()

with tracer.start_as_current_span("main_workflow"):
    print("Processing with distributed tracing enabled")

# 4. Optional: cleanup

shutdown_headroom_tracing()

Summary

  • Install the extra: Use pip install "headroom-ai[otel]" to include OpenTelemetry SDK dependencies.
  • Set environment variables: Configure HEADROOM_LANGFUSE_ENABLED, LANGFUSE_PUBLIC_KEY, and LANGFUSE_SECRET_KEY to authenticate with the Langfuse collector.
  • Initialize at startup: Call configure_langfuse_tracing() once to set up the TracerProvider and BatchSpanProcessor.
  • Instrument code: Use get_headroom_tracer() to obtain the tracer and start_as_current_span() to create exportable spans.
  • Manage lifecycle: Call shutdown_headroom_tracing() on exit to ensure all spans flush to the collector.

Frequently Asked Questions

What happens if I install Headroom without the otel extra?

The library defaults to a no-op tracer that records spans in-process only. If you call configure_langfuse_tracing() without the extra installed, the function catches the missing dependency and logs a warning, continuing execution without exporting traces (see lines 149-158 in headroom/observability/tracing.py).

Can I export traces to a different OTLP endpoint instead of Langfuse?

Currently, Headroom only supports Langfuse as the OTLP destination through the configure_langfuse_tracing() helper. The function specifically constructs the Langfuse endpoint path (/api/public/otel/v1/traces) and authentication headers. For other collectors, you would need to implement a custom configuration using the underlying OpenTelemetry SDK directly.

How do I add custom resource attributes to all spans?

Set the HEADROOM_LANGFUSE_RESOURCE_ATTRIBUTES environment variable to a comma-separated list of key=value pairs before calling configure_langfuse_tracing(). These attributes attach to the Resource associated with the TracerProvider, appearing on every span exported from the service.

Is tracing enabled by default?

No. Tracing remains disabled until you explicitly set HEADROOM_LANGFUSE_ENABLED=true and call configure_langfuse_tracing(). This opt-in design prevents accidental data leakage to external collectors and ensures zero overhead when observability is not required.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →