feat(traces): span handles - #951
Open
turnipdabeets wants to merge 1 commit into
Open
turnipdabeets wants to merge 1 commit into
turnipdabeets wants to merge 1 commit into
Conversation
Contributor
posthog-python Compliance ReportDate: 2026-09-15 14:30:19 UTC ✅ All Tests Passed!111/111 tests passed Capture_V1 Tests✅ 94/94 tests passed View Details
Feature_Flags Tests✅ 17/17 tests passed View Details
|
Contributor
Prompt To Fix All With AI### Issue 1
posthog/tracing/_span.py:333-339
**Shared spans end early**
The implementation supports entering one span from several threads or tasks, but each `__exit__` ends that shared span. If one block exits while another is still active, later events and exceptions from the remaining block are ignored, producing an incomplete trace. Track active scope ownership and end only after the final scope exits, or explicitly reject concurrent entry.
### Issue 2
posthog/tracing/_span.py:302-305
**Concurrent end exports duplicates**
`end()` checks and sets `_ended` without synchronization. Concurrent callers can both pass the check and invoke `_on_end`, violating the documented idempotency contract and exporting duplicate span records. Protect the check-and-set transition with a lock.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "feat(traces): span handles" | Re-trigger Greptile |
This was referenced Sep 14, 2026
turnipdabeets
force-pushed
the
traces/03-span-handles
branch
from
September 14, 2026 22:58
8848500 to
f506a3e
Compare
turnipdabeets
added this pull request to stack #958
September 14, 2026 23:03
turnipdabeets
force-pushed
the
traces/03-span-handles
branch
from
September 15, 2026 14:09
f506a3e to
af28b90
Compare
turnipdabeets
force-pushed
the
traces/03-span-handles
branch
from
September 15, 2026 14:17
af28b90 to
ece21ff
Compare
Adds the Span interface (posthog.tracing.span, the only public module in the package) and its handles. The recording span keeps its timing on a monotonic clock, with children of a local parent on the root's clock basis so they stay inside it; end() is idempotent and hands the pipeline one record. The no-op handle is returned when tracing cannot run, and the pass-through handle echoes an inbound traceparent and tracestate so a service with tracing off still forwards the trace, including from spans nested inside it. Entering a handle makes it the active span for the block and records an exception raised out of it. Not reachable from the client. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TkZAsCciW4PV8ZdcCHmAbA
turnipdabeets
force-pushed
the
traces/03-span-handles
branch
from
September 15, 2026 14:25
ece21ff to
cf74b0b
Compare
turnipdabeets
marked this pull request as ready for review
September 15, 2026 15:12
Contributor
|
Reviews (2): Last reviewed commit: "feat(traces): span handles" | Re-trigger Greptile |
dustinbyrne
approved these changes
Sep 15, 2026
dustinbyrne
left a comment
Contributor
There was a problem hiding this comment.
Reviewed cf74b0b17bcf0e496fd4f35b9a63837f4e6a7cf2 via source inspection and existing CI. No issues found in this staged span-handle slice. Approval covers this slice; #950 precedes it in the stack.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
💡 Motivation and Context
Adds the
Spaninterface (posthog.tracing.span, the only public module in the package) and its three handles:end()is idempotent and hands the pipeline one record.traceparent/tracestateso a service with tracing off still forwards the trace, including from spans nested inside it.Entering a handle makes it the active span for the block and records an exception raised out of it. Not reachable from the client yet.
Stack (PR 3 of 9, based on
traces/02-otlp-encoding):traces/01-ids-traceparenttraces/02-otlp-encodingtraces/03-span-handles← this PRtraces/04-transporttraces/05-pipelinetraces/06-exporttraces/07-span-limitstraces/08-before-span-sendtraces/09-client-wiring💚 How did you test it?
Unit tests in
posthog/test/tracing/test_span.pycover timing, idempotentend(), active-span scoping, exception recording and pass-through propagation.📝 Checklist
If releasing new changes
sampo addto generate a changeset file🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Implemented with Claude Code (Claude Opus 5) against the traces spec, one commit per slice so each PR reviews on its own. Rebased onto main and opened as a stacked draft in a later Claude Code session (Claude Fable 5.1).
🤖 Generated with Claude Code
https://claude.ai/code/session_012o7CtHLfcypjmXL7g9ZGRC