Issue summary
Add retrieval tracing to the Drupal Langfuse module by modeling the RAG retrieval workflow as
nested span observations inside the existing per-request trace (nested only if needed, it can also be just 1 span).
Problem/Motivation
- Today, the module creates one
traceper Drupal request and appends LLM-related observations (generation,event). - Retrieval for RAG (vector store + context prep) is not captured. If we were to use a single
eventwe'd lose timing and structure. - We want end-to-end observability of retrieval latency, inputs, filters, candidates, and context encoding stats.
Proposed resolution
- Represent retrieval as a
spannamedrag.retrieve. - Potentially - within that span, create child
spans for each step:vector-store-query- (optional as already happening)
context-encoding - (optional)
rerank
- No breaking changes: this only adds spans; existing trace lifecycle and bulk-send remain unchanged.
Recommended metadata on retrieval spans
query,normalizedQuery,topK,filtersvectorStore(provider/index/namespace),similarityMetriccandidates(IDs + scores; redact or hash content when needed)rerankerModel(if used), per-steplatencyMs,usedContextTokenCount
| Comment | File | Size | Author |
|---|---|---|---|
| #19 | Screenshot from 2025-12-01 23-40-27.png | 36.99 KB | nikro |
Issue fork langfuse-3557948
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #8
nikro commentedAlright pushed some stuff straight into the main for now:
+ Add trace manager service - Core service and interface
+ Register trace manager service - Service definition
+ Use trace manager in AI subscriber - Refactored to use centralized trace logic
+ Register tool and search span subscribers - Service registrations
+ Track AI agent tool executions - Tool span subscriber
+ Track Search API queries - Search span subscriber for RAG
TLDR - now we can hierarchically track any tool-call and also we bolted in a specialized logic for ai_search_block (which doesn't use any tool) - basically if the ai_search query is performed, we create also a span for it.
Comment #18
nikro commentedMore changes - as previous ones ignored some things:
I had to split the ai logging sub-module into 3 separate sub-modules: general ai, ai agents and search - because they actually depend on separate module:
This structure keeps AI Agents and AI Search logging optional submodules (wiring only when those contrib modules are enabled) while preserving a single runner-context system the rest of the code can rely on.
Comment #19
nikro commentedComment #20
nikro commentedAfter anlyzing this live with Frederik Wouters, we discovered that it misbehaves when used under Deepchat.
More fixes done:
Termination Flow Consolidation
Removed duplicate
KernelEvents::TERMINATEhandler from langfuse_ai_logging. The root LangfuseSyncSubscriber in web/modules/custom/langfuse/src/EventSubscriber/LangfuseSyncSubscriber.php now exclusively finalizes traces, updates metadata (final timestamp/output), clears the active trace, and runs syncTraces().DeepChat-Friendly Trace Management
Comment #29
nikro commentedSo last updates were as following:
- Kept unified terminate subscriber.
- But, removed the deepchat attempted integration - as it requires way more changes than I thought - especially SDK changes. I'll leave it for now as a separate ticket.
Comment #30
wouters_f commentedComment #31
nikro commentedDone, made a new alpha1 release with this in it.
Thanks!