Skip to content

Share parent's PropagationTags for local child spans#11701

Draft
dougqh wants to merge 2 commits into
masterfrom
dougqh/ptags-per-segment
Draft

Share parent's PropagationTags for local child spans#11701
dougqh wants to merge 2 commits into
masterfrom
dougqh/ptags-per-segment

Conversation

@dougqh

@dougqh dougqh commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

What This Does

Local child spans now share the parent's (trace-level) PropagationTags instead of each allocating a fresh empty(). Collapses N+1 → 1 PropagationTags per N-span trace.

Motivation

CoreTracer span-build allocated propagationTagsFactory.empty() for every local child span (the common in-process case); only the distributed ExtractedContext path reused the parent's. A non-root child's own PropagationTags, however, is never readDDSpanContext.getPropagationTags() routes to the root (getRootSpanContextOrThis().propagationTags). So the per-span empty() was pure allocation waste.

Additional Notes

Correctness — gated by a characterization test

First commit adds PropagationTagsChildSpanTest, which pins the load-bearing behavior: a non-root (local child) span still carries the inbound distributed _dd.p.* tags on injection. Both tests pass, confirming this is pure allocation waste, not a latent correctness bug. The test is the gate + safety net for the change.

Safety

  • The ctor's updateTraceIdHighOrderBits stamp is guard-idempotent (if (traceIdHighOrderBits != highOrderBits)) and a no-op on the already-stamped shared root instance (same trace ⇒ same high-order bits).
  • The full dd-trace-core propagation + span-build suite passes (W3C/Datadog extractors+injectors, W3CPropagationTags, OPM round-trip, OrgGuard, CoreSpanBuilderTest, DDSpanContextTest) — 0 failures.

Misc

The lastParentId/OPM inject-time mutation race (a transient per-injection value parked in the shared object) is pre-existing — injection already routes to the root's shared instance via getPropagationTags() — so it is a separate concurrency concern, not introduced or worsened by this change. Tracked for a follow-up.

🤖 Generated with Claude Code

dougqh and others added 2 commits June 22, 2026 17:22
CoreTracer span-build allocates a fresh propagationTagsFactory.empty()
per local child span; only the distributed ExtractedContext path reuses
the parent's. Before optimizing that per-span allocation away, this test
pins the load-bearing behavior: that a non-root (local child) span still
carries the inbound distributed _dd.p.* tags when it injects.

Verdict (both tests pass): it does. DDSpanContext.getPropagationTags()
routes to the root (getRootSpanContextOrThis), so a non-root child's own
propagationTags field is never read for injection. The per-span empty()
is pure allocation waste, not a latent correctness bug.

This test is the gate + safety net for the planned "share the parent's
PropagationTags for local children" allocation fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CoreTracer span-build allocated a fresh propagationTagsFactory.empty()
for every local child span, reused from the parent only on the
distributed ExtractedContext path — N+1 PropagationTags per N-span
trace, N of them needless empties.

A non-root child's own PropagationTags is never read for injection:
DDSpanContext.getPropagationTags() routes to the root
(getRootSpanContextOrThis), confirmed by PropagationTagsChildSpanTest
(inbound _dd.p.* survive child injection). So local children can share
the parent's (trace-level) instance instead of allocating their own,
collapsing N+1 -> 1 per trace.

Safe: the ctor's updateTraceIdHighOrderBits stamp is guard-idempotent
and a no-op on the already-stamped shared root instance (same trace =>
same high-order bits). Full dd-trace-core propagation + span-build
suite passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dougqh dougqh changed the title Characterize non-root span _dd.p.* propagation (gate for PTags per-span alloc fix) Share parent's PropagationTags for local child spans Jun 22, 2026
@datadog-prod-us1-4

datadog-prod-us1-4 Bot commented Jun 22, 2026

Copy link
Copy Markdown

Pipelines

Fix all issues with BitsAI

⚠️ Warnings

🚦 4 Pipeline jobs failed

DataDog/apm-reliability/dd-trace-java | jetty-app.amd64.DOC: [public.ecr.aws/docker/library/oraclelinux:8.10, linux/amd64, 24.0.1-zulu]   View in Datadog   GitLab

Run system tests | main / parametric / parametric (1)   View in Datadog   GitHub Actions

DataDog/apm-reliability/dd-trace-java | test_inst_latest: [17, 1/6]   View in Datadog   GitLab

View all 4 failed jobs.

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: dbbd71e | Docs | Datadog PR Page | Give us feedback!

@dd-octo-sts

dd-octo-sts Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

🟢 Java Benchmark SLOs — All performance SLOs passed

Suite Status
Startup 🟢 pass

SLO thresholds are defined here based on automatically generated metrics. A warning is raised when results are within 5% of the threshold.

PR vs. master results
Scenario Candidate master Δ (95% CI of mean)
startup:insecure-bank:iast:Agent 14.00 s 13.84 s [+0.3%; +1.9%] (maybe worse)
startup:insecure-bank:tracing:Agent 12.87 s 12.92 s [-1.1%; +0.3%] (no difference)
startup:petclinic:appsec:Agent 16.88 s 16.69 s [+0.2%; +2.1%] (maybe worse)
startup:petclinic:iast:Agent 16.80 s 16.48 s [-2.4%; +6.4%] (no difference)
startup:petclinic:profiling:Agent 16.76 s 16.93 s [-2.0%; +0.0%] (no difference)
startup:petclinic:sca:Agent 16.84 s 16.82 s [-0.7%; +0.9%] (no difference)
startup:petclinic:tracing:Agent 15.48 s 16.06 s [-7.6%; +0.5%] (no difference)

Commit: dbbd71e7 · CI Pipeline · Benchmarking Platform UI


Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion.

ciVisibilityContextData = null;
}
propagationTags = tracer.propagationTagsFactory.empty();
// Local child: share the parent's (trace-level) PropagationTags instead of allocating a

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

To Claude - can we simplify this a bit?

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