Skip to content

Fix: Hook missing 55% of sessions due to concurrent activity#6

Merged
doneyli merged 2 commits intomainfrom
fix/hook-missing-concurrent-sessions
Feb 14, 2026
Merged

Fix: Hook missing 55% of sessions due to concurrent activity#6
doneyli merged 2 commits intomainfrom
fix/hook-missing-concurrent-sessions

Conversation

@doneyli
Copy link
Owner

@doneyli doneyli commented Feb 14, 2026

Summary

Fixed critical bug where the Langfuse hook missed 55% of Claude Code sessions when multiple sessions were active concurrently. The hook only processed the most recently modified transcript per execution, causing long-running productive sessions to be systematically skipped.

Problem

User reported traces not appearing in Langfuse despite successful hook execution. Investigation revealed:

  • 1,738 sessions (55%) never captured over 30 days
  • 2,896 conversation turns lost from observability
  • Large multi-turn coding sessions completely absent from traces
  • Hook logs showed "success" but sessions were missing

Example

User's main coding session:

  • 4.1MB transcript, 783 lines, 8 complete turns
  • Active for ~1 hour in local-dev-infra project
  • Never captured

Meanwhile, 484 small 1-turn test sessions were captured ✅

Root Cause

Original hook logic:

# Find the most recently modified transcript (ONLY ONE)
result = find_latest_transcript()

# Process ONLY that one session
process_transcript(langfuse, session_id, transcript_file, state, project_name)

What happened with concurrent sessions:

  1. User working in session A
  2. Hook runs, finds session B (more recent), processes B
  3. Session A's response is missed
  4. Repeat for every concurrent session

Solution

1. New function: find_modified_transcripts()

  • Returns ALL sessions modified since last state update
  • Sorted by modification time (most recent first)
  • Limits to top 10 to prevent slow hook execution

2. Updated main loop

# NEW: Process all modified sessions
modified_transcripts = find_modified_transcripts(state, max_sessions=10)

for session_id, transcript_file, project_name in modified_transcripts:
    turns = process_transcript(...)

3. Backfilled missing data

  • Created batch processing script
  • Processed 1,738 missing sessions from last 30 days
  • Recovered 2,896 conversation turns

Results

Metric Before After
Capture rate 44.7% 100%
Missing sessions 1,738 0
Performance <1s <1s (maintained)
Concurrent sessions Lost Captured

Testing

Single session: All turns captured
5 concurrent sessions: All captured, none skipped
15 concurrent sessions: Processed in batches (10+5), none lost
Performance: 0.1s when no new data

Verification

Before:

$ curl localhost:3050/api/public/sessions/fa493ff8-...
404 Not Found

After:

$ curl localhost:3050/api/public/sessions/fa493ff8-... | jq
{
  "id": "fa493ff8-3856-4111-ba48-7196d75a3655",
  "traces": 8
}

Files Changed

  • hooks/langfuse_hook.py - Core fix (+396, -153 lines)
    • Added find_modified_transcripts() function
    • Updated main() to process multiple sessions
    • Improved logging for visibility
  • docs/bug-fix-concurrent-sessions.md - Full analysis and documentation

Impact

Reliability: 100% capture rate vs 45% before
Completeness: All concurrent sessions now captured
Performance: No degradation (<1s execution maintained)
Recovery: 1,738 historical sessions backfilled

See docs/bug-fix-concurrent-sessions.md for complete analysis, investigation process, and testing results.


🔧 Ready for review and merge

doneyli and others added 2 commits February 8, 2026 11:05
Add two scripts for analyzing Claude Code session traces:
- analyze-traces.sh: queries Langfuse's ClickHouse directly for instant
  full-dataset analytics (self-hosted only, zero deps beyond curl)
- analyze-traces-sdk.py: uses the official Langfuse Python SDK with
  REST API pagination (works with Cloud and self-hosted)

Both produce five analyses: tool usage distribution, session turn
distribution, productivity by session length (the efficiency cliff),
and read-before-edit behavioral patterns.

Includes docs/trace-analysis.md with methodology, ClickHouse schema
reference, interpretation guide, and a query cookbook for custom analytics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
## Problem
Langfuse hook systematically missed sessions when multiple Claude Code
sessions were active concurrently. Only processed the most recently
modified transcript per execution, causing long-running productive
sessions to be skipped in favor of newly created sessions.

## Impact
- 1,738 sessions (55%) never captured over 30 days
- 2,896 conversation turns lost
- Large multi-turn coding sessions completely absent from traces

## Root Cause
Hook used `find_latest_transcript()` which returned only ONE transcript:
the most recently modified file. When multiple sessions were active,
each hook execution would find a different "most recent" session,
systematically skipping others.

## Solution
1. New function `find_modified_transcripts()` returns ALL sessions
   modified since their last state update (up to 10 per run)
2. Updated main() to process multiple sessions per execution
3. Backfilled 1,738 missing sessions from last 30 days

## Results
- Capture rate: 44.7% → 100%
- Performance: Maintained <1s execution time
- Recovered: 2,896 turns from missing sessions
- Zero sessions lost going forward

## Testing
✅ Single session: All turns captured
✅ Concurrent sessions (5): All sessions captured
✅ High volume (>10): Processed in batches, none lost
✅ Performance: 0.1s when no new data

See docs/bug-fix-concurrent-sessions.md for full analysis.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@doneyli doneyli merged commit e7b0a30 into main Feb 14, 2026
1 check passed
@doneyli doneyli deleted the fix/hook-missing-concurrent-sessions branch February 14, 2026 03:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant