Skip to content

[Traces] Add error sampling with opt-in tracer-drop rescue - #169

Open
lucaspimentel wants to merge 44 commits into
mainfrom
lpimentel/add-error-sampler
Open

lucaspimentel wants to merge 44 commits into
mainfrom
lpimentel/add-error-sampler

Conversation

@lucaspimentel

@lucaspimentel lucaspimentel commented Sep 18, 2026 •

Copy link
Copy Markdown
Member

What does this PR do?

Integrate the shared error sampler from #141 into the SCL trace processor, giving dropped error chunks another sampling opportunity.

  • Rescue chunks containing at least one span with error != 0. Priority 0 is eligible by default, regardless of decision maker.
  • Opt into additional negative priorities with DD_APM_FEATURES=error_rare_sample_tracer_drop. Exclude exact manual drops (priority == -1 and chunk _dd.p.dm == "-4"); positive priorities never qualify.
  • Chunks without a sampling priority (-128) are never eligible. The backend keeps them anyway, and in the Go agent they reach the error sampler only after its no-priority sampler drops them, so rescuing them would only spend the shared budget. The Lambda extension also treats them as kept.
  • Promote _dd.p.dm from the first span carrying it to chunk tags before enrichment, independently of rescue settings. Existing chunk values take precedence, including empty strings; span metadata remains intact.
  • Stamp _dd.errors_sr on the resolved root when the sampler keeps a chunk. This enables backend retention without changing sampling priorities or decision makers. Forward every chunk, including those not rescued.

Motivation

APMSVLS-472: retain a representative sample of errors that would otherwise be dropped, with a shared adaptive sampling budget. The opt-in feature widens eligibility only; it does not enable a disabled sampler.

Additional Notes

  • On by default: existing users get error rescue when they upgrade, up to 10 error traces per second per instance, matching the Go agent's ErrorTPS default. Set DD_APM_ERROR_TPS=0 to turn it off.
  • Use RateLimited mode with extra sample rate 1. DD_APM_ERROR_TPS <= 0 disables rescue; blank values count as unset; malformed/non-finite values warn and fall back to 10. DD_APM_ERROR_SAMPLER_MODE is not read.
  • Differs from the Lambda extension: the extension uses DD_SERVERLESS_ERROR_SAMPLER_ENABLED (off by default, keeps every candidate) and only warns on DD_APM_ERROR_TPS. This PR follows the Go agent setting instead; the extension can be aligned separately.
  • All eligible priorities share one sampler budget across requests and processor clones. Sampler signatures prefer the payload environment, falling back to the agent environment consistently with stats.
  • Rescue is independent of agent stats computation. When enabled, stats receive chunks before rescue stamping; rescue runs before payload splitting.
  • Feature parsing matches #186: split on commas if present, otherwise literal ASCII spaces; trim entries and match the complete feature name case-sensitively.
  • Warn at startup if the tracer-drop feature is enabled while TPS disables rescue.
  • Fake-intake tests verify the outbound wire contract, not backend retention.

Describe how to test/QA your changes

  • Unit coverage checks configuration, eligibility, decision-maker precedence, root resolution, shared-budget decisions, timestamp clamping, and stats independence.
  • Paired real-flusher integration tests cover feature-on/off behavior, outbound rescue metrics, unchanged priorities and metadata, forwarding, and stats inclusion.
  • The workspace test suite, workspace all-features Clippy with warnings denied, and formatting pass.

@lucaspimentel

Copy link
Copy Markdown
Member Author

@DataDog review

@datadog-datadog-prod-us1-2 datadog-datadog-prod-us1-2 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.

Datadog Autotest: FAIL

Concurrent requests can send times to the shared sampler in reverse order at a bucket limit. This can clear valid counts and permit too many rescued traces.

Open Bits AI session

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

@lucaspimentel

Copy link
Copy Markdown
Member Author

@DataDog review

@datadog-datadog-prod-us1-2 datadog-datadog-prod-us1-2 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.

Datadog Autotest: FAIL

A backward system-clock change can move the sampler to an old bucket. The sampler then uses stale counts and applies the TPS limit incorrectly.

Open Bits AI session

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

@lucaspimentel
lucaspimentel force-pushed the lpimentel/add-error-sampler branch from e5fcd5e to bfbe164 Compare September 24, 2026 15:07
@lucaspimentel lucaspimentel changed the title Rescue errored P0 trace chunks from backend drop feat(traces): Add error sampler, rescue errored p0 trace chunks Sep 24, 2026
@lucaspimentel
lucaspimentel marked this pull request as ready for review September 24, 2026 15:08
@lucaspimentel
lucaspimentel requested review from a team as code owners September 24, 2026 15:08
@lucaspimentel
lucaspimentel requested review from apiarian-datadog and lym953 and a lite review from Copilot and removed request for a team September 24, 2026 15:08
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-29T21:47:45.303010Z 0d6f521 New commits
🔒 Security Review ✅ Completed 2026-10-29T21:37:13.740258Z 0d6f521 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: bfbe16481b

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Moderate issues remain in sampler test equivalence, mutex contention, and integration-test error propagation.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 Medium severity · 1 Low severity

Open (3)
What changed in this PR

Adds shared error sampling to rescue eligible errored P0 trace chunks while preserving priorities and stats behavior.

Changes:

  • Integrates configurable, shared error sampling.
  • Stamps _dd.errors_sr on rescued root spans.
  • Adds configuration, dependency wiring, and unit/integration coverage.
File Review summary
crates/​datadog-trace-agent/​tests/​integration_test.rs Moderate findings (1 vote each): propagate mini-agent startup and shutdown/task errors.
crates/​datadog-trace-agent/​src/​trace_processor.rs Moderate findings: align test environments in sampler oracles (2 votes each); avoid holding a blocking mutex during the full payload walk (1 vote). Nit: document root-resolution fallback behavior (2 votes).
crates/​datadog-trace-agent/​src/​stats_processor.rs Test configuration fixtures updated; no findings.
crates/​datadog-trace-agent/​src/​config.rs Sampler configuration parsing updated; no findings.
crates/​datadog-trace-agent/​Cargo.toml Adds the sampler dependency; no findings.
crates/​datadog-serverless-compat/​src/​main.rs Initializes the shared sampler; no findings.
Cargo.lock Records dependency updates; no findings.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@lucaspimentel

Copy link
Copy Markdown
Member Author

@DataDog review

@datadog-datadog-prod-us1-2 datadog-datadog-prod-us1-2 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.

Bits Code Review: PASS

More details

The shared sampler is consistently configured, reused across processor clones, and applied after stats submission without changing sampling priorities.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit 69fc977 · @DataDog review to ask questions

@lucaspimentel lucaspimentel changed the title feat(traces): Add error sampler, rescue errored p0 trace chunks feat(traces): wire in the error sampler to rescue errored p0 trace chunks Sep 29, 2026
@lucaspimentel

Copy link
Copy Markdown
Member Author

@DataDog review

@datadog-datadog-prod-us1-2 datadog-datadog-prod-us1-2 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.

Bits Code Review: PASS

More details

The sampler is shared across processor clones and runs after stats submission without changing sampling priorities; the completed static review found no actionable regression.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit 69fc977 · @DataDog review to ask questions

@lucaspimentel
lucaspimentel force-pushed the lpimentel/add-error-sampler branch from 3788c42 to 0346af6 Compare October 19, 2026 13:42
@lucaspimentel
lucaspimentel force-pushed the lpimentel/add-error-sampler branch from f01c4f5 to 23fc576 Compare October 26, 2026 20:36

@lym953 lym953 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.

[Written by Claude, an AI assistant, for Yiming]

I reviewed the production code and the tests. The PR adds about 310 lines of production code and about 1,490 lines of tests. The inline comments have the details.

Production code

  • The Lambda extension configures the same sampler with different environment variables.
  • The timestamp floor can live in the sampler mutex.
  • Two questions: why the stats setting controls rescue, and why priority -128 is never eligible.

Tests
I estimate that you can remove about 400 to 450 test lines and keep coverage of each behavior:

  • The eligibility table test covers six single-case tests.
  • Two tests do the same check.
  • Some tests check the sampler crate again.
  • The config tests repeat the same setup block.

I suggest that you keep these tests, because no other test covers them:

  • the eligibility table test
  • decision-maker promotion
  • the initialization warning
  • the resolved-root test
  • the test that healthy chunks use no budget
  • the disabled-TPS test
  • the timestamp clamp
  • the stats-off no-op test
  • the test that stats see chunks before stamping
  • the two integration tests

I measured the line counts. The saving is an estimate, because I did not write the shorter version or run a coverage tool.

@lucaspimentel

Copy link
Copy Markdown
Member Author

@DataDog review

@lucaspimentel

Copy link
Copy Markdown
Member Author

@codex review

@datadog-datadog-prod-us1-2 datadog-datadog-prod-us1-2 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.

Bits Code Review: PASS

More details

The diff reflects the discussed design revisions: no-priority error chunks qualify, and rescue runs independently of stats computation. Static review identified no reportable defect.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit 391cbfe

@lucaspimentel
lucaspimentel force-pushed the lpimentel/add-error-sampler branch from 74b4dff to c91d837 Compare October 29, 2026 20:45
Chunks without a sampling priority are kept by the backend, so they no longer use the shared error sampling budget. This matches the Go agent, where only chunks dropped by the no-priority sampler reach the error sampler.
An empty or whitespace-only value now uses the default without logging an invalid-value warning, as the Go agent does.
Drop the AlwaysKeep disabled case and the lock-ordering test, and assert literal keep decisions instead of replaying a standalone sampler.
ServerlessTraceProcessor::new now takes the config and owns its error sampler, instead of exposing the shared lock in its public signature. Clones still share one budget.
Disabled rescue no longer takes the shared lock, and span views are built before locking, so large payloads hold it for less time.

@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: 0d6f521f16

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

let eligible = chunk.priority == 0
|| (tracer_drop_enabled
&& chunk.priority < 0
&& chunk.priority != i32::from(i8::MIN)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Align no-priority rescue behavior with the PR contract

For traces whose tracer omitted sampling priority, the collector represents the priority as -128; the PR description says these errored chunks are eligible by default, but this condition excludes them even when the tracer-drop feature is enabled, so they can never receive _dd.errors_sr. Either restore the advertised eligibility or update the PR description and QA expectations to document the intentional exclusion.

AGENTS.md reference: AGENTS.md:L64-L65

Useful? React with 👍 / 👎.

Comment on lines +1502 to +1503
fn test_rate_limited_under_sustained_load_keeps_and_rejects() {
for (sample_rate, expected_keeps) in [(None, 83_usize), (Some(0.25_f64), 9)] {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Remove the duplicate sampler-algorithm test

This test asserts exact keep counts (83 and 9) produced by the shared sampler's rate algorithm, duplicating behavior already tested in datadog-agent-trace-sampler and coupling the trace-agent suite to its internals rather than merely checking the adapter call. The change adds about 272 core lines but 955 test lines; replacing this 100-chunk algorithm test with a small adapter-focused case would reduce that disproportion without losing integration coverage.

AGENTS.md reference: AGENTS.md:L45-L47

Useful? React with 👍 / 👎.

This branch has not been deployed

No deployments
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.

3 participants