zoukankan      html  css  js  c++  java
  • 前端日志埋点优化

    前一段时间查看前端日志监控的时候发现,有很多关键业务节点埋点及用户行为轨迹数据丢失,而且丢失率达到16%这么高,梳理了一下工程里的前端埋点逻辑及方法,发现存在很大漏洞,做了一期优化,使得日志丢失率不足0.1%,使用了浏览器提供的发送保障的更简洁的sendBeacon方法,以下是对sendBeacon方法的一些理解

    用户卸载网页的时候,有时需要向服务器发一些数据。很自然的做法是在unload事件或beforeunload事件的监听函数里面,使用XMLHttpRequest对象发送数据。但是,这样做不是很可靠,因为XMLHttpRequest对象是异步发送,很可能在它即将发送的时候,页面已经卸载了,从而导致发送取消或者发送失败。 解决方法就是 AJAX 通信改成同步发送,即只有发送完成,页面才能卸载。但是,很多浏览器已经不支持同步的 XMLHttpRequest 对象了(即open()方法的第三个参数为false)

    window.addEventListener('unload', logData, false);
    
    function logData() {
      var client = new XMLHttpRequest();
      // 第三个参数表示同步发送
      client.open('POST', '/log', false);
      client.setRequestHeader('Content-Type', 'text/plain;charset=UTF-8');
      client.send(analyticsData);
    }

    上面代码指定XMLHttpRequest同步发送,很多浏览器都已经不支持这种写法。

    而且将XMLHttpRequest同步发送,会延迟页面的卸载及下一个页面的载入,性能非常的差

    同步通信有几种变通的方法:

    1、一种做法是新建一个<img>元素,数据放在src属性,作为 URL 的查询字符串,这时浏览器会等待图片加载完成(服务器回应),再进行卸载。

    使用new Image有可能遇到aborted,导致无法成功发送

    2、另一种做法是创建一个循环,规定执行时间为几秒钟,在这几秒钟内把数据发出去,然后再卸载页面。

    这些做法的共同问题是,由于同步请求的阻塞,卸载的时间被硬生生拖长了,后面页面的加载被推迟了,用户体验不好。

    navigator.sendBeacon() 方法可用于通过HTTP将少量数据异步传输到Web服务器。

    navigator.sendBeacon(url, data);

    为了解决这个问题,浏览器来提供发送保障的更简洁的sendBeacon方法。sendBeacon是异步的,不会影响当前页到下一个页面的跳转速度,且不受同域限制。这个方法还是异步发出请求,但是请求与当前页面脱离关联,作为浏览器的任务,因此可以保证会把数据发出去,不拖延卸载流程。

    window.addEventListener('unload', logData, false);
    
    function logData() {
      navigator.sendBeacon('/log', analyticsData);
    }

    Navigator.sendBeacon方法接受两个参数,第一个参数是目标服务器的 URL,第二个参数是所要发送的数据(可选),可以是任意类型(字符串、表单对象、二进制对象等等)。

    sendBeacon 如果成功进入浏览器的发送队列后,会返回true;如果受到队列总数、数据大小的限制后,会返回false。返回ture后,只是表示进入了发送队列,浏览器会尽力保证发送成功,但是否成功了,不会再有任何返回值。目前暂无具体的数据长度限制标准。

    navigator.sendBeacon(url, data)
    // HTML 代码如下
    // <body "analytics('start')" οnunlοad="analytics('end')">
    
    function analytics(state) {
      if (!navigator.sendBeacon) return;
    
      var URL = 'http://example.com/analytics';
      var data = 'state=' + state + '&location=' + window.location;
      navigator.sendBeacon(URL, data);
    }

     sendBeacon() 方法存在的意义:

    使用 sendBeacon() 方法会使用户代理在有机会时异步地向服务器发送数据,同时不会延迟页面的卸载或影响下一导航的载入性能。这就解决了提交分析数据时的所有的问题:数据可靠,传输异步并且不会影响下一页面的加载。此外,代码实际上还要比其他技术简单许多。

    最新的浏览器兼容情况:

    考虑到对目前浏览器的支持情况,需要做一下降级支持(如同步模式下的xhr,如果不是同域则要支持CORS):

    navigator.sendBeacon || new Function('var xhr=new XMLHttpRequest();
    xhr.open("POST",arguments[0],true);r.send(arguments[1]);');
    
    example:
    function SendBeacon(src)
         if (typeof(navigator.sendBeacon) == "function") {
              var b = new Blob([], {type: 'application/x-www-form-urlencoded'});
              return navigator.sendBeacon(src, b);
         }
         return false;
     
    }

  • 相关阅读:
    [转]HSPICE软件的应用及常见问题解决
    Node.js基于Express框架搭建一个简单的注册登录Web功能
    Node.js开发Web后台服务
    mysql update 将一个表某字段设为另一个表某字段的值
    一个最简的Thinkphp3.2 操作Mongodb的例子
    MongoDB GUI( Robo 3T) Shell使用及操作
    Robomongo,Mongo可视化工具
    thinkphp mysql和mongodb 完美使用
    大型网站系统架构演化之路
    30个php操作redis常用方法代码例子
  • 原文地址:https://www.cnblogs.com/katydids/p/12200623.html
Copyright © 2011-2022 走看看