You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
| Google ADK | OpenTelemetry (via OpenInference) |`instrument_google_adk()`| OTLP |`deepeval/integrations/google_adk/`|
21
-
| Pydantic AI | OpenTelemetry |`ConfidentInstrumentationSettings(...)`| OTLP |`deepeval/integrations/pydantic_ai/`|
9
+
The "Mixes with `@observe`?" column tracks whether the integration's spans flow into deepeval's native trace context — i.e. whether `@observe`, `with trace(...)`, `update_current_trace(...)`, and `update_current_span(...)` work transparently for that integration's spans, anywhere in the call stack (Langfuse-style).
10
+
11
+
-**Good** — trace metadata flows from `update_current_trace(...)`, span metadata flows from `update_current_span(...)`, and spans land in `trace_manager` so pytest tracing evals + `evals_iterator` work. Single REST POST per trace.
12
+
-**Bad** — only the trace UUID syncs between transports. Per-call metadata is locked at `instrument_*()` time; `update_current_span(...)` from inside a tool / callback is a no-op. Dual-posts (REST from `@observe` + OTLP from the integration) reconciled server-side by UUID.
13
+
14
+
| Integration | Mode | Entry point | Transport | Mixes with `@observe`? | Source |
| AgentCore | OpenTelemetry |`instrument_agentcore()`| OTLP | Bad — needs the Pydantic AI POC pattern applied[^poc]|`deepeval/integrations/agentcore/`|
24
+
| Google ADK | OpenTelemetry (via OpenInference) |`instrument_google_adk()`| OTLP | Bad — needs the Pydantic AI POC pattern applied[^poc]|`deepeval/integrations/google_adk/`|
25
+
|**Pydantic AI**|**OpenTelemetry**|**`ConfidentInstrumentationSettings(...)`**|**REST when context active, OTLP otherwise**|**Good (POC)**|`deepeval/integrations/pydantic_ai/`|
26
+
27
+
[^poc]: The Pydantic AI integration is the reference for OTel-mode "Good" behavior. Its `SpanInterceptor` reads trace-level metadata from `current_trace_context` per span (instead of baking it at `instrument_*()` time) and pushes a `BaseSpan` placeholder onto `current_span_context` for each OTel span's lifetime so `update_current_span(...)` from anywhere lands in `confident.span.*` attributes at `on_end`. The `ContextAwareSpanProcessor` (`deepeval/tracing/otel/context_aware_processor.py`) routes spans to REST when a deepeval trace context is active or an evaluation is running, OTLP otherwise. Apply the same pattern to `agentcore/` and `openinference/` (which Google ADK delegates to) to flip those rows to Good.
When an OTel-mode integration runs inside an active `@observe` / `with trace(...)` context, the OTel span interceptor synchronizes the trace UUID (`current_trace_context.uuid = OTel trace_id`) so both transports land on the same trace server-side. This means a mixed trace currently produces one REST POST + one or more OTLP POSTs that the backend reconciles by UUID. See internal notes for the proposed single-transport refactor that would route OTel spans through `ConfidentSpanExporter` (REST) when a deepeval trace is active.
57
+
When an OTel-mode integration runs inside an active `@observe` / `with trace(...)` context, the OTel span interceptor synchronizes the trace UUID (`current_trace_context.uuid = OTel trace_id`) so both transports land on the same trace server-side.
58
+
59
+
For integrations marked **Good** above, `ContextAwareSpanProcessor` automatically routes the OTel spans through `ConfidentSpanExporter` (REST) when a deepeval trace context is active or an evaluation is running — so a mixed trace produces a single REST POST and `update_current_trace(...)` / `update_current_span(...)` from anywhere in the call stack land on the right span. Pydantic AI is the reference implementation; apply the same pattern (see footnote in the matrix) to migrate AgentCore and OpenInference (Google ADK).
60
+
61
+
For integrations marked **Bad**, the trace UUID syncs but per-call metadata is locked at `instrument_*()` time and the integration produces dual posts (one REST POST from the `@observe` trace flush + one or more OTLP POSTs from the integration's spans) that the backend reconciles by UUID.
0 commit comments