Mark all spans with apm billing disabled tag - #7359
Conversation
|
|
|
7fbe28c to
e674e2c
Compare
e674e2c to
42003de
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 84c13538fc
ℹ️ 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".
| : - component_version: "<3.11.0" | ||
| declaration: missing_feature (APPSEC-57830 python tracer was using MANUAL_KEEP for 1 trace in 60 seconds to keep instead of AUTO_KEEP) | ||
| weblog: *django | ||
| tests/appsec/test_asm_standalone.py::Test_AppSecStandalone_APMDisabledMarker: missing_feature |
There was a problem hiding this comment.
Enable the new marker test for supported libraries
This new test is added as missing_feature here, and the same blanket entry is added to every library manifest touched by the commit, so the APPSEC_STANDALONE CI matrix will never execute the new coverage. Several adjacent AppSec standalone classes are already enabled for released/dev versions in the same manifests, so this should use the appropriate version/weblog-specific activation instead of disabling the class everywhere.
Useful? React with 👍 / 👎.
| """Every span sent in standalone mode carries the APM-disabled billing marker.""" | ||
|
|
||
| def setup_all_spans_have_apm_disabled_marker(self) -> None: | ||
| self.r = weblog.get("/") |
There was a problem hiding this comment.
Send an AppSec event before checking standalone spans
When this class is enabled for a tracer that honors DD_APM_TRACING_ENABLED=false, a plain GET / does not create a security or upstream-kept trace, so interfaces.library.get_traces(request=self.r) can be empty and the new assert spans fails without testing the marker. Use a request that actually generates an AppSec-retained trace, such as the Arachni/v1 attack header pattern already used in this file, because setup methods are the phase that must generate the captured traces for validation. .cursor/rules/end-to-end-testing.mdcL9-L9
Useful? React with 👍 / 👎.
| def test_all_spans_have_apm_disabled_marker(self) -> None: | ||
| assert self.r.status_code == 200 | ||
|
|
||
| spans = [span for _, trace in interfaces.library.get_traces(request=self.r) for span in trace] |
There was a problem hiding this comment.
Collect delayed chunks by trace ID
For delayed trace chunks, filtering with get_traces(request=self.r) only returns chunks where some span can be matched back to the request RID; delayed child/outbound chunks can share the trace ID but lack the request user-agent tag, so they are silently skipped here. After identifying the request trace, iterate all library traces with the same trace ID before asserting the billing marker, otherwise this can pass while the delayed chunk is missing _dd.apm.enabled.
Useful? React with 👍 / 👎.
| assert spans, "No spans were sent for the request" | ||
|
|
||
| for span in spans: | ||
| apm_enabled = span["metrics"].get("_dd.apm.enabled") |
There was a problem hiding this comment.
Assert the marker on chunk roots, not every span
When the retained request emits more than one span in a trace chunk, this asserts _dd.apm.enabled on child spans too, but the change is testing a trace-chunk billing marker and trace-level markers are attached to the chunk root/first span. This can make compliant tracers fail once the test uses a multi-span or delayed-chunk endpoint; iterate the chunks and validate trace[0] for each chunk instead.
Useful? React with 👍 / 👎.
| def setup_all_spans_have_apm_disabled_marker(self) -> None: | ||
| self.r = weblog.get("/") | ||
|
|
||
| def test_all_spans_have_apm_disabled_marker(self) -> None: |
There was a problem hiding this comment.
This function should be moved to the top level and implemented in the standalone AI Guard tests as well
There was a problem hiding this comment.
Done! I have a function that I can reuse on ai guard! I'll create a follow-up for ai guard once this merged
| - weblog_declaration: | ||
| nextjs: missing_feature (endpoint not implemented) | ||
| tests/appsec/test_asm_standalone.py::Test_APISecurityStandalone: *ref_5_52_0 | ||
| tests/appsec/test_asm_standalone.py::Test_AppSecStandalone_APMDisabledMarker: missing_feature |
There was a problem hiding this comment.
Hasn't any tracer implemented this feature?
There was a problem hiding this comment.
Probably Go, I'd like too keep it missing feature and let lib owners make the changes
| """Every span sent in standalone mode carries the APM-disabled billing marker.""" | ||
|
|
||
| def setup_all_spans_have_apm_disabled_marker(self) -> None: | ||
| self.r = weblog.get("/") |
There was a problem hiding this comment.
Maybe we should create a new endpoint that generates nested spans, or makes an HTTP call, to ensure there are multiple spans and that they are all marked correctly
There was a problem hiding this comment.
My initial implementation attempted to add nested calls, but this could have different behaviour for async frameworks! well we can do it with the newest test version. probably on a follow-up
…led (#19242) APPSEC-69365 ## Summary The APM tracing disablement metric `_dd.apm.enabled:0` was only being set on the **local root span**, not on all service entry (top-level) spans. This mirrors a mistake previously made for AppSec event tagging. When APM tracing is disabled and a trace contains an inferred/child service — e.g. a sibling service entry span created for an outgoing HTTP client call — that span (`_dd.top_level:1`) was left untagged. As a result the intake metered those inferred services as having APM enabled. Reported in a customer support case (found in java and nodejs first). Also tested with DataDog/system-tests#7359 ## Change In `TraceSamplingProcessor.process_trace`, when `apm_opt_out` is set, tag every span in the trace chunk with `_dd.apm.enabled:0` instead of only the local root span. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: florentinl <florentin.labelle@datadoghq.com>
9fc2201 to
240f52a
Compare
Motivation
Adds system-test coverage for delayed trace chunks in standalone ASM, the test verifies that all spans have the tag
_dd.apm.enabled: 0.Changes
Workflow
🚀 Once your PR is reviewed and the CI green, you can merge it!
🛟 #apm-shared-testing 🛟
Reviewer checklist
tests/ormanifests/is modified ? I have the approval from R&P teambuild-XXX-imagelabel is present