phoenix.otel SDK collapses all of it into a single function call — and adds a few Phoenix-specific capabilities on top.
For the practical how-to of installing and using these helpers, see Set up tracing. This page covers what they do under the hood.
Appreciate the Simplicity
Configuring tracing with raw OpenTelemetry — Resource, Exporter, Span Processor, Tracer Provider — looks like this:register() helper replaces all of that:
What register() Does Under the Hood
The convenience function handles four things for you. Each one has additional capabilities specific to OpenInference and Phoenix compared to the standard OTel SDK:
Component returned by register() | What it adds beyond standard OTel |
|---|---|
| Tracer Provider | A Phoenix-aware provider with sensible defaults. Combined with the OpenInference instrumentation libraries, it makes the OpenInference context managers (using_session, using_user, using_metadata, etc.) attach attributes to spans automatically. |
| Span Processor | Configured and pre-attached. SimpleSpanProcessor by default, BatchSpanProcessor when you pass batch=True. |
| Span Exporter | Auto-detects gRPC or HTTP from the endpoint URL and configures the matching OTLP exporter. If api_key is set, it adds the Authorization: Bearer <key> header for you. |
| Resource | Sets the project name automatically from your project_name argument (or the PHOENIX_PROJECT_NAME environment variable). |
Auto-instrumentation
register() has an auto_instrument=True option that automatically calls .instrument() on every OpenInference auto-instrumentor installed in your environment.
OpenAIInstrumentor().instrument(...), LangChainInstrumentor().instrument(...), and so on for every installed instrumentor. Just pip install the instrumentors you want active, and auto_instrument=True finds them at runtime.
For the full set of installable instrumentors, see the OpenInference repository.
Configuration
register() reads from environment variables when arguments aren’t passed:
| Argument | Environment variable | Notes |
|---|---|---|
project_name | PHOENIX_PROJECT_NAME | Name of the project in Phoenix. Defaults to "default". |
endpoint | PHOENIX_COLLECTOR_ENDPOINT | The collector endpoint. Defaults to http://localhost:6006. |
api_key | PHOENIX_API_KEY | Optional for local Phoenix. Required for Phoenix Cloud or any authenticated instance — added as a Bearer token header. |
headers | PHOENIX_CLIENT_HEADERS | Additional headers for the OTLP request (e.g. tenant identifiers). |
Multi-project routing
Phoenix is typically deployed as one instance per environment, and each application sends all of its traces to a single project. If you need to route traces from one application to multiple projects, the options are:- Multiple
register()calls with differentproject_namevalues andset_global_tracer_provider=Falseon all but one. You then have to track which tracer provider to use where in your code. - OpenTelemetry Collector with a routing connector — let the application send all spans to the Collector, then route to different Phoenix projects (or different backends entirely) based on span attributes. See OpenTelemetry Collector.
register() call is everything you need.
When to Use Which
| Use case | Recommended approach |
|---|---|
| Single project, simple app | register(...) |
| Single project + auto-instrument every installed library | register(project_name=..., auto_instrument=True) |
| Multiple projects from one app | Multiple register() calls, or an OTel Collector routing connector |
| Maximum control, custom processor pipeline | Raw OTel — see Tracer Provider |

