Skip to content

Commit 8045cd6

Browse files
authored
Add Voice Live telemetry quickstart samples (#218)
* Add Voice Live telemetry quickstart samples for Python with placeholders for C#, Java, JS * Address review: add flush/shutdown, fix docstring deps, fix relative links
1 parent aa856ee commit 8045cd6

11 files changed

Lines changed: 704 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Python samples showcasing:
6262
- **Model Quickstart**: Direct model access with flexible authentication
6363
- **Bring-Your-Own-Model (BYOM) Quickstart**: Use your own models hosted in Foundry with proactive greetings
6464
- **Function Calling**: Advanced tool integration with custom functions and proactive greetings
65+
- **Telemetry Quickstart**: OpenTelemetry tracing — console export, Azure Monitor, custom attributes, and content recording
6566
- **RAG-enabled Voice Assistant**: Full-stack voice assistant with Azure AI Search integration and `azd` deployment
6667
- **Voice Live Avatar**: Avatar-enabled voice conversations with server-side SDK and Docker deployment
6768
- Built with Python 3.8+ and async/await patterns
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Telemetry Quickstart - C#
2+
3+
Telemetry samples for the C# Voice Live SDK are coming soon.
4+
5+
For Python telemetry samples, see the [Python TelemetryQuickstart](../../../python/voice-live-quickstarts/TelemetryQuickstart/).
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Telemetry Quickstart - Java
2+
3+
Telemetry samples for the Java Voice Live SDK are coming soon.
4+
5+
For Python telemetry samples, see the [Python TelemetryQuickstart](../../../python/voice-live-quickstarts/TelemetryQuickstart/).
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Telemetry Quickstart - JavaScript
2+
3+
Telemetry samples for the JavaScript Voice Live SDK are coming soon.
4+
5+
For Python telemetry samples, see the [Python TelemetryQuickstart](../../../python/voice-live-quickstarts/TelemetryQuickstart/).

python/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@ Demonstrates how to implement function calling with VoiceLive models, enabling t
6868
- Advanced tool integration
6969
- Proactive greeting support
7070

71+
### [Telemetry Quickstart](./voice-live-quickstarts/TelemetryQuickstart/)
72+
73+
Demonstrates how to enable and customize OpenTelemetry tracing for Voice Live SDK sessions. These are text-mode samples — copy the region-tagged snippets into any existing Voice Live application.
74+
75+
**Key Features:**
76+
- Console span export for local debugging
77+
- Azure Monitor / Application Insights export
78+
- Custom span attributes for session and user correlation
79+
- Content recording with PII warnings
80+
81+
> **Docs**: [Enable telemetry and tracing for Voice Live](https://learn.microsoft.com/azure/ai-services/speech-service/how-to-voice-live-telemetry)
82+
7183
### [RAG-enabled Voice Assistant](./voice-live-voicerag-assistant/README.md)
7284

7385
Demonstrates how to build a real-time voice assistant with Retrieval-Augmented Generation (RAG) capabilities using Azure AI Voice Live API and Azure AI Search.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Telemetry Quickstart - Python
2+
3+
These samples demonstrate how to enable and customize OpenTelemetry tracing for the Azure AI Voice Live SDK.
4+
5+
> **Text-mode samples**: These samples use text mode (`Modality.TEXT`) so they run without a microphone. The telemetry setup code is isolated inside region tags (e.g., `# <enable_console_tracing>` / `# </enable_console_tracing>`) and can be copied into any existing Voice Live application — including audio-mode quickstarts and demos in this repo.
6+
7+
## Documentation
8+
9+
- [Enable telemetry and tracing for Voice Live](https://learn.microsoft.com/azure/ai-services/speech-service/how-to-voice-live-telemetry) — full how-to guide on Microsoft Learn
10+
11+
## Samples
12+
13+
| File | Region tag(s) | Description |
14+
|---|---|---|
15+
| `telemetry-console.py` | `enable_console_tracing` | Export Voice Live traces to the console |
16+
| `telemetry-azure-monitor.py` | `enable_azure_monitor_tracing` | Export traces to Azure Monitor / Application Insights |
17+
| `telemetry-custom-attributes.py` | `custom_span_processor`, `add_custom_processor` | Add custom span attributes for correlation |
18+
| `telemetry-content-recording.py` | `enable_content_recording` | Enable full message payload recording in traces |
19+
20+
### Adding telemetry to other samples
21+
22+
Copy the code between the region tags into your own sample. For example, to add console tracing to any Voice Live app, copy the code inside `# <enable_console_tracing>` / `# </enable_console_tracing>` from `telemetry-console.py` and place it before your `connect()` call.
23+
24+
## Prerequisites
25+
26+
- Python 3.9 or later
27+
- An Azure AI Services or Speech resource
28+
- Complete one of the Voice Live quickstarts first:
29+
- [Voice Live with Foundry models](https://learn.microsoft.com/azure/ai-services/speech-service/voice-live-quickstart)
30+
- [Voice Live with Foundry agents](https://learn.microsoft.com/azure/ai-services/speech-service/voice-live-agents-quickstart)
31+
32+
## Setup
33+
34+
1. Install dependencies:
35+
36+
```bash
37+
pip install -r requirements.txt
38+
```
39+
40+
2. Set environment variables:
41+
42+
```bash
43+
export AZURE_VOICELIVE_ENDPOINT="https://<your-resource>.services.ai.azure.com"
44+
export AZURE_VOICELIVE_API_KEY="<your-api-key>"
45+
```
46+
47+
For the Azure Monitor sample, also set:
48+
49+
```bash
50+
export APPLICATIONINSIGHTS_CONNECTION_STRING="<your-connection-string>"
51+
```
52+
53+
3. Run any sample:
54+
55+
```bash
56+
python telemetry-console.py
57+
```
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
azure-ai-voicelive
2+
opentelemetry-sdk
3+
azure-core-tracing-opentelemetry
4+
azure-monitor-opentelemetry
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# -------------------------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License.
4+
# -------------------------------------------------------------------------
5+
6+
"""
7+
FILE: telemetry-azure-monitor.py
8+
9+
DESCRIPTION:
10+
This sample demonstrates how to export Voice Live OpenTelemetry traces
11+
to Azure Monitor / Application Insights. View results in the "Tracing"
12+
tab in your Azure AI Foundry project page or in Application Insights.
13+
14+
The telemetry setup code (marked with region tags) can be copied into
15+
any existing Voice Live application to add Azure Monitor tracing.
16+
17+
USAGE:
18+
python telemetry-azure-monitor.py
19+
20+
Set the environment variables with your own values before running:
21+
1) AZURE_VOICELIVE_ENDPOINT - The Azure VoiceLive endpoint
22+
2) AZURE_VOICELIVE_API_KEY - The Azure VoiceLive API key
23+
3) APPLICATIONINSIGHTS_CONNECTION_STRING - Application Insights
24+
connection string
25+
26+
REQUIREMENTS:
27+
- azure-ai-voicelive
28+
- azure-monitor-opentelemetry
29+
- azure-core-tracing-opentelemetry
30+
"""
31+
32+
import asyncio
33+
import os
34+
35+
# <enable_azure_monitor_tracing>
36+
from azure.core.settings import settings
37+
38+
# Step 1: Tell azure-core to use OpenTelemetry for tracing.
39+
settings.tracing_implementation = "opentelemetry"
40+
41+
# Step 2: Configure Azure Monitor as the trace exporter.
42+
from opentelemetry import trace
43+
from azure.monitor.opentelemetry import configure_azure_monitor
44+
45+
application_insights_connection_string = os.environ[
46+
"APPLICATIONINSIGHTS_CONNECTION_STRING"
47+
]
48+
configure_azure_monitor(
49+
connection_string=application_insights_connection_string
50+
)
51+
52+
# Step 3: Enable the VoiceLive instrumentor.
53+
from azure.ai.voicelive.telemetry import VoiceLiveInstrumentor
54+
55+
os.environ.setdefault(
56+
"AZURE_EXPERIMENTAL_ENABLE_GENAI_TRACING", "true"
57+
)
58+
VoiceLiveInstrumentor().instrument()
59+
# </enable_azure_monitor_tracing>
60+
61+
from azure.core.credentials import AzureKeyCredential
62+
from azure.ai.voicelive.aio import connect
63+
from azure.ai.voicelive.models import (
64+
InputTextContentPart,
65+
Modality,
66+
OutputAudioFormat,
67+
RequestSession,
68+
ServerEventType,
69+
ServerVad,
70+
UserMessageItem,
71+
)
72+
73+
tracer = trace.get_tracer(__name__)
74+
75+
76+
async def main() -> None:
77+
endpoint = os.environ["AZURE_VOICELIVE_ENDPOINT"]
78+
api_key = os.environ["AZURE_VOICELIVE_API_KEY"]
79+
model = os.environ.get(
80+
"AZURE_VOICELIVE_MODEL", "gpt-realtime"
81+
)
82+
83+
credential = AzureKeyCredential(api_key)
84+
85+
with tracer.start_as_current_span(
86+
"telemetry-azure-monitor"
87+
):
88+
async with connect(
89+
endpoint=endpoint,
90+
credential=credential,
91+
model=model,
92+
) as connection:
93+
print(f"Connected to VoiceLive at {endpoint}")
94+
95+
session_config = RequestSession(
96+
modalities=[Modality.TEXT],
97+
instructions=(
98+
"You are a helpful assistant. "
99+
"Say hello briefly."
100+
),
101+
turn_detection=ServerVad(
102+
threshold=0.5,
103+
prefix_padding_ms=300,
104+
silence_duration_ms=500,
105+
),
106+
output_audio_format=OutputAudioFormat.PCM16,
107+
)
108+
await connection.session.update(
109+
session=session_config
110+
)
111+
print("Session configured.")
112+
113+
await connection.conversation.item.create(
114+
item=UserMessageItem(
115+
content=[
116+
InputTextContentPart(
117+
text="Hello, tell me a joke"
118+
)
119+
]
120+
)
121+
)
122+
await connection.response.create()
123+
print("User message sent.")
124+
125+
async for event in connection:
126+
event_type = getattr(event, "type", None)
127+
print(f"Received event: {event_type}")
128+
129+
if event_type == ServerEventType.RESPONSE_DONE:
130+
print("Response complete.")
131+
break
132+
133+
print("Connection closed.")
134+
135+
136+
if __name__ == "__main__":
137+
try:
138+
asyncio.run(main())
139+
finally:
140+
tracer_provider = trace.get_tracer_provider()
141+
if hasattr(tracer_provider, "force_flush"):
142+
tracer_provider.force_flush()
143+
if hasattr(tracer_provider, "shutdown"):
144+
tracer_provider.shutdown()
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# -------------------------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License.
4+
# -------------------------------------------------------------------------
5+
6+
"""
7+
FILE: telemetry-console.py
8+
9+
DESCRIPTION:
10+
This sample demonstrates how to enable OpenTelemetry tracing for the
11+
Azure AI Voice Live SDK with console output. All connection, send, and
12+
receive operations produce OpenTelemetry spans printed to stdout.
13+
14+
The telemetry setup code (marked with region tags) can be copied into
15+
any existing Voice Live application, such as the model quickstart or
16+
agent quickstart, to add tracing without changing application logic.
17+
18+
USAGE:
19+
python telemetry-console.py
20+
21+
Set the environment variables with your own values before running:
22+
1) AZURE_VOICELIVE_ENDPOINT - The Azure VoiceLive endpoint
23+
2) AZURE_VOICELIVE_API_KEY - The Azure VoiceLive API key
24+
25+
REQUIREMENTS:
26+
- azure-ai-voicelive
27+
- opentelemetry-sdk
28+
- azure-core-tracing-opentelemetry
29+
"""
30+
31+
import asyncio
32+
import os
33+
34+
# <enable_console_tracing>
35+
from azure.core.settings import settings
36+
37+
# Step 1: Tell azure-core to use OpenTelemetry for tracing.
38+
settings.tracing_implementation = "opentelemetry"
39+
40+
# Step 2: Configure a TracerProvider with a console exporter.
41+
from opentelemetry import trace
42+
from opentelemetry.sdk.trace import TracerProvider
43+
from opentelemetry.sdk.trace.export import (
44+
SimpleSpanProcessor,
45+
ConsoleSpanExporter,
46+
)
47+
48+
tracer_provider = TracerProvider()
49+
tracer_provider.add_span_processor(
50+
SimpleSpanProcessor(ConsoleSpanExporter())
51+
)
52+
trace.set_tracer_provider(tracer_provider)
53+
54+
# Step 3: Enable the VoiceLive instrumentor.
55+
from azure.ai.voicelive.telemetry import VoiceLiveInstrumentor
56+
57+
os.environ.setdefault(
58+
"AZURE_EXPERIMENTAL_ENABLE_GENAI_TRACING", "true"
59+
)
60+
VoiceLiveInstrumentor().instrument()
61+
# </enable_console_tracing>
62+
63+
from azure.core.credentials import AzureKeyCredential
64+
from azure.ai.voicelive.aio import connect
65+
from azure.ai.voicelive.models import (
66+
InputTextContentPart,
67+
Modality,
68+
OutputAudioFormat,
69+
RequestSession,
70+
ServerEventType,
71+
ServerVad,
72+
UserMessageItem,
73+
)
74+
75+
tracer = trace.get_tracer(__name__)
76+
77+
78+
async def main() -> None:
79+
endpoint = os.environ["AZURE_VOICELIVE_ENDPOINT"]
80+
api_key = os.environ["AZURE_VOICELIVE_API_KEY"]
81+
model = os.environ.get(
82+
"AZURE_VOICELIVE_MODEL", "gpt-realtime"
83+
)
84+
85+
credential = AzureKeyCredential(api_key)
86+
87+
with tracer.start_as_current_span("telemetry-console"):
88+
async with connect(
89+
endpoint=endpoint,
90+
credential=credential,
91+
model=model,
92+
) as connection:
93+
print(f"Connected to VoiceLive at {endpoint}")
94+
95+
session_config = RequestSession(
96+
modalities=[Modality.TEXT],
97+
instructions=(
98+
"You are a helpful assistant. "
99+
"Say hello briefly."
100+
),
101+
turn_detection=ServerVad(
102+
threshold=0.5,
103+
prefix_padding_ms=300,
104+
silence_duration_ms=500,
105+
),
106+
output_audio_format=OutputAudioFormat.PCM16,
107+
)
108+
await connection.session.update(
109+
session=session_config
110+
)
111+
print("Session configured.")
112+
113+
await connection.conversation.item.create(
114+
item=UserMessageItem(
115+
content=[
116+
InputTextContentPart(
117+
text="Hello, tell me a joke"
118+
)
119+
]
120+
)
121+
)
122+
await connection.response.create()
123+
print("User message sent.")
124+
125+
async for event in connection:
126+
event_type = getattr(event, "type", None)
127+
print(f"Received event: {event_type}")
128+
129+
if event_type == ServerEventType.RESPONSE_DONE:
130+
print("Response complete.")
131+
break
132+
133+
print("Connection closed.")
134+
135+
tracer_provider.force_flush()
136+
tracer_provider.shutdown()
137+
138+
139+
if __name__ == "__main__":
140+
asyncio.run(main())

0 commit comments

Comments
 (0)