Repository navigation
feat(rum): add rum_permanent_retention_filters resource - #718
michael-richey wants to merge 5 commits into
Conversation
michael-richey
left a comment
There was a problem hiding this comment.
Thanks for adding this model + coverage. I did find one blocking correctness issue:
Blocking: key collision across applications for permanent filters
import_resource() returns resource["id"] as the state key. For permanent filters, IDs are fixed/system-defined (synthetics_sessions, etc.) and repeat under every app. That means imports from multiple apps collide in state.source[self.resource_type][_id], so only the last app survives.
Concretely, with two apps both containing synthetics_sessions, state ends up with a single key:
- imported
synthetics_sessionsfrom app A - imported
synthetics_sessionsfrom app B - final state key set:
['synthetics_sessions'](app A overwritten)
This breaks multi-app sync for rum_permanent_retention_filters.
Suggested fix
Use a composite key for this resource type (e.g. "{application_id}:{filter_id}") for import/state indexing, while keeping payload data.id as the server filter id.
That preserves per-app cardinality and keeps create/update/delete URL construction unambiguous.
Happy to re-review after this is addressed.
d79679a to
7561097
Compare
|
Thanks for catching this — fixed in |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Excluding the parent application ID from diffs can skip configuration after a destination application is recreated.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
What changed in this PR
Adds synchronization support for application-scoped permanent RUM retention filters.
Changes:
- Adds PATCH-only resource handling with composite state keys.
- Registers and documents the resource and dependency.
- Adds unit coverage for retrieval, updates, remapping, and deletion behavior.
| File | Description |
|---|---|
datadog_sync/model/rum_permanent_retention_filters.py |
Implements the resource model. |
datadog_sync/models/__init__.py |
Registers the model. |
tests/unit/test_rum_permanent_retention_filters.py |
Adds unit tests. |
README.md |
Documents support and dependencies. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
e298847 to
c2e4117
Compare
7561097 to
9192e66
Compare
|
Fixed in |
Integration Test Findings (EU1 → US5 sync)Ran a full integration test: imported all RUM resources from the EU1 internal testing org, then synced to the US5 internal testing org. Found 1 failure in
|
c2e4117 to
56d4b34
Compare
9192e66 to
864e6dd
Compare
|
Fixed in |
Re-test Results (after fix
|
56d4b34 to
221d602
Compare
864e6dd to
b66155e
Compare
|
Fixed in Fix: removed |
221d602 to
390b682
Compare
b66155e to
3585b3a
Compare
390b682 to
48de449
Compare
3585b3a to
a6191f3
Compare
Permanent RUM retention filters are system-defined with fixed ids (rum_apm_flat_sampling, synthetics_sessions, forced_replay_sessions) identical across orgs, so the filter id needs no remapping -- only the parent application id does. The endpoint set is PATCH-only (no POST/DELETE), so create_resource delegates to update_resource and delete_resource is a no-op, mirroring logs_archances_order. Parent-scoped like rum_retention_filters: synthetic _application_id injected during enumeration, remapped via resource_connections, kept out of excluded_attributes (must survive prep_resource) and excluded from diffs via deep_diff_config.exclude_regex_paths. Only attributes.cross_product_sampling is updatable, so attributes.name/description/editability are excluded. - datadog_sync/model/rum_permanent_retention_filters.py (new) - datadog_sync/models/__init__.py -- register - tests/unit/test_rum_permanent_retention_filters.py (new) -- 6 unit tests - README.md -- add rum_permanent_retention_filters (depends on rum_applications) Integration tests + VCR cassettes deferred (require sandbox-org API access).
BLOCKING fix per review: permanent filter IDs are fixed/system-defined
(synthetics_sessions, rum_apm_flat_sampling, forced_replay_sessions) and
repeat under every application. Using resource['id'] as the state key
caused collisions when multiple apps were synced -- only the last app
survived.
Fix: use a composite key '{application_id}:{filter_id}' for state indexing.
The payload data.id remains the server filter id. update_resource now uses
the resource's id and _application_id directly (the id is fixed across orgs,
and _application_id was remapped by connect_resources) instead of looking
up state, simplifying the first-create path.
Per review: excluding _application_id from the diff hid a real parent remap. If a destination RUM application is deleted and recreated, the parent ID changes but persisted state still references the old ID; the exclusion made the sync skip the PATCH, leaving the new application's permanent filters at their defaults. Now _application_id participates in the diff so a changed parent mapping forces the PATCH. Added regression test verifying _application_id is not in exclude_regex_paths.
Per integration test findings (EU1 -> US5 sync): rum_apm_flat_sampling (400 'trace fields are not editable for the rum_apm_flat_sampling filter'): the API rejects PATCHes that include cross_product_sampling.trace_sample_rate or trace_enabled when editability.trace_editable is false. update_resource now checks the editability.trace_editable flag and strips trace_sample_rate and trace_enabled from cross_product_sampling when the flag is false, so only non-trace attributes are sent in the PATCH body. Two new tests: one verifying trace fields are stripped when trace_editable=false, one verifying they are kept when trace_editable=true.
Per integration test re-test: attributes.editability was in excluded_attributes, so prep_resource stripped it before update_resource could read editability.trace_editable. The trace fields were never stripped, causing 400 on rum_apm_flat_sampling (trace_editable=false). Fix: removed attributes.editability from excluded_attributes so it survives prep_resource. Added editability to deep_diff_config.exclude_regex_paths so it doesn't cause a perpetual diff (it's read-only). Two new regression tests verify editability is not excluded but is excluded from diffs.
48de449 to
d42eac2
Compare
a6191f3 to
46857db
Compare
|
Nice work on this one. Highlights:
No blocking issues from my side. |

Summary
Permanent RUM retention filters — system-defined with fixed ids (
rum_apm_flat_sampling,synthetics_sessions,forced_replay_sessions) identical across orgs, so the filter id needs no remapping; only the parent application id does. PATCH-only (no POST/DELETE):create_resourcedelegates toupdate_resource,delete_resourceis a no-op (mirrorslogs_archives_order).Stacked on #717 (
rum_retention_filters_order).Design
rum_retention_filters: synthetic_application_idinjected during enumeration, remapped viaresource_connections, kept out ofexcluded_attributes(must surviveprep_resource), excluded from diffs viadeep_diff_config.exclude_regex_paths.attributes.cross_product_samplingis updatable, soattributes.name/description/editabilityare inexcluded_attributes(removed by prep, not needed for update).Changes
datadog_sync/model/rum_permanent_retention_filters.py(new)datadog_sync/models/__init__.py— registertests/unit/test_rum_permanent_retention_filters.py(new) — 6 unit testsREADME.md— addrum_permanent_retention_filters(depends onrum_applications)Testing
pytest tests/unit/test_rum_permanent_retention_filters.py→ 6 passedFollow-up
Integration tests + VCR cassettes deferred (require sandbox-org API access).