feat(rum): add rum_operations resource - #719
michael-richey wants to merge 4 commits into
Conversation
michael-richey
left a comment
There was a problem hiding this comment.
Good addition.
Implementation and tests are consistent with existing model conventions:
- search endpoint read path is clear
- create/update/delete URL + payload behavior is covered
- application remapping via
resource_connectionsis tested
No new blocking issues found in this PR diff.
d79679a to
7561097
Compare
2e1c183 to
6dd8547
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The search endpoint only imports its first page, potentially omitting operations.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (1)
What changed in this PR
Adds synchronization support for Datadog RUM operation definitions and their application dependencies.
Changes:
- Implements CRUD and application-ID remapping for RUM operations.
- Registers and documents the resource.
- Adds unit coverage for core synchronization behavior.
| File | Description |
|---|---|
datadog_sync/model/rum_operations.py |
Implements the RUM operations resource model. |
datadog_sync/models/__init__.py |
Registers the model. |
tests/unit/test_rum_operations.py |
Tests CRUD and ID remapping. |
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.
| resp = await client.get(self._search_path) | ||
|
|
||
| return resp["data"] |
|
Thanks for catching this — fixed in |
7561097 to
9192e66
Compare
c279302 to
608bc96
Compare
9192e66 to
864e6dd
Compare
608bc96 to
f73ec4c
Compare
Integration Test Finding:
|
864e6dd to
b66155e
Compare
f73ec4c to
67daf21
Compare
|
Fixed in Fix: |
Re-test Results (after fix
|
|
Fixed in Fix: match by name only (operation names are unique within an org). Updated test to verify matching works even when the existing op has a different application_id than the current sync. |
b66155e to
3585b3a
Compare
fbd95da to
3a336dd
Compare
3585b3a to
a6191f3
Compare
3a336dd to
bcf4158
Compare
RUM operations are static definitions (name, display_name, category, query, journey rules) tied to a RUM application via attributes.application_id (a real body field, remapped to the destination app id via resource_connections). The query fields in the journey are RUM query filters (e.g. @type:view), not session ids, so no session-id stripping is required -- the feasibility spike confirmed operations are clean static definitions. List is via the /rum/operations/search GET endpoint; create is POST, update is PUT, delete is DELETE. Create data has no id (server-assigned); update sets id to the destination id. - datadog_sync/model/rum_operations.py (new) - datadog_sync/models/__init__.py -- register - tests/unit/test_rum_operations.py (new) -- 7 unit tests - README.md -- add rum_operations (depends on rum_applications) Integration tests + VCR cassettes deferred (require sandbox-org API access).
Per review: /rum/operations/search is paginated but get_resources only returned the first page. Switch to client.paginated_request with PaginationConfig (page[limit]=100, page[offset] incrementing by page_size) so all operations are imported, not just the first page. Test updated to verify paginated_request is used.
Per integration test: rum_operations has skip_resource_mapping=True, so the apply pre-pass never lists destination operations. On a second run, create_resource POSTs unconditionally and gets 409 Conflict. Fix: create_resource now searches the destination's operations (via the search endpoint) before POSTing. If a matching operation is found (same name + application_id), it hydrates state and delegates to update instead of creating a duplicate. New test verifies the reconciliation path.
Per integration test re-test: the reconciliation in create_resource matched by name AND application_id, but the existing destination operation has an application_id from a previous destination app (created by an earlier sync run). When state is wiped and a new destination app is created, the old operation's application_id doesn't match the new app's ID, so the match fails and the sync POSTs unconditionally (409 Conflict). Fix: match by name only (operation names are unique within an org). Updated test to verify matching works even when the existing op has a different application_id than the current sync.
a6191f3 to
46857db
Compare
bcf4158 to
dcf0952
Compare
|
Great model and tests overall. I found one blocker in the 409 reconciliation path: Reconciliation search is not paginatedOn create conflict, we do a single GET on In orgs with enough operations, the conflicting operation may be outside the first page:
Suggested fix:
I’d consider this a blocker for large-org reliability. |

Summary
RUM operations — static definitions (name, display_name, category, query, journey rules) tied to a RUM application via
attributes.application_id(a real body field, remapped to the destination app id viaresource_connections).Stacked on #718 (
rum_permanent_retention_filters).Feasibility spike result
The plan flagged a concern that operations might embed session-id references that can't be cleanly stripped. Inspection of the
RUMOperationschema confirms the opposite: thequeryfields injourney_rum.rum_stepsare RUM query filters (e.g.@type:view), not session ids. Operations are clean static definitions — no session-id stripping required.Design
/rum/operations/searchGET; create POST; update PUT/{id}; delete DELETE/{id}.id(server-assigned, popped); update setsresource["id"] = destination_id.resource_connections={"rum_applications": ["attributes.application_id"]}— application_id is a real body field, remapped viaconnect_id(no synthetic field needed).excluded_attributes:id+ server-managedcreated_at/created_by/updated_at/updated_by/org_id.Changes
datadog_sync/model/rum_operations.py(new)datadog_sync/models/__init__.py— registertests/unit/test_rum_operations.py(new) — 7 unit testsREADME.md— addrum_operations(depends onrum_applications)Testing
pytest tests/unit/test_rum_operations.py→ 7 passedFollow-up
Integration tests + VCR cassettes deferred (require sandbox-org API access).