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

Throttling/pausing of Mutation Events #221

Closed
eoghanmurray opened this issue May 25, 2020 · 7 comments
Closed

Throttling/pausing of Mutation Events #221

eoghanmurray opened this issue May 25, 2020 · 7 comments

Comments

@eoghanmurray
Copy link
Contributor

I'm just wondering whether there has been any effort, or rejected effort, to add throttling and/or grouping to the MutationObserver.

I'm recording a website which has an image carousel which transitions images via a setInterval script, so every second, dozens of new mutation events are being generated without any user actions.
All the mutations are happening on the style attribute, so there's quite a lot of commonality between the events, which suggests a few different 'packing' strategies, but before delving into this level of complexity, I'm wondering whether an API method to pause mutation tracking would be useful?

This could be triggered by e.g. https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API so that if a user isn't actually on the page, then mutation events will be batched up until they return.

@eoghanmurray
Copy link
Contributor Author

Have started some prep work for this in #223

@Yuyz0112
Copy link
Member

@eoghanmurray This will be one of the most exciting features for rrweb! I will start to review your patch today. Thanks a lot!

@eoghanmurray
Copy link
Contributor Author

Part 2 is in #224 which builds upon #223

@eoghanmurray
Copy link
Contributor Author

I've gone for adding a new API method freezePage (sitting alongside the only other one addCustomEvent). Here's some sample code of how this could be used

var pause_timeout = false;
    
rrwebRecord({
    emit: function(event) {
        if (!(event.type == 3 && event.data.source == 0)) {
            if (pause_timeout) {
                clearTimeout(pause_timeout);
            }
            pause_timeout = setTimeout(function(){
                // stop recording page mutations after 10s of inactivity
                rrwebRecord.freezePage();
            }, 10000);
        }
        
         ///  ... rest of emission code
    },
});

function handleVisibilityChange() {
    if (document.hidden) {
        rrwebRecord.addCustomEvent('window-hidden');
        rrwebRecord.freezePage();
    } else {
        rrwebRecord.addCustomEvent('window-visible');
    }
}

// Warn if the browser doesn't support addEventListener or the Page Visibility API
if (typeof document.addEventListener === "undefined" || is_hidden_attr === undefined) {
    //pass
} else {
    document.addEventListener('visibilitychange', handleVisibilityChange, false);
}

@eoghanmurray
Copy link
Contributor Author

Let me know if you think the above behavior should be made into a config setting, e.g.

autofreezeOnBlur: boolean = false;
autofreezeAfterSeconds: float = -1;

@Yuyz0112
Copy link
Member

Hi @eoghanmurray, thanks a lot for the PRs.

Would you like to explain more about the full plan of doing this? Like the data structure, events, browser API, etc.

@eoghanmurray
Copy link
Contributor Author

So the only other possible change would be to create a separate Page Visibility observer, which could e.g. set a class/state on the <iframe> which could be used by the replayer to indicate that the page is not currently visible to the end user. I feel like that's a separate proposal though.

Otherwise, there's not much more to it; the changes I've made in #224 enables me to do all the things we need to achieve (see sample code above)
The idea with 'config settings' is that users of rrweb wouldn't have to use the new freezePage method, but that the logic could be moved into rrweb and behaviour enabled in config, e.g.
setting autofreezonBlur: true to call freezePage whenever the document is hidden.
or setting autofreezeAfterSeconds to 10 would enable the pause_timeout functionality shown in the sample above.

I've sketched out where these config changes could go in statcounter@9f24c10

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

No branches or pull requests

3 participants