Sitelet https://github.com/getsentry/sentry-elixir/pull/1163
Skip to content

fix(tracing): report spans that outlive their sent parent - #1163

Merged
solnic merged 1 commit into
masterfrom
fix/otel-orphan-span-promotion
Aug 20, 2026
Merged

solnic merged 1 commit into
masterfrom
fix/otel-orphan-span-promotion

Conversation

@solnic

@solnic solnic commented Aug 7, 2026 •

Copy link
Copy Markdown
Collaborator

A span that outlives its transaction root (ie async work via Tasks/Broadway/Oban continuing a trace after the root was reported) was either corrupted or lost:

  • If it was still running when the root ended, it was serialized into the root transaction with "timestamp": null — Relay patches that into a zero-duration span with a bogus deadline_exceeded status (first screenshot; the span actually ran for 500ms and succeeded).
  • Once it finished, it was silently dropped.

Unfinished children are now excluded from the transaction payload, and sent transaction roots leave a short-lived marker in span storage. A span ending with a marked parent is promoted to a follow-up transaction in the same trace - same trace_id, parent_span_id pointing at the sent root, tagged sentry.parent_span_already_sent: true.

Before

image image

After

image

Fixes #1011

@solnic solnic changed the title fix(tracing): report spans that outlive their sent parent (#1011) fix(tracing): report spans that outlive their sent parent Aug 7, 2026
@solnic
solnic marked this pull request as ready for review August 7, 2026 13:49
Comment thread lib/sentry/opentelemetry/span_processor.ex Outdated
Comment thread lib/sentry/opentelemetry/span_processor.ex
Comment thread lib/sentry/opentelemetry/span_processor.ex Outdated
Comment thread lib/sentry/opentelemetry/span_processor.ex
@solnic
solnic force-pushed the fix/otel-orphan-span-promotion branch from b822b9b to 203b3c5 Compare August 7, 2026 14:44
Comment thread lib/sentry/opentelemetry/span_processor.ex Outdated
Comment thread lib/sentry/opentelemetry/span_processor.ex
@solnic
solnic marked this pull request as draft August 13, 2026 09:04
@solnic
solnic force-pushed the fix/otel-orphan-span-promotion branch from 203b3c5 to b9a2229 Compare August 13, 2026 09:09
@solnic
solnic marked this pull request as ready for review August 13, 2026 11:58
Comment thread lib/sentry/opentelemetry/span_storage.ex
Comment thread lib/sentry/opentelemetry/span_processor.ex
@solnic
solnic force-pushed the fix/otel-orphan-span-promotion branch from c15942f to 6863a94 Compare August 20, 2026 11:07
defp start_report_task(nil), do: :ok

defp start_report_task(test_process) do
notify = String.to_existing_atom(test_process)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The call to String.to_existing_atom/1 with an unvalidated URL parameter test_process can cause the LiveView to crash if the atom does not exist.
Severity: LOW

Suggested Fix

Although this is in a test application, consider using String.to_atom/1 within a try/rescue block to handle cases where the atom does not exist, or switch to String.to_atom/1 if atom creation is acceptable in this context. Alternatively, add a check to validate the input before conversion.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location:
test_integrations/phoenix_app/lib/phoenix_app_web/live/async_report_live.ex#L22

Potential issue: The function `start_report_task` receives a `test_process` string from
a URL query parameter and passes it directly to `String.to_existing_atom/1`. There is no
validation to ensure the corresponding atom exists in the atom table. If a request is
made to the `/async-report` endpoint with a `test_process` parameter that does not
correspond to a pre-existing atom, the call will raise an `ArgumentError`, causing the
LiveView process to crash during the `mount` phase.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6863a94. Configure here.

:ets.delete(table_name, key)
end

remove_child_spans(span_data.span_id, table_name: table_name)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finished spans dropped during send

High Severity

Cleanup after a send deletes every descendant that now has an end_time, not only spans that were in the payload and marked sent. Work that finishes after collection—especially nested spans whose in-progress parent is not marked—can be removed after on_end already decided to wait, so they are never reported.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6863a94. Configure here.

# records are removed below, later spans can never be attached to this
# transaction either way.
sent_span_ids = [span_record.span_id | Enum.map(child_span_records, & &1.span_id)]
:ok = SpanStorage.mark_spans_sent(sent_span_ids)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-ups can duplicate sent spans

Medium Severity

Follow-up transactions include every stored descendant with an end_time, without skipping IDs already passed to mark_spans_sent. If an in-progress parent ends while the ancestor send is still in flight, cleanup has not run yet, so spans already in the original payload can be sent again on the follow-up.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6863a94. Configure here.

@solnic
solnic merged commit e7534b5 into master Aug 20, 2026
16 checks passed
@solnic
solnic deleted the fix/otel-orphan-span-promotion branch August 20, 2026 11:11
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.

SpanProcessor drops child spans that start after the root ends

2 participants