rrweb-io / rrweb

record and replay the web
https://www.rrweb.io/
MIT License
16.55k stars 1.41k forks source link

TypeError in rrweb.min.js #646

Closed ozeitis closed 2 years ago

ozeitis commented 3 years ago

I get this when trying to play my events (live mode) Code below as well for help to debug.

2021-07-29 at 14 10 40

RECORDER CODE:

    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.min.css"
    />
    <script src="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.min.js"></script>
    <script>
    let events = [];

    rrweb.record({
      emit(event) {
        // push event into the events array
        events.push(event);
        //replayer.addEvent(event);
      },
      checkoutEveryNth: 100, // checkout every 100 events
    });

    // this function will send events to the backend and reset the events array
    function save() {
      const body = JSON.stringify({ events });
      events = [];
      fetch('/apiv1/events', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body,
      });
    }

    // save events every 1 seconds
    setInterval(save, 1 * 1000);
    </script>

PLAYER CODE:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
    <script>
    //init events and set live mode FOR EVERY user
    // user = IP Address
    const events = {{all_events|safe}}.flat();
    //player for the events
    const replayer = new rrweb.Replayer([], {
      liveMode: true,
    });

    replayer.startLive(1000);

    //player.addEvent({{event|safe}}) // add your events in here one by one as the come in

    // get hold of jquery
    var repeater;
    function doWork() {
      $(document).ready(function(){ //wait until page is ready
       setInterval(function() { // this will execute the function every 1s
            // Variables
            let url = "/analytics/latest"; // locaiton of your form page

            // Get
            $.get(url, function(d) { // jquery function that 'does' the GET request
               replayer.addEvent(d['events']) // when we have a returned request, populate the element above with the body of the returned request ( plain text )
            });
       }, 1000); // here we have set 1s (1000 ms)
      })
      repeater = setTimeout(doWork, 1000);
    }

    doWork();
    </script>
Yuyz0112 commented 3 years ago

Could you post your events JSON for debugging?

Looks like some of your events are undefined.

ozeitis commented 3 years ago

Could you post your events JSON for debugging?

Looks like some of your events are undefined.

Sure!

const events = [[{'type': 3, 'data': {'source': 1, 'positions': [{'x': 244, 'y': 17, 'id': 76, 'timeOffset': -1}]}, 'timestamp': 1627661208227}, {'type': 3, 'data': {'source': 0, 'texts': [], 'attributes': [], 'removes': [], 'adds': [{'parentId': 21, 'nextId': None, 'node': {'type': 2, 'tagName': 'div', 'attributes': {'id': 'cohere-overlay'}, 'childNodes': [], 'id': 5364}}]}, 'timestamp': 1627661208428}], [{'type': 3, 'data': {'source': 1, 'positions': [{'x': 253, 'y': 128, 'id': 150, 'timeOffset': -448}, {'x': 252, 'y': 203, 'id': 150, 'timeOffset': -398}, {'x': 251, 'y': 218, 'id': 150, 'timeOffset': -348}, {'x': 258, 'y': 219, 'id': 150, 'timeOffset': -297}, {'x': 408, 'y': 258, 'id': 150, 'timeOffset': -231}, {'x': 632, 'y': 313, 'id': 3773, 'timeOffset': -180}, {'x': 733, 'y': 315, 'id': 3780, 'timeOffset': -130}, {'x': 802, 'y': 269, 'id': 3730, 'timeOffset': -64}, {'x': 766, 'y': 165, 'id': 152, 'timeOffset': -14}]}, 'timestamp': 1627661208727}, {'type': 3, 'data': {'source': 1, 'positions': [{'x': 502, 'y': 60, 'id': 82, 'timeOffset': -465}, {'x': 364, 'y': 79, 'id': 150, 'timeOffset': -415}, {'x': 394, 'y': 284, 'id': 150, 'timeOffset': -365}, {'x': 520, 'y': 383, 'id': 150, 'timeOffset': -313}, {'x': 586, 'y': 366, 'id': 150, 'timeOffset': -248}, {'x': 509, 'y': 264, 'id': 150, 'timeOffset': -111}, {'x': 578, 'y': 288, 'id': 150, 'timeOffset': -48}]}, 'timestamp': 1627661209228}], [{'type': 0, 'data': {}, 'timestamp': 1627661210170}, {'type': 1, 'data': {}, 'timestamp': 1627661210861}, {'type': 4, 'data': {'href': 'http://localhost:5000/wilf', 'width': 2560, 'height': 1304}, 'timestamp': 1627661210861}, {'type': 2, 'data': {'node': {'type': 0, 'childNodes': [{'type': 1, 'name': 'html', 'publicId': '', 'systemId': '', 'id': 2}, {'type': 2, 'tagName': 'html', 'attributes': {'lang': 'en', 'data-kantu': '1'}, 'childNodes': [{'type': 2, 'tagName': 'script', 'attributes': {'type': 'text/javascript', 'async': '', 'id': 'inspsync', 'src': 'http://cdn.inspectlet.com/inspectlet.js?wid=1431149582&r=452128'}, 'childNodes': [], 'id': 4}, {'type': 2, 'tagName': 'script', 'attributes': {'type': 'text/javascript', 'async': '', 'src': 'http://cdn.heapanalytics.com/js/heap-3870805101.js'}, 'childNodes': [], 'id': 5}, {'type': 2, 'tagName': 'script', 'attributes': {'type': 'text/javascript', 'async': '', 'src': 'http://www.googletagmanager.com/gtag/js?id=G-R6STXFDLFP&l=dataLayer&cx=c'}, 'childNodes': [], 'id': 6}, {'type': 2, 'tagName': 'script', 'attributes': {'type': 'text/javascript', 'id': 'zsiqscript', 'defer': '', 'src': 'https://salesiq.zoho.com/widget'}, 'childNodes': [], 'id': 7}, {'type': 2, 'tagName': 'script', 'attributes': {'async': '', 'src': 'https://www.googletagmanager.com/gtm.js?id=GTM-53BT6PV'}, 'childNodes': [], 'id': 8}, {'type': 2, 'tagName': 'script', 'attributes': {'type': 'text/javascript', 'async': '', 'src': 'https://static.cohere.so/main.js', 'crossorigin': 'anonymous'}, 'childNodes': [], 'id': 9}, {'type': 2, 'tagName': 'script', 'attributes': {}, 'childNodes': [{'type': 3, 'textContent': 'SCRIPT_PLACEHOLDER', 'id': 11}], 'id': 10}, {'type': 5, 'textContent': ' Required meta tags ', 'id': 12}, {'type': 2, 'tagName': 'head', 'attributes': {}, 'childNodes': [{'type': 2, 'tagName': 'meta', 'attributes': {'charset': 'utf-8'}, 'childNodes': [], 'id': 14}, {'type': 3, 'textContent': '\n ', 'id': 15}, {'type': 2, 'tagName': 'meta', 'attributes': {'name': 'viewport', 'content': 'width=device-width, initial-scale=1'}, 'childNodes': [], 'id': 16}, {'type': 3, 'textContent': '\n \n', 'id': 17}, {'type': 2, 'tagName': 'link', 'attributes': {'rel': 'stylesheet', 'href': 'https://commerce.coinbase.com/v1/button.css'}, 'childNodes': [], 'id': 18}, {'type': 2, 'tagName': 'link', 'attributes': {'rel': 'stylesheet', 'href': 'https://css.zohocdn.com/salesiq/https/styles/floatbutton_1e8876aaacd501ace23a5c823c48ec53_.css'}, 'childNodes': [], 'id': 19}, {'type': 2, 'tagName': 'script', 'attributes': ...... too lng

ozeitis commented 3 years ago

2021-07-30 at 09 14 01

Here is a screenshot of me adding it to log

ozeitis commented 3 years ago

2021-07-30 at 10 07 38 Here is another small error that is present now. It seems I keep getting formatting errors? Sometimes it happens with "True" in the data as it is capitalized instead of lowercase. I am using Python/Flask so maybe it is converting the data when it hits my API?

Yuyz0112 commented 2 years ago

Yes, True/None are Python variables. You should transport standard JSON to your frontend apps to avoid these issues.