Documentation Index
Fetch the complete documentation index at: https://braintrust.dev/docs/llms.txt
Use this file to discover all available pages before exploring further.
Summary
Configure tracing and observability for OpenAI Realtime API WebSocket sessions using Braintrust’s OpenTelemetry integration. This approach allows you to log session-based traces, capture event metadata, and maintain full control over event schemas without relying on the Braintrust proxy.
Configuration Steps
Set up OpenTelemetry to send traces directly to Braintrust’s OTEL endpoint with proper authentication and project context.
OTEL_EXPORTER_OTLP_ENDPOINT=https://api.braintrust.dev/otel
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer , x-bt-parent=project_name:"
Step 2: Initialize session-based tracing
Create a root span for the entire WebSocket session to track the long-lived connection and session-level metadata.
// Java example using OpenTelemetry
Span sessionSpan = tracer.spanBuilder("voice_interaction")
.setAttribute("braintrust.input", userSpeechText)
.setAttribute("braintrust.metadata", JSON.toJson(Map.of(
"user_id", "user-123",
"session_id", "session-456",
"audio_duration_ms", 2500
)))
.setAttribute("braintrust.tags", JSON.toJson(List.of("voice", "realtime-api")))
.startSpan();
Step 3: Log individual events as nested spans
Create child spans for specific WebSocket events like RAG retrieval and LLM generation to maintain granular observability.
// Nested span for RAG retrieval
Span retrievalSpan = tracer.spanBuilder("rag_retrieval")
.setParent(Context.current().with(sessionSpan))
.setAttribute("braintrust.metadata", JSON.toJson(Map.of(
"documents_considered", List.of(
Map.of("id", "kb_123", "title", "Product FAQ", "relevance", 0.92),
Map.of("id", "kb_456", "title", "User Guide", "relevance", 0.78)
),
"retrieval_method", "semantic_search"
)))
.startSpan();
Step 4: Capture conversation data in root span
Store complete conversation context and metadata in the root span to support custom scorers and analysis tools.
// Store conversation data for scoring
sessionSpan.setAttribute("braintrust.output", llmResponse);
sessionSpan.setAttribute("braintrust.metadata", JSON.toJson(Map.of(
"conversation_history", conversationMessages,
"rag_documents", retrievedDocuments,
"total_tokens", tokenCount,
"session_duration_ms", sessionDuration
)));
Step 5: Close spans and flush data
Properly end spans when events complete and ensure data is sent to Braintrust.
// End nested spans first
retrievalSpan.end();
// End session span when WebSocket closes
sessionSpan.setAttribute("braintrust.metrics", JSON.toJson(Map.of(
"total_messages", messageCount,
"total_duration_ms", sessionDuration
)));
sessionSpan.end();
// Flush telemetry data
OpenTelemetry.getGlobalOpenTelemetry().shutdown();
Helpful Links