🐛 Align session-ended WebSocket teardown with the latest view's end clocks - #4911
Conversation
Bundles Sizes Evolution
|
🎉 All green!🧪 All tests passed 🎯 Code Coverage (details) 🔗 Commit SHA: 79de282 | Docs | Datadog PR Page | Give us feedback! |
700d262 to
79de282
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 79de282d72
ℹ️ 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".
| const associatedView = intakeRegistry.rumViewEvents.find((event) => event.view.id === closedVital!.view.id) | ||
| expect(associatedView).toBeDefined() | ||
|
|
||
| const viewEndTime = associatedView!.date + associatedView!.view.time_spent / NANOSECONDS_PER_MILLISECOND | ||
| expect(closedVital!.date).toBeLessThanOrEqual(viewEndTime) | ||
| expect(wsWithSessionEnd!.resource.websocket.end_time).toBeLessThanOrEqual(viewEndTime) |
There was a problem hiding this comment.
🥜 nitpick: Do we need to check that? I guess ensuring that we are collecting the closing vital should be enough for an e2e scenario
There was a problem hiding this comment.
It doesn't cost us much to have this and it prevents any regression where the vital is emitted with an incoherent timestamp.
Motivation
When a RUM session expires, open WebSocket connections are finalized with
tracking_end_reason: 'session_end'. The teardown usedclocksNow()independently in bothtrackViews(to end the active view) andwebSocketCollection(to close the websocket vital/resource). Because these two calls happened at slightly different times, the websocket'send_timecould land after the view'send_time— causing thewebsocket-closedvital to be dropped during assembly and the resource'send_timeto fall outside the lifespan of the view it was attached to.Changes
SessionExpiredEventtype ({ endClocks: ClocksState }) carried on theSESSION_EXPIREDlifecycle event, instead ofvoid.startRumnow capturesclocksNow()once when the session expires and notifiesSESSION_EXPIREDwith those clocks, so every subscriber ends things at the exact same instant.trackViewsends the current view using the sharedendClocksfromSESSION_EXPIREDinstead of computing its own.webSocketCollection.flushOpenConnectionsnow accepts an optionalendClocksparam, using the shared clocks passed onSESSION_EXPIRED(falling back toclocksNow()for its ownstop()call, where no shared clocks exist).SessionExpiredEventpayload and the wired session-end path instartRum,trackViews, andwebSocketCollection.websocket-closedvital and resourceend_timedo not exceed the associated view's end time.Test instructions
Checklist