How does livekit agent insights work if we have mu...
# ask-ai
g
How does livekit agent insights work if we have multiple otel trace exporters
t
Thanks for reaching out, Aumesh. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m responding to your question about how LiveKit Agent Insights behaves when you have multiple OpenTelemetry (OTel) trace exporters configured. • LiveKit Agent emits spans to the OpenTelemetry Tracer the agent uses. • If you register multiple exporters in your OTel SDK (for example via a CompositeExporter or multiple SpanProcessors), those exporters will receive the spans the agent emits. How traces are duplicated, merged, or forwarded depends on your OTel SDK configuration — not LiveKit. • LiveKit’s Agent Insights dashboard uses LiveKit’s own observability sink for storage and visualization and will still capture the same turn-by-turn traces, logs, and session data when enabled. • In short: LiveKit will produce the spans; any additional exporters you add via OTel will receive copies if they’re registered. LiveKit does not coordinate exporter behavior beyond emitting the spans into the OTel pipeline. Would you like guidance on configuring multiple exporters in your OpenTelemetry SDK (language/runtime), or on ensuring LiveKit’s dashboard tracing and your external exporters contain the same spans? Sources: https://blog.livekit.io/streamline-troubleshooting-with-agent-observability/#/portal/signup| | Agents (Node.js) | livekit/livekit_composite | DeepWiki | Streamline Troubleshooting with Agent Observability | https://blog.livekit.io/streamline-troubleshooting-with-agent-observability/#/portal|
g
I have multiple exporters and I want to make sure livekit doesn't show duplicate logs
t
Thanks — addressing your concern about duplicates in Agent Insights when you have multiple OTel exporters configured. • LiveKit’s Agent Insights uses LiveKit’s internal observability pipeline for traces, logs, and transcripts. External OTLP exporters you register in your OpenTelemetry SDK send telemetry to their own backends and are not re-ingested into LiveKit’s dashboard. • Therefore multiple exporters will not cause duplicate logs or traces to appear in LiveKit’s Agent Insights. • To avoid duplicate data in your external backends, ensure each exporter is configured properly (unique endpoints, correct sampling, and intended span processors like a
CompositeExporter
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 | DeepWiki
g
yes this is what I currently have:
Copy code
configure_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)
t
Thanks — I’m looking at the snippet you shared that wraps Azure Monitor’s exporter with
FilteringSpanExporter
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.
g
In my agents do:
Copy code
base_logger = logging.getLogger("xyz")

class BaseAgent(Agent):
   async def on_enter(self) -> None:
       self.logger = base_logger
t
Thanks — you're using a shared Python logger (
base_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.