Skip to content

Add @ForegroundSafe/@BackgroundOnly declared-contract reachability check (J16) (AI perf review) - #12474

Closed
dougqh wants to merge 65 commits into
robertomonteromiguel/dd-apm-sdk-review-java-overridesfrom
dougqh/foreground-background-only-check
Closed

dougqh wants to merge 65 commits into
robertomonteromiguel/dd-apm-sdk-review-java-overridesfrom
dougqh/foreground-background-only-check

Conversation

@dougqh

@dougqh dougqh commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

What Does This Do

  • Adds datadog.trace.api.function.ForegroundSafe/.BackgroundOnly annotations declaring a one-way foreground/background cost contract, applied to FixedSizeCache/EncodingCache as initial markers.
  • Adds addendum J16 (background-only-contract) to the dd-apm-sdk-review skill's performance lens: flags a foreground call path reaching @BackgroundOnly code, including a declaration-site inheritance-widening violation and a bounded two-hop interface-propagation extension.
  • Documents the contract in both annotations' Javadoc, the J16 addendum, and a new section in docs/instrumentation_design_guidelines.md.
  • Uses CLASS retention so a future bytecode-level checker (APMLP-1645) can consume the markers.
  • Adds .llm-validation fixtures covering the interface-hop and inheritance-widening cases (13 gate cases total, up from 11).

Motivation

Part of APMLP-1513 / APMLP-1645: giving the perf-review tooling a declared contract to check against, rather than relying on ad hoc judgment calls about whether code is cheap enough for a foreground thread.

Additional Notes

  • ./gradlew :internal-api:spotlessJavaCheck passes.
  • .llm-validation gate run (13 cases) and the dd-apm-sdk-review 8-lens re-review are pending via the platform CI job.
  • Module-placement P1 explicitly deferred from the review: annotations stay in internal-api for now, pending a future move of the whole toolbox into its own component.

Contributor Checklist

  • Format the title according to the contribution guidelines
  • Assign the type: and (comp: or inst:) labels in addition to any other useful labels
  • Avoid using close, fix, or any linking keywords when referencing an issue
  • Update the CODEOWNERS file on source file addition, migration, or deletion (n/a — no new module/ownership boundary)
  • Update public documentation with any new configuration flags or behaviors (n/a — internal-only marker annotations)
  • Once approved, use merge queue to merge the PR

Jira ticket: APMLP-1513

🤖 Generated with Claude Code

@dougqh dougqh added tag: no release notes Changes to exclude from release notes inst: java Core Java language instrumentation tag: ai generated Largely based on code generated by an AI or LLM labels Sep 11, 2026
@dougqh

dougqh commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a6310c5078

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread internal-api/src/main/java/datadog/trace/api/cache/FixedSizeCache.java Outdated
Comment thread .agents/dd-apm-sdk-review-overrides/reviewers/performance.md Outdated
@datadog-datadog-prod-us1

This comment has been minimized.

@dd-octo-sts

dd-octo-sts Bot commented Sep 11, 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.80 s 14.71 s [-0.3%; +1.5%] (no difference)
startup:insecure-bank:tracing:Agent 13.63 s 13.70 s [-1.1%; +0.1%] (no difference)
startup:petclinic:appsec:Agent 16.93 s 16.13 s [-0.4%; +10.4%] (unstable)
startup:petclinic:iast:Agent 16.84 s 16.44 s [-2.0%; +6.9%] (no difference)
startup:petclinic:profiling:Agent 16.72 s 16.71 s [-1.0%; +1.1%] (no difference)
startup:petclinic:sca:Agent 16.83 s 16.49 s [+1.1%; +2.9%] (significantly worse)
startup:petclinic:tracing:Agent 16.00 s 15.56 s [-1.3%; +7.0%] (no difference)

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

@dd-octo-sts

dd-octo-sts Bot commented Sep 11, 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.81 s 14.73 s [-0.5%; +1.6%] (no difference)
startup:insecure-bank:tracing:Agent 13.63 s 13.69 s [-1.3%; +0.4%] (no difference)

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

@pr-commenter

pr-commenter Bot commented Sep 11, 2026

Copy link
Copy Markdown

LLM Validation

LLM Validation Gate — dd-apm-sdk-review

✅ PASS

  • No blocking-case regressions; the quality change is within noise (baseline/candidate confidence intervals overlap).
  • Advisory: the candidate introduced a bad signal on 1 case(s) that the baseline did not — surfaced for review (see Cases); it does not block on its own.
  • Advisory: 1 run(s) could not be evaluated (agent infra error) and were excluded from scoring — re-run if a case shows too few evaluated runs to trust.

Analysis

Changed instruction file(s): .agents/skills/dd-apm-sdk-review/SKILL.md, .agents/skills/dd-apm-sdk-review/reviewers/_common.md, .agents/skills/dd-apm-sdk-review/reviewers/correctness.md, .agents/skills/dd-apm-sdk-review/reviewers/performance.md, .agents/skills/dd-apm-sdk-review/reviewers/report-template.md, .agents/skills/dd-apm-sdk-review/review-without-harness.md, .agents/skills/dd-apm-sdk-review/reviewers/coherence.md, .agents/skills/dd-apm-sdk-review/reviewers/security.md, .agents/skills/dd-apm-sdk-review/reviewers/design.md, .agents/skills/dd-apm-sdk-review/reviewers/maintainability.md, .agents/skills/dd-apm-sdk-review/reviewers/conventions.md, .agents/skills/dd-apm-sdk-review/reviewers/cross-sdk.md, .agents/dd-apm-sdk-review-overrides/repo-context.md, .agents/dd-apm-sdk-review-overrides/reviewers/security.md, .agents/dd-apm-sdk-review-overrides/reviewers/performance.md, .agents/dd-apm-sdk-review-overrides/reviewers/design.md, .agents/dd-apm-sdk-review-overrides/reviewers/conventions.md, .agents/dd-apm-sdk-review-overrides/reviewers/maintainability.md.

1 case(s) dipped but stayed within the pass bar.

  • java-correctness-mapper-state-leak: won 25% of blind comparisons, quality -15.0. ⚠️ Introduced a new bad signal (advisory).
    • Asked: Run dd-apm-sdk-review on the following change. There is no git repository to inspect — this diff is the entire change set; do not attempt any git commands, go
    • Baseline answer: I now have everything needed. I confirmed the full lifecycle and traced the flag's behavior through every path. Note: the skill's SKILL.md and reviewer files are deleted from this worktree (only a mirror README.md survives) and the skill isn't wired into the Skill tool, so I ran the review directly using the
    • Candidate answer: I have everything I need. Since the change was pasted inline, this ran in single-context sequential mode (expected for pasted input, not a capability gap). Grounding checks done: reset() is called per payload flush (PayloadDispatcherImpl:110), the firstSpanWritten pattern matches the sibling TraceMapperV0_5,

Results

  • Pairwise win-rate: 65% [58%–72%] — candidate's share of blind comparisons (90% CI; spanning 50% = no clear difference)
  • Overall quality: 78.5 → 83.5 (/100, +5.1)
  • Bad signals introduced (advisory): 1
  • Candidate criteria coverage (advisory): 39/43 (91%) — expected_criteria the candidate met; does not affect the gate
  • Candidate bad signals (all, advisory): 2 case(s) — trips on the candidate, including ones the baseline also hit
  • Blocking-case regressions: 0
  • Inconclusive runs (excluded — infra error): 1

Cases

Case Mode Quality Δ Win-rate (90% CI) Safety
java-perf-lens-wrong-collection-001 block -2.7 38% [17%–58%] ok
java-perf-pipeline-full-review-002 block +35.0 100% [100%–100%] ok
java-security-crash-handler-before-trust block +0.4 50% [50%–50%] ok
java-correctness-capture-before-send block +0.8 62% [23%–100%] ok
java-correctness-sqs-queue-name-incomplete block +7.1 75% [51%–99%] ok
java-maintainability-resource-leak-streams block +13.3 88% [67%–100%] ok
java-correctness-span-events-list-only block +12.1 100% [100%–100%] ok
java-correctness-mapper-state-leak block -15.0 25% [0%–66%] (1 inconc.) ⚠️ bad signal
java-perf-foreground-calls-background-only-001 block +2.5 62% [42%–83%] ok
java-perf-foreground-calls-unannotated-002 block -5.8 50% [50%–50%] fail (both)
java-perf-foreground-calls-method-override-003 block +2.1 50% [50%–50%] ok
java-perf-foreground-calls-interface-hop-004 block 0.0 50% [50%–50%] ok
java-perf-inheritance-widen-violation-005 block +5.8 75% [51%–99%] ok

Per-dimension scores, token usage, latency, and estimated cost are in the CI job logs.

@bric3
bric3 added this pull request to stack #12505 September 15, 2026 12:29
@dougqh dougqh changed the title Add @ForegroundSafe/@BackgroundOnly declared-contract reachability check (J16) Add @ForegroundSafe/@BackgroundOnly declared-contract reachability check (J16) (AI perf review) Sep 15, 2026
Prevent Netty idle timers from retaining request context

Co-authored-by: andrea.marziali <andrea.marziali@datadoghq.com>
Prevent Netty startup tasks from inheriting context

Cover shaded Netty event executors

Co-authored-by: andrea.marziali <andrea.marziali@datadoghq.com>
Avoid abandoning Guidewire test continuations

Co-authored-by: andrea.marziali <andrea.marziali@datadoghq.com>
Close ServiceTalk captured context scope in test

Co-authored-by: andrea.marziali <andrea.marziali@datadoghq.com>
@dougqh
dougqh marked this pull request as ready for review September 16, 2026 12:00
@dougqh
dougqh requested a review from a team as a code owner September 16, 2026 12:00
@dougqh
dougqh requested review from jandro996 and removed request for a team September 16, 2026 12:00

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8163b89741

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread .agents/dd-apm-sdk-review-overrides/reviewers/performance.md Outdated
Comment thread .agents/dd-apm-sdk-review-overrides/reviewers/performance.md Outdated

@datadog-datadog-prod-us1 datadog-datadog-prod-us1 Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Datadog Autotest: FAIL

The type annotation marks linear cache operations as foreground-safe. The interface rule also reports a contract violation when the runtime target is not known.

Open Bits AI session

🤖 Datadog Autotest · Commit 8163b89 · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest

Comment thread internal-api/src/main/java/datadog/trace/api/cache/FixedSizeCache.java Outdated
Comment thread .agents/dd-apm-sdk-review-overrides/reviewers/performance.md Outdated
AlexeyKuznetsov-DD and others added 6 commits September 16, 2026 13:04
Prevent nested smoke builds from falling back to Maven Central

Redirect nested Maven Central declarations

Deduplicate nested Maven proxy repositories

The init script injects the repository proxy and redirectMavenCentral()
rewrites any mavenCentral() the nested build declares onto that same URL,
so both the plugin-management and project repository lists end up holding
the proxy twice. They stay distinct Gradle repositories, duplicating
metadata and artifact requests on every cache miss.

Drop the redundant entries, keeping the repository this script injected:
it is the only one known to be unrestricted. A declared mavenCentral()
may carry content filters or narrowed metadata sources that the redirect
does not lift, so keeping such a declaration instead would stop resolving
whatever it excludes. Containers this script never injected into are left
untouched, so nothing removes a proxy the nested build owns outright.

Also handle a repository declared without a URL, which would otherwise
fail with a NullPointerException thrown from an injected init script
rather than Gradle's own error.

The test fixture now declares Maven Central with a content filter before
the injection happens, which is the ordering that makes the choice of
survivor observable.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Co-authored-by: alexey.kuznetsov <alexey.kuznetsov@datadoghq.com>
Fix ATR eligibility with fail-fast test ordering

test: clarify ATR eligibility coverage

Co-authored-by: daniel-mohedano <daniel.mohedano@datadoghq.com>
Fix Robolectric 4.17 muzzle validation

Preserve Robolectric minor release codenames

Convert Robolectric codename test to JUnit

fix: avoid reflection for Robolectric Android codenames

test: cover fixed and latest Robolectric versions

fix: smoke test version resolution

Merge branch 'master' into alexeyk/fix-robolectric-4-17-muzzle

Rollback temporarey fix.

Merge branch 'master' into alexeyk/fix-robolectric-4-17-muzzle

refactor: simplify Robolectric codename mapping

Co-authored-by: daniel-mohedano <daniel.mohedano@datadoghq.com>
Co-authored-by: alexey.kuznetsov <alexey.kuznetsov@datadoghq.com>
Infer status 200 for implicit-success Lambda responses

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Update Lambda URL instrumentation test for inferred success status

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Merge branch 'master' into clara.poncet/api-security-lambda

Co-authored-by: devflow.devflow-routing-intake <devflow.devflow-routing-intake@kubernetes.us1.ddbuild.io>
…test version. (#12488)

Use Apache archive for Tomcat smoke test, since dlcdn has ONLY the latest version.

Merge branch 'master' into alexeyk/use-archived-tomcat-distribution

Merge branch 'master' into alexeyk/use-archived-tomcat-distribution

Merge branch 'master' into alexeyk/use-archived-tomcat-distribution

Merge branch 'master' into alexeyk/use-archived-tomcat-distribution

Co-authored-by: alexey.kuznetsov <alexey.kuznetsov@datadoghq.com>
fix(ci-visibility): align TIA missing coverage field

Merge branch 'master' into daniel.mohedano/fix-tia-missing-line-coverage-field

Merge branch 'master' into daniel.mohedano/fix-tia-missing-line-coverage-field

Merge branch 'master' into daniel.mohedano/fix-tia-missing-line-coverage-field

Merge branch 'master' into daniel.mohedano/fix-tia-missing-line-coverage-field

Co-authored-by: daniel.mohedano <daniel.mohedano@datadoghq.com>
ygree and others added 2 commits September 16, 2026 23:44
…#12433)

Fix `Lettuce5MasterReplicaTest` span wait race

Replace `writer.waitForTraces(1)` with a predicate-based wait for the
Redis `SET` span. This avoids relying on `ListWriter`’s cumulative trace
count after `writer.clear()` and prevents the assertion from running
before the command span is written.

Reproduce missing peer.hostname with Lettuce running with redis cluster

Fix missing peer.hostname on Lettuce cluster spans

Fixed the CI failure in Lettuce5ClusterTest

Root cause: the test used `grokzen/redis-cluster:6.2.1`, and Docker now
returns `NotFound` for that tag. Docker Hub currently lists newer
`6.2.x` tags such as `6.2.14`

Fixed Lettuce5 muzzle test

Use the official Redis image to bootstrap a single-node cluster in
Lettuce5ClusterTest available in the CI registry mirror.

Fix Lettuce cluster peer tags for replica reads

Decorate Lettuce cluster command spans from the physical connection
selected by
the cluster provider instead of deriving peer tags from the slot-owning
master.

When ReadFrom routes a cluster read to a replica,
getConnectionAsync(READ, slot)
can return a replica connection while the slot partition still points to
the
master. Track RedisURI on the selected write/read connection futures and
use that
connection context when decorating the active command span.

Expand Lettuce5ClusterTest to run a single-shard master/replica Redis
Cluster,
verify replica-routed reads use the replica peer tags, and keep random
exposed
ports with room for Redis cluster bus ports.

Fixed the Lettuce 6.2 failure.

Cause: Lettuce 6.2’s replica read selection requires the replica
partition metadata to have a non-zero replication offset. The test
created the replica correctly, but the client could still have stale
topology metadata when `ReadFrom.SLAVE` was enabled, causing
`PartitionSelectorException`.

Populate Lettuce cluster context at node connection creation

Move `StatefulConnection -> RedisURI` context population from
per-command pooled cluster connection lookups to
`RedisClusterClient.connectToNodeAsync`, deriving the URI from Lettuce’s
resolved `ConnectionFuture` remote address. This removes the hot-path
`thenApply` wrappers from cluster read/write selection while preserving
command span decoration for the selected physical node.

Also add a completed-future fast path for cluster and master/replica
span decoration callbacks.

Fix Lettuce cluster SET span wait in tests

Fix reactive Lettuce cluster peer tagging

Activate the stored reactive Redis command span while
`RedisSubscription.dispatchCommand()` selects the physical cluster
connection, allowing existing connection decoration to add peer tags.
Add a reactive cluster regression test covering `peer.hostname` on
command spans.

Merge branch 'master' into ygree/lettuce-cluster-mode-peer-hostname-fix

Sequence Lettuce peer decoration before connection use

Return the dependent connection future that performs peer decoration and
replace the async advice return values so Lettuce dispatch waits until
the selected connection has tagged the active Redis span. Keeps
already-completed futures on the synchronous path.

Merge branch 'master' into ygree/lettuce-cluster-mode-peer-hostname-fix

Merge branch 'master' into ygree/lettuce-cluster-mode-peer-hostname-fix

Co-authored-by: yury.gribkov <yury.gribkov@datadoghq.com>
chore: Update Gradle dependencies

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

Co-authored-by: alexey.kuznetsov <alexey.kuznetsov@datadoghq.com>
FixedSizeCache's per-method markers were unreachable by the checker at
real call sites, since every caller holds a DDCache-typed reference.
Move @BackgroundOnly onto DDCache.visit() itself (mirroring the
EncodingCache precedent) and drop it from FixedSizeCache.clear(), which
wasn't cost-justified at the small capacities real callers use.

Also fixes an inverted "narrow"/"widen" phrase in both markers' javadoc
(three independent reviewers flagged it) and updates the J16 example in
performance.md to match.
@dougqh
dougqh force-pushed the dougqh/foreground-background-only-check branch from 9a7f0e7 to bad45b5 Compare September 22, 2026 17:28
@dougqh
dougqh requested review from a team as code owners September 22, 2026 17:28
@dougqh
dougqh requested review from AlexeyKuznetsov-DD, claponcet, mhlidd, randomanderson, tylfin and vandonr and removed request for a team September 22, 2026 17:29
@dougqh

dougqh commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

Unstacking: this branch was based on the now-paused dd-apm-sdk-review review-framework branch and its history was entangled with that framework's J16 lens/.llm-validation fixtures. Superseded by #12606, which carries just the real @ForegroundSafe/@BackgroundOnly annotation + cache-class work rebased directly onto master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

inst: java Core Java language instrumentation tag: ai generated Largely based on code generated by an AI or LLM tag: no release notes Changes to exclude from release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.