Trace Lifecycle
This page covers the complete trace lifecycle, including the race condition problem and the hybrid linking solution.
The Complete Flow
Timeline for Fast Test (< 5 seconds)
Key Phases
The Race Condition Problem
The Issue
OpenTelemetry’s BatchSpanProcessor batches spans and exports every 5 seconds. This creates unpredictable timing:
Fast Tests (< 5s): Test result created BEFORE spans exported
Slow Tests (> 5s): Spans exported BEFORE test result created
The Solution: Hybrid Linking
Link traces at TWO strategic points to handle both scenarios:
Linking Points
Point #1: After Test Result Creation
Location: tasks/execution/executors/results.py → link_traces_for_test_result()
Purpose: Catch traces that arrived BEFORE test result (slow tests)
Point #2: After Span Ingestion
Location: tasks/telemetry/post_ingest.py → link_traces_for_incoming_batch(), run inside the async post_ingest_link task dispatched by the ingestion endpoint
Purpose: Catch traces that arrived AFTER test result (fast tests)
Idempotency
Both linking points call crud.update_traces_with_test_result_id(), which only updates traces that aren’t linked yet:
Safe to call multiple times:
- First call: Updates N traces
- Second call: Updates 0 traces (already linked)
Result: 100% linking success rate regardless of test duration.
Test Execution Context
Context passed from test executor → SDK → spans:
This context is stored as span attributes:
Timing Summary
Critical Timing Points
| Point | Timing | Impact |
|---|---|---|
| BatchSpanProcessor delay | 5 seconds | Largest delay, unavoidable |
| Test execution | Variable | Determines which scenario |
| Span ingestion | ~10-20ms | Fast |
| Linking + enrichment | ~50-100ms | Background (Celery) |
| Query | ~10ms | Cached |
Why 5 Seconds?
The 5-second batch delay is a trade-off:
| Shorter Delay | Longer Delay |
|---|---|
| More HTTP requests | Fewer HTTP requests |
| Lower latency | Higher latency |
| Higher network overhead | Lower network overhead |
| Better real-time visibility | Batching efficiency |
OpenTelemetry’s default of 5 seconds optimizes for production efficiency over real-time visibility.
Cannot Avoid: The 5-second delay is fundamental to OpenTelemetry’s batch processing design. The hybrid linking strategy is the mitigation.
Error Handling
Broker Unreachable at Dispatch
Detection: post_ingest_link.delay(...) raises a broker error (Redis/kombu unreachable)
Handling: Caught and logged as a warning; ingestion still returns 200
Impact: Linking and enrichment are skipped for that batch — this is fire-and-forget, not retried by the ingestion request itself
Task Failure After Dispatch
Handling: post_ingest_link retries up to 3 times (max_retries=3, 30s delay) on uncaught exceptions
Impact: Transient failures (e.g. a momentarily locked row) self-heal; exhausted retries are logged
Database Failure
Handling: Return 500 error
Impact: Spans lost (SDK retries the export)
Linking Failure
Handling: Log error, don’t fail the task
Impact: Traces stored but not linked
Enrichment Failure
Handling: Skip problematic spans
Impact: Partial enrichment (other spans still enriched)
Debugging Guide
Traces Not Appearing?
- Check SDK export: Is
BatchSpanProcessorconfigured? - Check backend: Is
/telemetry/tracesreceiving requests? - Check database: Are spans stored in the
tracetable? - Wait 5 seconds for batching delay
Traces Not Linked to Test Results?
- Check test context: Are spans created with
rhesis.test.*attributes? - Check Celery: Is
post_ingest_linkrunning (broker reachable)? - Check database: Is
test_result_idNULL or set?
Enrichment Not Happening?
- Check workers: Are Celery workers running?
- Check logs: Did
post_ingest_linkdispatch successfully? - Check database: Is
enriched_datapopulated andprocessed_atset?