Implementation:Arize ai Phoenix TracerProvider Instrumentation
Appearance
| Knowledge Sources | |
|---|---|
| Domains | AI Observability, OpenTelemetry, LLM Instrumentation |
| Last Updated | 2026-02-14 00:00 GMT |
Overview
Concrete tool for instrumenting LLM applications with OpenTelemetry tracing provided by the phoenix.otel module's TracerProvider class and the register() function's auto-instrumentation capability.
Description
The Phoenix TracerProvider extends openinference.instrumentation.TracerProvider (which itself extends opentelemetry.sdk.trace.TracerProvider) with Phoenix-aware defaults. It serves as the foundation for both manual and automatic instrumentation of LLM applications.
Key behaviors:
- Default processor creation: When an
endpointis provided (or inferred fromPHOENIX_COLLECTOR_ENDPOINT), theTracerProviderautomatically creates a defaultSimpleSpanProcessorwith an appropriate exporter (HTTP or gRPC) based on the endpoint URL pattern. - Processor replacement: Calling
add_span_processor()on aTracerProviderthat has a default processor will first shut down and remove the default processor before adding the new one. This prevents duplicate span export. - Resource management: Automatically creates an OTel
Resourcewith theopeninference.project.nameattribute set from the environment if no explicit resource is provided. - Auto-instrumentation: The
register(auto_instrument=True)pathway calls_auto_instrument_installed_openinference_libraries(), which discovers all installed OpenInference instrumentors via Python entry points and activates them.
Usage
Use these APIs when:
- You need manual instrumentation with fine-grained control: instantiate
TracerProviderdirectly, obtain a tracer, and create spans explicitly. - You want automatic instrumentation: call
register(auto_instrument=True)to discover and activate all installed OpenInference instrumentors. - You need to combine both approaches: use auto-instrumentation for framework calls and manual instrumentation for custom business logic.
Code Reference
Source Location
- Repository: Phoenix
- File:
packages/phoenix-otel/src/phoenix/otel/otel.pyTracerProviderclass: lines 201-296_auto_instrument_installed_openinference_libraries(): lines 805-821
Signature
class TracerProvider(_TracerProvider):
def __init__(
self,
*args: Any,
endpoint: Optional[str] = None,
protocol: Optional[Literal["http/protobuf", "grpc"]] = None,
verbose: bool = True,
**kwargs: Any,
):
...
def add_span_processor(
self,
*args: Any,
replace_default_processor: bool = True,
**kwargs: Any,
) -> None:
...
Auto-instrumentation helper:
def _auto_instrument_installed_openinference_libraries(
tracer_provider: TracerProvider,
) -> None:
...
Import
from phoenix.otel import TracerProvider
from phoenix.otel import register
I/O Contract
Inputs (TracerProvider.__init__)
| Name | Type | Required | Description |
|---|---|---|---|
| *args | Any | No | Positional arguments forwarded to the base opentelemetry.sdk.trace.TracerProvider.
|
| endpoint | Optional[str] | No | Collector endpoint URL. If provided, a default SimpleSpanProcessor and exporter are created automatically. Falls back to PHOENIX_COLLECTOR_ENDPOINT env var, then http://localhost:6006.
|
| protocol | Optional[Literal["http/protobuf", "grpc"]] | No | Explicit transport protocol. If not set, inferred from the endpoint URL (paths containing /v1/traces use HTTP; port 4317 uses gRPC).
|
| verbose | bool | No | If True (default), prints tracing configuration details to stdout.
|
| **kwargs | Any | No | Keyword arguments forwarded to the base TracerProvider, including resource for custom OTel resource attributes.
|
Inputs (add_span_processor)
| Name | Type | Required | Description |
|---|---|---|---|
| *args | Any | Yes | Positional arguments forwarded to the base add_span_processor (typically a SpanProcessor instance).
|
| replace_default_processor | bool | No | If True (default), shuts down and removes any default processor before adding the new one.
|
| **kwargs | Any | No | Additional keyword arguments forwarded to the base method. |
Outputs
| Name | Type | Description |
|---|---|---|
| TracerProvider instance | TracerProvider | A configured tracer provider from which tracers can be obtained via get_tracer().
|
| tracer | Tracer | Obtained via tracer_provider.get_tracer(__name__), used to create spans.
|
Usage Examples
Manual Instrumentation
from phoenix.otel import TracerProvider
# Create a TracerProvider that auto-configures endpoint from env
tracer_provider = TracerProvider()
# Obtain a tracer
tracer = tracer_provider.get_tracer(__name__)
# Create spans manually
with tracer.start_as_current_span("process-user-query") as span:
span.set_attribute("input.value", "What is the capital of France?")
with tracer.start_as_current_span("llm-call") as child_span:
response = call_llm(query)
child_span.set_attribute("output.value", response)
child_span.set_attribute("llm.token_count.total", token_count)
Automatic Instrumentation via register()
from phoenix.otel import register
# Auto-discover and instrument all installed OpenInference libraries
tracer_provider = register(auto_instrument=True)
# Now all calls to instrumented libraries (OpenAI, LangChain, etc.)
# automatically produce spans
import openai
client = openai.OpenAI()
# This call is automatically traced
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Hello!"}],
)
Custom TracerProvider with Explicit Endpoint
from phoenix.otel import TracerProvider
from opentelemetry.sdk.resources import Resource
tracer_provider = TracerProvider(
resource=Resource.create({"openinference.project.name": "my-project"}),
endpoint="http://localhost:6006/v1/traces",
protocol="http/protobuf",
)
tracer = tracer_provider.get_tracer("my-app")
Combining Auto and Manual Instrumentation
from phoenix.otel import register
# Auto-instrument framework calls
tracer_provider = register(
auto_instrument=True,
project_name="my-agent",
)
# Also add manual spans for custom logic
tracer = tracer_provider.get_tracer(__name__)
with tracer.start_as_current_span("agent-reasoning-step"):
# Custom business logic that is not auto-instrumented
decision = evaluate_next_action(context)
Replacing the Default Processor
from phoenix.otel import TracerProvider, BatchSpanProcessor
# TracerProvider creates a default SimpleSpanProcessor
tracer_provider = TracerProvider()
# Replace the default with a BatchSpanProcessor for production
batch_processor = BatchSpanProcessor(
endpoint="https://my-collector.com/v1/traces",
headers={"Authorization": "Bearer my-token"},
)
tracer_provider.add_span_processor(batch_processor)
# The default SimpleSpanProcessor is automatically shut down and removed
Related Pages
Implements Principle
Requires Environment
Page Connections
Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment