Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The Voice Live SDK includes built-in OpenTelemetry instrumentation that automatically traces connection, send, and receive operations. Use telemetry to monitor session health, diagnose latency issues, and correlate Voice Live operations with your application traces.
What gets traced
When you enable telemetry, the SDK automatically creates OpenTelemetry spans for:
| Operation | Span name prefix | Description |
|---|---|---|
| WebSocket connect | connect |
Connection establishment and lifecycle |
| Send events | send |
Session updates, conversation items, response requests |
| Receive events | recv |
Server events including responses, VAD, and errors |
Prerequisites
- A working Voice Live setup. Complete one of the following quickstarts:
Reference documentation | Package (PyPi) | Additional samples on GitHub
Additional prerequisites
azure-ai-voicelivepackage version 1.2.0 or later.Install the telemetry dependencies:
pip install opentelemetry-sdk azure-core-tracing-opentelemetryFor Azure Monitor export, install instead:
pip install azure-monitor-opentelemetry
Enable console tracing
Add the following code to your application before calling connect(). This is the smallest code change to start seeing Voice Live spans in your terminal.
from azure.core.settings import settings
# Step 1: Tell azure-core to use OpenTelemetry for tracing.
settings.tracing_implementation = "opentelemetry"
# Step 2: Configure a TracerProvider with a console exporter.
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
SimpleSpanProcessor,
ConsoleSpanExporter,
)
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(
SimpleSpanProcessor(ConsoleSpanExporter())
)
trace.set_tracer_provider(tracer_provider)
# Step 3: Enable the VoiceLive instrumentor.
from azure.ai.voicelive.telemetry import VoiceLiveInstrumentor
os.environ.setdefault(
"AZURE_EXPERIMENTAL_ENABLE_GENAI_TRACING", "true"
)
VoiceLiveInstrumentor().instrument()
All connect, send, and recv operations now produce spans printed to stdout.
Export traces to Azure Monitor
To send traces to Application Insights instead of the console, replace the console setup with Azure Monitor configuration. Set the APPLICATIONINSIGHTS_CONNECTION_STRING environment variable, then add the following code.
from azure.core.settings import settings
# Step 1: Tell azure-core to use OpenTelemetry for tracing.
settings.tracing_implementation = "opentelemetry"
# Step 2: Configure Azure Monitor as the trace exporter.
from opentelemetry import trace
from azure.monitor.opentelemetry import configure_azure_monitor
application_insights_connection_string = os.environ[
"APPLICATIONINSIGHTS_CONNECTION_STRING"
]
configure_azure_monitor(
connection_string=application_insights_connection_string
)
# Step 3: Enable the VoiceLive instrumentor.
from azure.ai.voicelive.telemetry import VoiceLiveInstrumentor
os.environ.setdefault(
"AZURE_EXPERIMENTAL_ENABLE_GENAI_TRACING", "true"
)
VoiceLiveInstrumentor().instrument()
View the results in the Tracing tab in your Azure AI Foundry project page or in Application Insights.
Add custom span attributes
To correlate Voice Live traces with your application context (session IDs, user IDs, or request identifiers), create a custom SpanProcessor.
class CustomAttributeSpanProcessor(SpanProcessor):
"""Add application-specific attributes to every span."""
def on_start(self, span: Span, parent_context=None):
# Add a session identifier to all spans.
span.set_attribute(
"app.session_id", "my-session-123"
)
# Tag send spans with extra context.
if span.name and span.name.startswith("send"):
span.set_attribute(
"app.send.context", "user-interaction"
)
# Tag receive spans with a priority level.
if span.name and span.name.startswith("recv"):
span.set_attribute(
"app.recv.priority", "normal"
)
def on_end(self, span: ReadableSpan):
pass
Register the custom processor with the global tracer provider after your standard telemetry setup:
# Register the custom processor with the global provider.
provider = cast(TracerProvider, trace.get_tracer_provider())
provider.add_span_processor(CustomAttributeSpanProcessor())
Enable content recording
Content recording captures full message payloads (send and receive) in span events as gen_ai.event.content attributes. This is useful for debugging but can capture personal data.
Caution
Content recording may capture personal data. Only enable in development or controlled environments.
# Option 1: Enable via environment variable.
# os.environ[
# "OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"
# ] = "true"
# Option 2: Enable programmatically.
VoiceLiveInstrumentor().instrument(
enable_content_recording=True
)
Reference documentation | Package (NuGet) | Additional samples on GitHub
Note
C# telemetry samples are coming soon. Check back for updated guidance on enabling OpenTelemetry tracing with the C# Voice Live SDK.
Production best practices
- Batch export: Use
BatchSpanProcessorinstead ofSimpleSpanProcessorin production to reduce overhead. - Sampling: Configure a sampling strategy to control trace volume at scale.
- Sensitive data: Don't enable content recording in production. Message payloads can contain personal data.
- Correlation: Use custom span attributes to add session or user identifiers so you can filter traces in your observability backend.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| No spans appear | Missing AZURE_EXPERIMENTAL_ENABLE_GENAI_TRACING env var |
Set AZURE_EXPERIMENTAL_ENABLE_GENAI_TRACING=true |
| No spans appear | VoiceLiveInstrumentor().instrument() not called |
Call instrument() before connect() |
| Spans missing in Azure Monitor | Missing or invalid connection string | Verify APPLICATIONINSIGHTS_CONNECTION_STRING is set correctly |
| Spans appear in console but not in Azure Monitor | Using ConsoleSpanExporter instead of Azure Monitor |
Switch to configure_azure_monitor() |
| Custom attributes missing | Processor registered after spans are created | Register the custom processor before calling connect() |