Skip to content

Wire mergedTracerTags as a read-through parent at span build (level-split phase 1)#11932

Draft
dougqh wants to merge 4 commits into
dougqh/tagmap-read-throughfrom
dougqh/tagmap-read-through-consumer
Draft

Wire mergedTracerTags as a read-through parent at span build (level-split phase 1)#11932
dougqh wants to merge 4 commits into
dougqh/tagmap-read-throughfrom
dougqh/tagmap-read-through-consumer

Conversation

@dougqh

@dougqh dougqh commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Stacked on #11789 (TagMap read-through mechanism) — review that first.

Level-split phase 1: the wiring. Attaches mergedTracerTags as a read-through parent at span build (gated on !mergedTracerTagsNeedsIntercept) instead of copying it into every span's storage. This is the change that actually activates read-through — #11789 alone is inert (parent == null).

Commits: config-version handling out of the trace-level bundle, the read-through flip (DDSpanContext.parentTags / CoreTracer copy-vs-share gate), and a TagMapReadThroughBenchmark.

Draft — description to be refined; posting now so review can start this week ahead of the release cut.

🤖 Generated with Claude Code

@dd-octo-sts

dd-octo-sts Bot commented Jul 13, 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 13.99 s 13.93 s [-0.4%; +1.3%] (no difference)
startup:insecure-bank:tracing:Agent 12.95 s 13.02 s [-1.2%; +0.2%] (no difference)
startup:petclinic:appsec:Agent 16.92 s 16.49 s [+1.8%; +3.5%] (significantly worse)
startup:petclinic:iast:Agent 16.90 s 16.93 s [-0.9%; +0.7%] (no difference)
startup:petclinic:profiling:Agent 16.73 s 16.96 s [-2.2%; -0.5%] (maybe better)
startup:petclinic:sca:Agent 16.95 s 16.96 s [-1.1%; +1.0%] (no difference)
startup:petclinic:tracing:Agent 15.68 s 15.97 s [-6.1%; +2.5%] (no difference)

Commit: e65e58f8 · 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.

@dougqh dougqh force-pushed the dougqh/tagmap-read-through-consumer branch from 02ef063 to 7bb20f4 Compare July 13, 2026 17:49
dougqh and others added 4 commits July 13, 2026 14:14
Version is conditionally managed by InternalTagsAdder (added only when
service == DD_SERVICE and not set during the request). It was being applied to
every span via the trace-level bundle, then immediately stripped by a per-span
removeTag(VERSION) — apply-then-remove, net zero.

Exclude it from the bundle once at config build (withTracerTags) instead. This
is behavior-preserving today, and it prepares the bundle to become a read-through
parent: a removeTag on a key that lived in the parent would mint a per-span
tombstone. With version excluded, the retained per-span removeTag(VERSION) (which
still wipes a builder-set version, preserving the existing semantics) is a cheap
local op, never a tombstone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Level-split phase 1: when the trace-level bundle has no interceptable tags
(!mergedTracerTagsNeedsIntercept), attach it as a read-through parent of the
span's tags (shared by reference) instead of copying its entries into every
span. When it does need interception, fall back to the copy path (the
interceptor's per-span side-effects can't be shared).

- TagMap.withParent promoted to the interface (was package-private on
  OptimizedTagMap) — the public wiring deferred from the mechanism change.
- DDSpanContext.parentTags attaches the (frozen) parent to unsafeTags.
- CoreTracer span-build gates copy-vs-share on needsIntercept.

mergedTracerTags is the precedence floor (overridden by all other contributors),
so attaching it as the lowest-precedence parent preserves ordering. Version was
already excluded from the bundle, so the per-span removeTag never tombstones.
Tag-touching tests (CoreSpanBuilder/CoreTracer/DDSpan/InternalTagsAdder) green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Models span-build tag assembly: copyDown (putAll the frozen trace-level bundle
into a fresh span map, then span tags) vs readThrough (attach the bundle as a
read-through parent, span tags local only). Run with -prof gc to isolate the
per-span allocation read-through saves. Swept by traceTagCount {3,7,15} so the
win can be seen scaling with the bundle size; 7 ~ a realistic mergedTracerTags.

Quick read (noisy box): readThrough ~38% less alloc (deterministic) and ~1.7x
throughput. The alloc delta is bucket structure (BucketGroup clones + fewer local
collisions), not Entry objects -- putAll-into-empty already shares frozen entries.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rework the wiring onto the footgun-free API: instead of the post-construction
DDSpanContext.parentTags()/withParent() seam, thread a nullable read-through
parent into the DDSpanContext constructor and build unsafeTags via
TagMap.createFromParent(parent) when present. CoreTracer passes
mergedTracerTags on the !needsIntercept path (null otherwise), so the parent
is fixed at construction and read-through relies on a guarantee, not an
unenforced convention. Removes parentTags(); a back-compat 24-arg ctor
delegates with a null parent so existing callers are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dougqh dougqh force-pushed the dougqh/tagmap-read-through-consumer branch from 7bb20f4 to e65e58f Compare July 13, 2026 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant