chore(appsec): tag spans with refreshed rc client id - #19819
litianningdatadog wants to merge 1 commit into
Conversation
🎉 All green!🧪 All tests passed 🔄 Datadog auto-retried 1 job - 1 passed on retry 🔗 Commit SHA: b55c391 | Docs | View more details | Give us feedback! |
3e763c0 to
ff3e857
Compare
4d1e2f9 to
f070e18
Compare
ff3e857 to
25a94b2
Compare
f070e18 to
eda6c45
Compare
25a94b2 to
997466f
Compare
eda6c45 to
0369998
Compare
Codeowners resolved asResolved from the full PR diff against |
Circular import analysis
|
Dependency direction analysis
|
There was a problem hiding this comment.
Pull request overview
Updates AppSec span tagging to use the current Remote Config client ID after runtime identity refreshes.
Changes:
- Replaces cached client-ID state with an enablement flag.
- Reads the live client ID during span finalization.
- Adds tests for refreshed IDs, disabled tagging, and lazy imports.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Summary |
|---|---|
tests/appsec/appsec/test_remoteconfiguration.py |
Tests live and disabled client-ID tagging. |
tests/appsec/appsec/test_asm_request_context.py |
Verifies lazy Remote Config worker imports. |
ddtrace/internal/settings/asm.py |
Adds the tagging enablement flag. |
ddtrace/appsec/_remoteconfiguration.py |
Manages Remote Config client-ID tagging state. |
ddtrace/appsec/_asm_request_context.py |
Tags spans with the live client ID. |
Suppressed comments (2)
ddtrace/appsec/_asm_request_context.py:404
finalize_asm_envruns on every finalized AppSec request, so this function-level import performs an import-cache/module lookup on every span while RC is enabled. That adds avoidable overhead to a hot path and hides the dependency from normal module initialization; register a live client-id accessor (or client reference) duringenable_appsec_rc()and clear it indisable_appsec_rc(), then read that accessor here so the worker is not imported per request.
from ddtrace.internal.remoteconfig.worker import remoteconfig_poller
ddtrace/appsec/_remoteconfiguration.py:88
- Please add a regression assertion for the enabled-to-disabled transition here. The new test at
test_remoteconfiguration.py:297only covers the never-enabled case, so it would still pass if this assignment were removed; it does not verify that spans stop receiving_dd.rc.client_idafter AppSec RC is disabled.
asm_config._rc_client_id_enabled = False
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
BenchmarksBenchmark execution time: 2026-08-25 13:43:28 Comparing candidate commit 0369998 in PR branch Found 0 performance improvements and 2 performance regressions! Performance is the same for 82 metrics, 0 unstable metrics.
|
997466f to
6e15d59
Compare
0369998 to
e849ad0
Compare
6e15d59 to
e9a58bc
Compare
56a237b to
f38c7a7
Compare
f38c7a7 to
b55c391
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b55c391340
ℹ️ 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".
| if asm_config._rc_client_id is not None: | ||
| entry_span.set_tag(APPSEC.RC_CLIENT_ID, asm_config._rc_client_id) | ||
| if asm_config._rc_client_id_enabled: | ||
| from ddtrace.internal.remoteconfig.worker import remoteconfig_poller |
There was a problem hiding this comment.
Remove the deferred Remote Config worker import
When an AppSec request is finalized with RC tagging enabled, this imports the worker inside the hot-path function to avoid an import-time dependency, leaving _asm_request_context structurally coupled to the RC worker and even adding a test that enforces the workaround. Extract or inject a lightweight current-client-ID accessor instead; repository policy explicitly forbids leaving deferred imports in place to conceal import-graph problems.
AGENTS.md reference: AGENTS.md:L20-L21
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
I think Codex’s comment makes sense. WDYT @christophe-papazian?
| # Fetch the current id from the RC client at span finalization. asm_config only | ||
| # tracks whether AppSec RC enabled tagging; mirroring the id there would go stale | ||
| # when runtime identity refresh rebuilds the RC client. | ||
| rc_client_id = remoteconfig_poller._client.id |
There was a problem hiding this comment.
Preserve the polling client ID in forked workers
In a forked worker, the runtime-ID callback renews RemoteConfigClient.id and drops the inherited native client (client.py:142-159), while RemoteConfigPoller.reset_at_fork() disables agent polling and consumes the parent's snapshots through inherited shared memory (worker.py:144-165). Reading the renewed local id here therefore tags worker spans with a client ID that has never polled or registered with the agent, so AppSec traces from common prefork deployments cannot be correlated with the RC client that supplied their configuration; retain/expose the origin poller's ID for shared-memory consumers instead.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
I think Codex’s comment makes sense. WDYT @P403n1x87?
|
close it as it is out of the scope |
Stacked PRs:
Description
Split from #19780.
AppSec reports the Remote Config client id on spans. This PR changes span tagging to read the live Remote Config client id at span finalization instead of copying the id into
asm_configwhen AppSec RC is enabled.This is necessary because MicroVM runtime identity refresh rebuilds the Remote Config client with a fresh client id. A cached
asm_config._rc_client_idwould keep tagging spans with the old id after refresh.asm_confignow only tracks whether AppSec RC client-id tagging is enabled; the id itself comes from the current RC client so spans reflect identity refreshes.Testing
scripts/lint style ddtrace/appsec/_asm_request_context.py ddtrace/appsec/_remoteconfiguration.py ddtrace/internal/settings/asm.py tests/appsec/appsec/test_asm_request_context.py tests/appsec/appsec/test_remoteconfiguration.pygit diff --checkscripts/run-tests --venv 106f2d7 tests/appsec/appsec/test_asm_request_context.py tests/appsec/appsec/test_remoteconfiguration.py -- -- tests/appsec/appsec/test_asm_request_context.py tests/appsec/appsec/test_remoteconfiguration.pyattempted, but the riot env failed before tests due missing native extension:ModuleNotFoundError: No module named 'ddtrace.internal.native._native'Stack
Draft split branch. Stacked on the Remote Config split PR.