Edit

Enable telemetry and tracing for Voice Live

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

Reference documentation | Package (PyPi) | Additional samples on GitHub

Additional prerequisites

  • azure-ai-voicelive package version 1.2.0 or later.

  • Install the telemetry dependencies:

    pip install opentelemetry-sdk azure-core-tracing-opentelemetry
    

    For 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 BatchSpanProcessor instead of SimpleSpanProcessor in 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()