Skip to content

feat(rum): add rum_retention_filters_order resource - #717

Open
michael-richey wants to merge 3 commits into
michael.richey/add-rum-retention-filtersfrom
michael.richey/add-rum-retention-filters-order
Open

michael-richey wants to merge 3 commits into
michael.richey/add-rum-retention-filtersfrom
michael.richey/add-rum-retention-filters-order

Conversation

@michael-richey

Copy link
Copy Markdown
Collaborator

Summary

Per-application RUM retention filter order. The order endpoint is PATCH-only (no GET/DELETE); the source order is captured from the ordered list returned by /api/v2/rum/applications/{app_id}/retention_filters.

Stacked on #716 (rum_retention_filters).

Design

  • Keyed by application id; id (app id) and data[*].id (filter ids) are remapped via resource_connections (rum_applications, rum_retention_filters) before apply.
  • Both survive prep_resource (no excluded_attributes) so create/update can read them.
  • deep_diff_config.ignore_order=False so reordering is detected as a diff (ids already match after connect remapping, so no exclusion is needed).
  • Order is a separate resource synced after the filters exist at the destination — a pre_apply_hook runs before apply, when destination filters do not yet exist. Matches the codebase convention (logs_archives_order, sensitive_data_scanner_groups_order, logs_indexes_order, logs_pipelines_order).
  • delete_resource is a no-op (no DELETE endpoint).

Changes

  • datadog_sync/model/rum_retention_filters_order.py (new)
  • datadog_sync/models/__init__.py — register
  • tests/unit/test_rum_retention_filters_order.py (new) — 6 unit tests
  • README.md — add rum_retention_filters_order (depends on rum_applications, rum_retention_filters)

Testing

  • pytest tests/unit/test_rum_retention_filters_order.py → 6 passed
  • Full unit suite: no new failures.

Follow-up

Integration tests + VCR cassettes deferred (require sandbox-org API access).

@michael-richey michael-richey left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Nice incremental step.

The per-app order modeling and concurrent=False choice both make sense for an ordering resource, and tests cover remapping + endpoint payload shape well.

Non-blocking nit:

  • The class/test docstrings mention exclude_regex_paths for id/data[*].id, but the config currently doesn't set those exclusions. Behavior looks fine as-is because IDs are remapped before apply; this is mainly a docstring accuracy tweak if you want to align narrative with config.

No blocking issues from my side in this diff.

@michael-richey

Copy link
Copy Markdown
Collaborator Author

Thanks for the nit — fixed in e2988470. The docstring now accurately reflects the config: no exclude_regex_paths is set because ids are remapped to match the destination before the diff is computed, so no exclusion is needed. ignore_order=False remains so reordering is detected.

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

Destination-only filters must be preserved when patching the complete order relationship.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity · 1 Low severity

Open (2)
What changed in this PR

Adds per-application synchronization of RUM retention-filter ordering.

Changes:

  • Introduces the PATCH-only order resource with ID remapping.
  • Registers and documents its dependencies.
  • Adds unit coverage for retrieval, remapping, patching, and deletion behavior.
File Description
datadog_sync/​model/​rum_retention_filters_order.py Implements order synchronization.
datadog_sync/​models/​__init__.py Registers the resource model.
tests/​unit/​test_rum_retention_filters_order.py Adds model 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.

async def create_resource(self, _id: str, resource: Dict) -> Tuple[str, Dict]:
destination_client = self.config.destination_client
app_id = resource["id"]
payload = {"data": resource["data"]}
Comment on lines +14 to +16
``prep_resource`` (so create/update can read them), so they are excluded from
diffs via ``deep_diff_config.exclude_regex_paths`` rather than
``excluded_attributes``.
@michael-richey
michael-richey force-pushed the michael.richey/add-rum-retention-filters-order branch from e298847 to c2e4117 Compare September 28, 2026 14:10
@michael-richey

Copy link
Copy Markdown
Collaborator Author

Fixed in c2e41174 (two issues):

  1. Destination-only filter IDs: create_resource and update_resource now read the destination's current filter list via GET, append destination-only IDs while preserving their relative order, and PATCH the merged list — matching logs_archives_order.py, logs_indexes_order.py, and sensitive_data_scanner_groups_order.py. New test verifies destination-only IDs are appended.

  2. Test docstring: Corrected to accurately describe the deep_diff_config — no exclude_regex_paths is set because ids are remapped to match the destination before the diff is computed, so no exclusion is needed; ignore_order=False so reordering is detected.

@michael-richey
michael-richey force-pushed the michael.richey/add-rum-retention-filters-order branch from c2e4117 to 56d4b34 Compare October 1, 2026 15:54
@michael-richey

Copy link
Copy Markdown
Collaborator Author

Integration Test Finding: Cascading dependency failure from rum_retention_filters

During the full lifecycle integration test (EU1 → US5), rum_retention_filters_order failed to create with:

ERROR - [rum_retention_filters_order - b45873bb-7c62-459e-bfd2-d69bf9a8f3fe] - missing connections:
Failed to connect resource. {'rum_retention_filters': ['default_errors', 'default_sessions']}

Root cause

rum_retention_filters_order has a resource_connections dependency on rum_retention_filters:

resource_connections={
    "rum_retention_filters": [...],
}

The connection mapping requires default_errors and default_sessions to exist in state.destination["rum_retention_filters"]. However, those two filters fail to sync due to the meta.source bug on PR #716 (the source field is under meta, not attributes, so it's not stripped from the PATCH body). Because they never make it into destination state, the connection mapping for rum_retention_filters_order fails.

This is a cascading failure

Once PR #716 is fixed (stripping meta.source from the update payload), default_errors and default_sessions will sync successfully, and this cascading failure will resolve automatically.

Lifecycle test results for rum_retention_filters_order

Scenario Result Details
Create ❌ FAIL Missing connections to default_errors/default_sessions (cascading from PR #716)
Update SKIP No destination resources (create failed)
Skip SKIP No destination resources
Delete SKIP No destination resources

No code change needed on this PR — the fix is on PR #716.

@michael-richey
michael-richey force-pushed the michael.richey/add-rum-retention-filters-order branch from 56d4b34 to 221d602 Compare October 1, 2026 18:13
@michael-richey

Copy link
Copy Markdown
Collaborator Author

This is a cascading failure from PR #716 — default_errors and default_sessions failed to sync due to the meta.source bug, so they were missing from state.destination['rum_retention_filters'], causing the connection mapping to fail. Now fixed in #716 (dec60672 — meta is now stripped from the PATCH body). No code change needed on this PR.

@michael-richey
michael-richey force-pushed the michael.richey/add-rum-retention-filters branch from dec6067 to 2a81276 Compare October 1, 2026 20:37
@michael-richey
michael-richey force-pushed the michael.richey/add-rum-retention-filters-order branch from 221d602 to 390b682 Compare October 1, 2026 20:37
@michael-richey
michael-richey force-pushed the michael.richey/add-rum-retention-filters branch from 2a81276 to 6d64fe1 Compare October 1, 2026 21:17
@michael-richey
michael-richey force-pushed the michael.richey/add-rum-retention-filters-order branch from 390b682 to 48de449 Compare October 1, 2026 21:17
Per-application RUM retention filter order. The order endpoint is PATCH-only
(no GET/DELETE); the source order is captured from the ordered list returned
by /api/v2/rum/applications/{app_id}/retention_filters. The resource is keyed
by application id; id (the app id) and data[*].id (filter ids) are remapped
via resource_connections before apply, and both survive prep_resource (no
excluded_attributes) so create/update can read them. deep_diff_config uses
ignore_order=False so reordering is detected as a diff (ids already match
after connect remapping, so no exclusion is needed).

Order is a separate resource synced after the filters exist at the
destination, matching the codebase convention (logs_archives_order,
sensitive_data_scanner_groups_order, logs_indexes_order, logs_pipelines_order)
-- a pre_apply_hook would run before the destination filters exist.

- datadog_sync/model/rum_retention_filters_order.py (new)
- datadog_sync/models/__init__.py -- register
- tests/unit/test_rum_retention_filters_order.py (new) -- 6 unit tests
- README.md -- add rum_retention_filters_order (depends on rum_applications,
  rum_retention_filters)

Integration tests + VCR cassettes deferred (require sandbox-org API access).
The review nit pointed out that the docstring mentions
deep_diff_config.exclude_regex_paths for id/data[*].id, but the config
doesn't set those exclusions (they were removed during implementation
because ids are remapped to match the destination before the diff is
computed, so no exclusion is needed). Align the docstring with the actual
config.
Per review: the order PATCH sent only source-side IDs, discarding any
destination-only filters. Now reads the destination's current filter list,
appends destination-only IDs while preserving their relative order, and
uses the merged list for the PATCH (matching logs_archives_order.py,
logs_indexes_order.py, and sensitive_data_scanner_groups_order.py).

Also fixes the test docstring to accurately describe the deep_diff_config
(no exclude_regex_paths is set; ids are remapped before the diff, so no
exclusion is needed; ignore_order=False so reordering is detected).
@michael-richey
michael-richey force-pushed the michael.richey/add-rum-retention-filters branch from 6d64fe1 to e7798c9 Compare October 2, 2026 01:45
@michael-richey
michael-richey force-pushed the michael.richey/add-rum-retention-filters-order branch from 48de449 to d42eac2 Compare October 2, 2026 01:45
@michael-richey

Copy link
Copy Markdown
Collaborator Author

Good addition overall, but I think this currently inherits an ambiguity from the retention filter ids in #716.

Ordering remap needs app context

This resource connects via resource_connections={"rum_retention_filters": ["data.id"]}, which assumes each retention-filter id is globally unique in sync state.

If retention filter ids are only unique per app (e.g., built-in/default filters), then data.id alone is ambiguous across apps and can remap to the wrong destination id.

Suggested direction:

  • Align with composite retention-filter keys (<app_id>:<filter_id>), and
  • Include app context when remapping data.id (either via custom remap logic or by carrying/deriving app id into the connection mapping path).

I’d treat this as a blocker for multi-app correctness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants