✨ add beforeSend event filtering and scrubbing#177
Conversation
|
@codex review |
There was a problem hiding this comment.
PR Review — Score: 4.4 / 5
This is a strong, well-scoped feature addition. The shared RumEventMapper is wired at the right boundary—after format hooks assemble main-process and renderer events, but before ServerRumEvent emission—so filtered events skip transport and main-process view counters. The clone-and-allowlist approach mirrors Browser SDK semantics, protects view/crash events, bypasses internal view_update payloads, and is backed by thorough unit, e2e, and playground coverage plus clear customer docs. I would approve.
Why 4.4: Solid architecture, defensive scrubbing (sanitize, type-checked allowlist), fail-open error handling, explicit tests for edge cases (throws, protected events, unknown event types), and documentation that calls out Electron-specific limitations (no raw DOM/XHR context, renderer counter staleness).
Why not 5: A few integrator-facing behaviors are implicit rather than documented (session activity on filtered clicks; only explicit false discards), and deepClone on every mapped event is a latent perf cost for very high-volume apps.
Findings
- [Minor] Filtered clicks still renew session —
END_USER_ACTIVITYis emitted beforebeforeSend, so discarding renderer click events does not suppress session keep-alive/renewal side effects. - [Minor] Only explicit
falsedrops events —undefinedand other non-falsereturn values keep the event, which is reasonable but slightly at odds with thebooleantype/docs. - [Nit] Default mapper in constructors —
MainAssembly/RendererPipelinedefault tonew RumEventMapper()withoutconfig.beforeSend; onlyinit()passes the shared configured instance.
Architectural flow
sequenceDiagram
participant Src as Main RawEvent or Renderer IPC
participant Hooks as Format Hooks
participant Mapper as RumEventMapper
participant Out as ServerRumEvent / Transport
Src->>Hooks: triggerRum(source, eventType)
Hooks->>Mapper: fully assembled RumEvent
Mapper->>Mapper: deepClone + beforeSend on clone
alt explicit false and droppable type
Mapper-->>Out: discarded (no ServerRumEvent)
else keep or scrub
Mapper->>Mapper: copy allowlisted fields + sanitize
Mapper->>Out: emit ServerRumEvent
end
Before: RUM events flowed from assembly straight to transport once hooks enriched them.
After: Both MainAssembly and RendererPipeline share one RumEventMapper configured from init({ beforeSend }). Customers can scrub allowlisted fields or return false to drop events after all Electron context is attached; view, crash, and internal view_update events are protected. Telemetry, profiles, and spans are unchanged.
Sent by Cursor Automation: electron-sdk reviews
| return event; | ||
| } | ||
|
|
||
| event.context ??= {}; |
There was a problem hiding this comment.
This mutates the live event object before cloning (adding {} when context was absent). It is needed so allowlisted context writes round-trip, but it does mean beforeSend is not a pure read on the pre-mapper object. Worth a brief code comment if this trips future maintainers.
| private eventManager: EventManager, | ||
| private hooks: FormatHooks | ||
| private hooks: FormatHooks, | ||
| private rumEventMapper = new RumEventMapper() |
There was a problem hiding this comment.
The default new RumEventMapper() here (and in RendererPipeline) silently ignores config.beforeSend unless callers pass the shared mapper from init(). Fine for the public path today, but easy to footgun in future internal wiring—consider requiring the mapper parameter or threading config.
|
|
||
| Renderer events have already passed through any `beforeSend` configured in the renderer's Browser SDK. The Electron callback runs afterward, once main-process context is added. It can run multiple times for the same view as its metrics change; internal `view_update` payloads are not exposed. | ||
|
|
||
| Renderer view counters are computed by the Browser SDK before events reach the main process, so filtering a renderer event here does not retroactively adjust those counters. |
There was a problem hiding this comment.
You already document renderer view-counter staleness. Consider also noting that filtering renderer click actions still emits internal session activity (END_USER_ACTIVITY) so sessions can renew even when the click RUM event is discarded—this is tested in RendererPipeline.spec.ts and may surprise integrators.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 10244b5bd0
ℹ️ 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".


Motivation
Allow applications to filter and scrub RUM events before they are sent.
Changes
Adds a
beforeSendconfiguration callback for main and renderer RUM events, with documentation, playground controls, and test coverage.Test instructions
yarn test:unityarn test:e2eyarn --cwd playground testChecklist