Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Allow to configure triggerFullSnapshotOnMutation #58

Closed
wants to merge 4 commits into from

Conversation

mydea
Copy link
Member

@mydea mydea commented Feb 22, 2023

as a kind of follow-up to #55, this allows to configure an optional callback which can control if a mutation should result in a full snapshot or not.

We can leverage this in replay to:

  1. Log how many mutations are contained in a mutation set
  2. Potentially control to do full checkouts in certain times

@mydea mydea requested review from billyvg and Lms24 February 22, 2023 14:54
@mydea mydea self-assigned this Feb 22, 2023
@mydea mydea changed the title Fn/mutations filter feat: Allow to configure triggerFullSnapshotOnMutation Feb 22, 2023
@@ -109,7 +109,18 @@ export function initMutationObserver(
}

const observer = new mutationObserverCtor(
callbackWrapper(mutationBuffer.processMutations.bind(mutationBuffer)),
callbackWrapper((mutations) => {
if (options.triggerFullSnapshotOnMutation && options.triggerFullSnapshotOnMutation(mutations)) {
Copy link
Member

Choose a reason for hiding this comment

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

I wonder how frequent the mutation observer fires - we may want to split this into 2 configurations so that we're not calling a function for every mutation callback and only call it when it hits the mutation limit.

I think we should also only call the callback when limit is hit and not perform any side-effects, let the callback define the behavior when limit is hit, and then use the return value of the callback to determine if we should continue to process mutations or not.

I see the API as something like this:

record({
 maxMutations: 1000,
 onMaxMutations: (mutations) => {
   createBreadcrumb(...);
   record.takeFullSnapshot(false);
   return true; // skip processing mutations
 },
});

(ugh, API would be cleaner with just a callback though)

Copy link
Member Author

Choose a reason for hiding this comment

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

I see what you mean, but I think the impact wouldn't really be different, would it? As at run time you'd either do:

// How expensive this is depends on what `myCallback` does
// if you just do `mutations.length > 500` it should be pretty cheap
if( myCallback()) {
  record.takeFullSnapshot();
  return;
}

vs.

if (mutations.length > maxMutations) {
  const res = onMaxMutations();
  if(res) {
    return;
  }
}

--> as long as triggerFullSnapshotOnMutation is just (mutations) => mutations.length > 500, IMHO the frist will be "cheaper" or basically the same. Of course, if we put more logic in there, not necessarily 😅

Overall, considering how many things are happening in this mutation handler in rrweb already, I think whatever we're adding here is probably rather insignificant (e.g. one or two checks vs. iterating over 10s or thousands of mutations etc).

Mostly I try to think about this in the way of "what is most likely to be accepted if we upstream this", and honestly I'm not quite sure 😅 I think the callback only adds a smaller API surface, and is a bit more generic. What you suggested can maybe be a bit better optimized. 🤔

Copy link
Member

Choose a reason for hiding this comment

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

The difference is the extra function call, which is likely neglible and why I'm wondering generally how often the mutation observer callback gets called. But since by default callback will be undefined, this shouldn't matter for most users. And for us, like you said, this will not matter compared to the rest of rrweb. So let's do the onMutation callback approach imo

Copy link
Member Author

Choose a reason for hiding this comment

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

👍 so we're good to go with this PR from your perspective?

Copy link
Member

Choose a reason for hiding this comment

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

@mydea I think we should only add a generic callback and not have rrweb trigger fullsnapshot (let the SDK decide that).

Copy link
Member Author

Choose a reason for hiding this comment

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

ah, ok, I see - so just a callback to opt out of processing the mutations overall. I'll adjust this!

@Lms24
Copy link
Member

Lms24 commented Feb 24, 2023

potentially fixes getsentry/sentry-javascript#6946 once we use the callback in the SDK (just linking the issue)

@mydea
Copy link
Member Author

mydea commented Feb 28, 2023

Closing in favor of #70

@mydea mydea closed this Feb 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants