Skip to content

[Debugger] Add system-test coverage for the debugger guardrails - #7287

Open
dudikeleti wants to merge 24 commits into
mainfrom
dudik/debugger/guardrails-tests
Open

[Debugger] Add system-test coverage for the debugger guardrails#7287
dudikeleti wants to merge 24 commits into
mainfrom
dudik/debugger/guardrails-tests

Conversation

@dudikeleti

@dudikeleti dudikeleti commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Motivation

Add focused system-test coverage for the debugger guardrails required for GA.

Changes

  • Add method- and line-probe evaluation-timeout tests covering an expensive regex and a large collection filter. Aborted evaluations must produce exactly one evaluation-error snapshot with evaluationErrors[] populated and no captured data.
  • Add snapshot-size guardrail coverage verifying that the request containing the snapshot is ≤1 MB and includes a payload-pruning marker.
  • Add capture-timeout coverage verifying that the affected collection reports notCapturedReason=timeout, without incorrectly satisfying the snapshot-size guardrail.
  • Add the dedicated DEBUGGER_CAPTURE_TIMEOUT scenario with a 10 ms capture budget, CI orchestration, and compatible weblog filtering.
  • Add the /debugger/snapshot/capture-timeout fixture to supported .NET, Java, and Node.js weblogs and document the endpoint.
  • Extend test_default_max_length to verify that truncated strings report truncated=true.
  • Extract the shared captures_contain_data helper into tests.debugger.utils.
  • Enable capture-timeout coverage for supported .NET, Java, and Node.js tracer versions. Keep unsupported weblogs and the evaluation-timeout and snapshot-size guardrails disabled through manifests until support lands.

Workflow

  1. ⚠️ Create your PR as draft ⚠️
  2. Work on you PR until the CI passes
  3. Mark it as ready for review
    • Test logic is modified? -> Get a review from RFC owner.
    • Framework is modified, or non obvious usage of it -> get a review from R&P team

🚀 Once your PR is reviewed and the CI green, you can merge it!

🛟 #apm-shared-testing 🛟

Reviewer checklist

  • Anything but tests/ or manifests/ is modified ? I have the approval from R&P team
  • A docker base image is modified?
    • the relevant build-XXX-image label is present
  • A scenario is added, removed or renamed?

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

CODEOWNERS have been resolved as:

tests/debugger/test_debugger_guardrails.py                              @DataDog/debugger @DataDog/system-tests-core
tests/debugger/utils/probes/probe_capture_timeout_reason.json           @DataDog/debugger @DataDog/system-tests-core
tests/debugger/utils/probes/probe_evaluation_timeout_collection_filter.json  @DataDog/debugger @DataDog/system-tests-core
tests/debugger/utils/probes/probe_evaluation_timeout_regex.json         @DataDog/debugger @DataDog/system-tests-core
tests/debugger/utils/probes/probe_snapshot_size_cap.json                @DataDog/debugger @DataDog/system-tests-core
.github/workflows/run-end-to-end.yml                                    @DataDog/system-tests-core
docs/understand/weblogs/end-to-end_weblog.md                            @DataDog/system-tests-core
manifests/dotnet.yml                                                    @DataDog/apm-dotnet @DataDog/asm-dotnet
manifests/golang.yml                                                    @DataDog/dd-trace-go-guild
manifests/java.yml                                                      @DataDog/asm-java @DataDog/apm-java
manifests/nodejs.yml                                                    @DataDog/dd-trace-js
manifests/php.yml                                                       @DataDog/apm-php @DataDog/asm-php
manifests/python.yml                                                    @DataDog/apm-python @DataDog/asm-python
manifests/ruby.yml                                                      @DataDog/ruby-guild @DataDog/asm-ruby
tests/debugger/test_debugger_condition_errors.py                        @DataDog/debugger @DataDog/system-tests-core
tests/debugger/test_debugger_probe_snapshot.py                          @DataDog/debugger @DataDog/system-tests-core
tests/debugger/utils.py                                                 @DataDog/debugger @DataDog/system-tests-core
tests/test_the_test/scenarios.json                                      @DataDog/system-tests-core
tests/test_the_test/test_ci_orchestrator.py                             @DataDog/system-tests-core
tests/test_the_test/test_compute_libraries_and_scenarios.py             @DataDog/system-tests-core
utils/_context/_scenarios/__init__.py                                   @DataDog/system-tests-core
utils/build/docker/cpp_httpd/weblog_metadata.yml                        @DataDog/system-tests-core
utils/build/docker/cpp_kong/weblog_metadata.yml                         @DataDog/system-tests-core
utils/build/docker/cpp_nginx/weblog_metadata.yml                        @DataDog/system-tests-core
utils/build/docker/dotnet/weblog/Controllers/DebuggerController.cs      @DataDog/apm-dotnet @DataDog/asm-dotnet @DataDog/system-tests-core
utils/build/docker/dotnet/weblog_metadata.yml                           @DataDog/apm-dotnet @DataDog/asm-dotnet @DataDog/system-tests-core
utils/build/docker/golang/weblog_metadata.yml                           @DataDog/dd-trace-go-guild @DataDog/system-tests-core
utils/build/docker/java/spring-boot/src/main/java/com/datadoghq/system_tests/springboot/debugger/DebuggerController.java  @DataDog/apm-java @DataDog/asm-java @DataDog/system-tests-core
utils/build/docker/java/weblog_metadata.yml                             @DataDog/apm-java @DataDog/asm-java @DataDog/system-tests-core
utils/build/docker/nodejs/express/debugger/index.js                     @DataDog/dd-trace-js @DataDog/system-tests-core
utils/build/docker/nodejs/express4-typescript.Dockerfile                @DataDog/dd-trace-js @DataDog/system-tests-core
utils/build/docker/nodejs/express4-typescript/debugger/index.ts         @DataDog/dd-trace-js @DataDog/system-tests-core
utils/build/docker/nodejs/express4.Dockerfile                           @DataDog/dd-trace-js @DataDog/system-tests-core
utils/build/docker/nodejs/express5.Dockerfile                           @DataDog/dd-trace-js @DataDog/system-tests-core
utils/build/docker/nodejs/fastify.Dockerfile                            @DataDog/dd-trace-js @DataDog/system-tests-core
utils/build/docker/nodejs/fastify/debugger/index.js                     @DataDog/dd-trace-js @DataDog/system-tests-core
utils/build/docker/nodejs/uds-express4.Dockerfile                       @DataDog/dd-trace-js @DataDog/system-tests-core
utils/build/docker/nodejs/weblog_metadata.yml                           @DataDog/dd-trace-js @DataDog/system-tests-core
utils/build/docker/php/weblog_metadata.yml                              @DataDog/apm-php @DataDog/system-tests-core
utils/build/docker/python/weblog_metadata.yml                           @DataDog/apm-python @DataDog/asm-python @DataDog/system-tests-core
utils/build/docker/ruby/weblog_metadata.yml                             @DataDog/ruby-guild @DataDog/asm-ruby @DataDog/system-tests-core
utils/build/docker/rust/weblog_metadata.yml                             @DataDog/apm-rust @DataDog/system-tests-core

@datadog-datadog-prod-us1-2

datadog-datadog-prod-us1-2 Bot commented Jul 9, 2026

Copy link
Copy Markdown

Pipelines  Tests

Unblock PR with BitsAI

⚠️ Warnings

🚦 12 Pipeline jobs failed

DataDog/system-tests | K8S_LIB_INJECTION_PROFILING_ENABLED: [dd-lib-java-init-test-app, ${PRIVATE_DOCKER_REGISTRY}/system-tests/dd-lib-java-init-test-app, 235494822917.dkr.ecr.us-east-1.amazonaws.com/ssi/cluster-agent:7.81.1, 235494822917.dkr.ecr.us-east-1.amazonaws.com/ssi/apm-inject:latest, 3.231.5, 235494822917.dkr.ecr.us-east-1.amazonaws.com/ssi/dd-lib-java-init:latest]   View in Datadog   GitLab

DataDog/system-tests | K8S_LIB_INJECTION_PROFILING_ENABLED: [dd-lib-java-init-test-app, ${PRIVATE_DOCKER_REGISTRY}/system-tests/dd-lib-java-init-test-app, 235494822917.dkr.ecr.us-east-1.amazonaws.com/ssi/cluster-agent:7.81.1, 235494822917.dkr.ecr.us-east-1.amazonaws.com/ssi/apm-inject:latest, 3.231.5, 235494822917.dkr.ecr.us-east-1.amazonaws.com/ssi/dd-lib-java-init:latest_snapshot]   View in Datadog   GitLab

DataDog/system-tests | K8S_LIB_INJECTION_PROFILING_ENABLED: [dd-lib-java-init-test-app, ${PRIVATE_DOCKER_REGISTRY}/system-tests/dd-lib-java-init-test-app, 235494822917.dkr.ecr.us-east-1.amazonaws.com/ssi/cluster-agent:7.81.1, 235494822917.dkr.ecr.us-east-1.amazonaws.com/ssi/apm-inject:latest_snapshot, 3.231.5, 235494822917.dkr.ecr.us-east-1.amazonaws.com/ssi/dd-lib-java-init:latest]   View in Datadog   GitLab

View all 12 failed jobs.

ℹ️ Info

No other issues found (see more)

🧪 All tests passed
❄️ No new flaky tests detected

Useful? React with 👍 / 👎

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

@datadog-datadog-prod-us1-2

datadog-datadog-prod-us1-2 Bot commented Jul 10, 2026

Copy link
Copy Markdown

Bits couldn’t fix the CI

🟢 Investigated · 🔴 Fix failed · ⚪ Validate · ⚪ Ready

The newly enabled tests/debugger/test_debugger_guardrails.py::Test_Debugger_Snapshot_Guardrails::test_capture_timeout_reports_reason guardrail was running for tracer manifests where debugger capture-timeout reporting is still unsupported. Added explicit missing_feature entries for that test in manifests/dotnet.yml, manifests/golang.yml, manifests/java.yml, manifests/nodejs.yml, manifests/php.yml, manifests/python.yml, and manifests/ruby.yml.


View in Datadog | Reviewed commit 2c71ee0

@dudikeleti dudikeleti changed the title Dudik/debugger/guardrails tests [Debugger] Add system-test coverage for the debugger guardrails Jul 10, 2026
@dudikeleti
dudikeleti force-pushed the dudik/debugger/guardrails-tests branch 2 times, most recently from 3babba7 to f2c565e Compare July 11, 2026 10:46
@dudikeleti
dudikeleti requested a review from Copilot July 11, 2026 10:46
@dudikeleti

Copy link
Copy Markdown
Contributor Author

@codex review

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

Pull request overview

Adds focused end-to-end system-test coverage for debugger “guardrails” (evaluation timeout, snapshot size cap, and capture-timeout reporting) in the system-tests framework, wiring up new fixtures/endpoints across multiple weblogs and gating execution via orchestrator support checks and per-language manifests.

Changes:

  • Introduces new debugger guardrail tests (evaluation-timeout, snapshot-size cap, capture-timeout reason) plus new probe fixtures and a dedicated DEBUGGER_CAPTURE_TIMEOUT scenario.
  • Extends Node.js/Java/.NET test apps with a /debugger/snapshot/capture-timeout endpoint and updates Dockerfiles to include the debugger route modules.
  • Updates CI orchestration and “test-the-test” coverage (scenario mapping, workflow step, and _is_supported gating) and marks tests appropriately in language manifests.

Reviewed changes

Copilot reviewed 32 out of 32 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
utils/scripts/ci_orchestrators/workflow_data.py Restricts DEBUGGER_CAPTURE_TIMEOUT scenario to weblogs that include the new fixture.
utils/build/docker/nodejs/uds-express4.Dockerfile Copies the Express debugger routes into the UDS Express4 image.
utils/build/docker/nodejs/fastify/debugger/index.js Adds capture-timeout fixture route and local variable construction for snapshot capture.
utils/build/docker/nodejs/fastify.Dockerfile Copies fastify debugger routes into the image.
utils/build/docker/nodejs/express5.Dockerfile Copies Express debugger routes into the Express5 image.
utils/build/docker/nodejs/express4.Dockerfile Copies Express debugger routes into the Express4 image.
utils/build/docker/nodejs/express4-typescript/debugger/index.ts Adds capture-timeout fixture route for the TS Express4 app.
utils/build/docker/nodejs/express4-typescript.Dockerfile Copies TS debugger routes into the image.
utils/build/docker/nodejs/express/debugger/index.js Adds capture-timeout fixture route for Express apps.
utils/build/docker/java/spring-boot/src/main/java/com/datadoghq/system_tests/springboot/debugger/DebuggerController.java Adds capture-timeout endpoint/fixture for Java Spring Boot.
utils/build/docker/dotnet/weblog/Controllers/DebuggerController.cs Adds capture-timeout endpoint/fixture for .NET weblog.
utils/_context/_scenarios/init.py Adds DEBUGGER_CAPTURE_TIMEOUT scenario with tight capture/serialization budgets.
tests/test_the_test/test_compute_libraries_and_scenarios.py Updates expected scenario list to include DEBUGGER_CAPTURE_TIMEOUT.
tests/test_the_test/test_ci_orchestrator.py Adds regression test ensuring _is_supported gating matches expected fixture-enabled weblogs.
tests/test_the_test/scenarios.json Maps new guardrail tests to scenarios (DEBUGGER_CAPTURE_TIMEOUT and DEBUGGER_PROBES_SNAPSHOT).
tests/debugger/utils/probes/probe_snapshot_size_cap.json New probe fixture for snapshot-size cap behavior.
tests/debugger/utils/probes/probe_evaluation_timeout_regex.json New probe fixture for ReDoS-style regex evaluation timeout.
tests/debugger/utils/probes/probe_evaluation_timeout_collection_filter.json New probe fixture for expensive collection-filter evaluation timeout.
tests/debugger/utils/probes/probe_capture_timeout_reason.json New probe fixture to validate notCapturedReason='timeout'.
tests/debugger/utils.py Extracts captures_contain_data helper and adds line mapping for CaptureTimeout.
tests/debugger/test_debugger_probe_snapshot.py Extends default max-length test expectations (string truncation metadata).
tests/debugger/test_debugger_guardrails.py Adds new guardrail-focused debugger compliance tests.
tests/debugger/test_debugger_condition_errors.py Switches condition-error tests to use the shared captures_contain_data helper.
manifests/ruby.yml Marks new guardrail tests as missing_feature for Ruby.
manifests/python.yml Marks new guardrail tests as missing_feature for Python.
manifests/php.yml Marks new guardrail tests as missing_feature / incomplete_test_app where applicable.
manifests/nodejs.yml Adds per-weblog declarations for the capture-timeout fixture availability; marks others missing_feature.
manifests/java.yml Enables capture-timeout guardrail test for select Java weblogs; marks other guardrails missing_feature.
manifests/golang.yml Marks new guardrail tests missing_feature/incomplete_test_app for Go.
manifests/dotnet.yml Enables capture-timeout guardrail test for .NET; marks other guardrails missing_feature.
docs/understand/weblogs/end-to-end_weblog.md Documents the new /debugger/snapshot/capture-timeout endpoint semantics.
.github/workflows/run-end-to-end.yml Adds CI workflow step to execute the new DEBUGGER_CAPTURE_TIMEOUT scenario.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/debugger/test_debugger_guardrails.py Outdated
Comment thread tests/debugger/test_debugger_guardrails.py Outdated
Comment thread tests/debugger/test_debugger_probe_snapshot.py

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

ℹ️ 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".

Comment thread tests/debugger/test_debugger_guardrails.py
Comment thread tests/debugger/test_debugger_probe_snapshot.py
Comment thread tests/debugger/test_debugger_guardrails.py Outdated
@dudikeleti
dudikeleti force-pushed the dudik/debugger/guardrails-tests branch from 19a1599 to 273ee3c Compare July 14, 2026 11:36
@dudikeleti
dudikeleti marked this pull request as ready for review July 16, 2026 15:09
@dudikeleti
dudikeleti requested review from a team as code owners July 16, 2026 15:09
@dudikeleti
dudikeleti requested review from christophe-papazian and gyuheon0h and removed request for a team July 16, 2026 15:09
@dudikeleti
dudikeleti requested a review from a team as a code owner July 31, 2026 17:18
@dudikeleti
dudikeleti requested a review from cbeauchesne July 31, 2026 18:23
…reasons and evaluation timeout behavior, with new rows disabled in manifests until tracer support is ready.
…re timeout reporting. 1MB snapshot cap and notCapturedReason=timeout behavior.
…ves the setup-time negative snapshot wait so evaluation-timeout assertions rely on collected scenario output instead of a fixed sleep.
Detect delayed duplicate snapshots, validate complete backend request sizes, and avoid tracer-specific error messages. Tune probe limits and fixtures for reliable timeout and pruning coverage.
Preserve the fixture-specific scenario matrix after the orchestrator refactor and remove the unreachable legacy allowlist.
Keep the scenario categorized as dd_trace and explicitly exclude weblogs without the required fixture, preserving category semantics and the intended 14-weblog matrix.
@dudikeleti
dudikeleti force-pushed the dudik/debugger/guardrails-tests branch from 05addb3 to 05e83b5 Compare August 4, 2026 09:53
@datadog-datadog-prod-us1-2

datadog-datadog-prod-us1-2 Bot commented Aug 4, 2026

Copy link
Copy Markdown

Bits found no code fix to apply

🟢 Investigated · ⚪ No code fix needed

System Tests (nodejs, prod) / End-to-end #2 / express5 2 failed because its trace-stats payload contained no buckets; the identical Test_Time_Bucketing failure also occurred on main before this change. The remaining failures are CI timeouts, network/image-pull failures, a tracer import error, or a stale-container conflict, so no code change was made.


View in Datadog | Reviewed commit 05e83b5 · Any feedback? Reach out in #deveng-pr-agent

@grantseltzer grantseltzer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, but please take a look at few small comments.

Comment on lines +89 to +92
assert evaluation_errors, (
"Evaluation-timeout snapshot has an empty evaluationErrors[]; the tracer must "
"report that expression evaluation was aborted."
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This only checks that evaluationErrors is non-empty. Do we want to check the specific evaluation failures?

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.

We intentionally avoid checking the exact failure message because timeout wording isn’t standardized across tracers. The shared contract currently requires a populated evaluationErrors[] and no captured data.

class Test_Debugger_Snapshot_Size_Guardrail(_DebuggerSnapshotGuardrailTest):
"""RFC guardrail for the completed snapshot size."""

# Before enabling, verify this exceeds 1 MB without timing out; otherwise use a dedicated scenario or remove it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Has this been handled?

@dudikeleti dudikeleti Aug 5, 2026

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.

Yes, theoretically. The fixture is designed to exceed 1 MiB using a large string and collection. The test also requires a payload-size pruning marker, so a timeout alone cannot produce a false pass. However, it remains disabled pending per-tracer activation and end-to-end verification.

self.assert_all_probes_are_emitting()
self.assert_all_weblog_responses_ok()

for probe_id in self.probe_ids:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The for loop returns on the first probe, so any second probe is silently ignored, and the trailing raise AssertionError is only reachable when probe_ids is empty. Every probe file here has exactly one probe. Just assert that and index directly.

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.

Fixed in be6355a

Comment thread utils/_context/_scenarios/debugger.py Outdated
Comment on lines +11 to +16
def __init__(
self,
name: str,
doc: str,
weblog_env: dict[str, str | None],
) -> None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Autolint?

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.

excluded_scenarios:
- APPSEC_MISSING_RULES # C++ 1.2.0 freezes when the rules file is missing
- APPSEC_CORRUPTED_RULES # C++ 1.2.0 freezes when the rules file is corrupt
- DEBUGGER_CAPTURE_TIMEOUT

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If I'm not mistaken this scenario is used by only one test and is the only scenario of that test so this should be replaced by a manifest entry

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.

I may be missing some context here, since I’m not very familiar with this code. Based on the AI agent’s explanation, though, my understanding is that the current approach is preferable because the manifest already marks all debugger tests as irrelevant for cpp_httpd.

As I understand it, this intentionally prevents the orchestrator from scheduling the dedicated weblogs scenario without the capture-timeout fixture, while manifests only control pytest activation. Adding another manifest entry would therefore be redundant and would increase the CI matrix.

Does that reasoning make sense, or am I misunderstanding how this works?

Fail clearly when a fixture registers multiple probes instead of silently validating only the first.
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.

5 participants