glamorous-oil-12326
12/24/2025, 4:32 PMtall-airline-16756
12/24/2025, 4:32 PMtall-airline-16756
12/24/2025, 4:32 PMglamorous-oil-12326
12/24/2025, 4:35 PMtall-airline-16756
12/24/2025, 4:36 PMCompositeExporter or separate `SpanProcessor`s).
Would you like help reviewing your OTel SDK configuration (language/runtime) to verify exporters and sampling?
Sources: Streamline Troubleshooting with Agent Observability | Examples | livekit/livekit_composite | DeepWikiglamorous-oil-12326
12/24/2025, 4:37 PMconfigure_azure_monitor(
logger_name="xyz",
instrumentation_options={
"azure_sdk": {"enabled": False},
},
)
trace_provider = trace.get_tracer_provider()
# Replace Azure Monitor processor with filtered version
processors = trace_provider._active_span_processor._span_processors
new_processors = []
for processor in processors:
if hasattr(processor, "span_exporter"):
# Wrap the exporter and create new processor
original_exporter = processor.span_exporter
filtered_exporter = FilteringSpanExporter(original_exporter)
new_processor = BatchSpanProcessor(filtered_exporter)
new_processors.append(new_processor)
else:
new_processors.append(processor)
# Replace the processor list
trace_provider._active_span_processor._span_processors = tuple(new_processors)tall-airline-16756
12/24/2025, 4:37 PMFilteringSpanExporter and replaces the active span processors.
Quick review and suggestions:
• This approach is valid: wrapping the original exporter in a filtering exporter and then creating a new BatchSpanProcessor around it will cause only filtered spans to be sent to Azure Monitor. That will not create duplicates in LiveKit Agent Insights because LiveKit’s dashboard uses its own internal pipeline and does not re-ingest from your external exporters.
• Two things to double-check:
a. Make sure FilteringSpanExporter only drops spans you intend to filter (verify the filter logic matches the span attributes/names LiveKit emits). Otherwise you might inadvertently drop needed telemetry in your external backend.
b. Confirm processor replacement is happening early (before spans are produced). If spans are already created before you swap processors, those spans may be processed by the original processors.
• Minor robustness improvements you can consider:
◦ Avoid relying on private attributes (_active_span_processor._span_processors) if a public API is available in your SDK version. If you must access internals, add defensive checks (existence/type) and log warnings on unexpected structure changes.
◦ After replacement, validate by creating a test trace and confirming:
▪︎ LiveKit Agent Insights shows the trace (no duplication).
▪︎ Azure Monitor only receives the filtered spans.
If you’d like, tell me your runtime/language and I can suggest a safer replacement pattern or an example filter that matches LiveKit span names/attributes.glamorous-oil-12326
12/24/2025, 4:41 PMbase_logger = logging.getLogger("xyz")
class BaseAgent(Agent):
async def on_enter(self) -> None:
self.logger = base_loggertall-airline-16756
12/24/2025, 4:41 PMbase_logger) assigned to each agent instance in on_enter. That’s fine; a few concise notes to ensure you don’t get duplicate entries in your external exporters and that LiveKit Agent Insights stays unaffected:
• LiveKit Agent Insights won’t show duplicates from your exporters; it uses LiveKit’s internal pipeline.
• For your Python logging setup, avoid duplicate export to external backends by ensuring you do not attach multiple handlers that forward the same spans/logs. Check:
◦ Handlers: Attach only the desired OTLP/OTel handler once to base_logger (or root logger), not per-agent instance.
◦ Propagation: If you set base_logger.propagate = True and also add handlers on the root logger, you may get duplicate exports. Set propagate = False on base_logger if you want handler behavior scoped to that logger.
◦ Handler-level filtering: Use handler filters or your FilteringSpanExporter to drop spans/logs you don’t want sent to a particular exporter.
Quick checklist to validate your current runtime behavior:
1. Verify you add OTLP/azure handlers once (startup), not inside on_enter.
2. Confirm base_logger.handlers length is what you expect and base_logger.propagate is set intentionally.
3. Create a test trace/log and confirm: LiveKit dashboard shows the session, and each external backend receives only the intended spans/logs.
If you want, tell me which OTel log/span handler you attach (library/runtime) and I’ll provide exact code to attach it once and set `propagate`/filters correctly.