应用实时监控 ARMS 上线用户行为回溯功能

随着前端技术日新月异迅猛发展,为了实现更好的前端性能,最大程度提高用户体验,支持单页应用的框架逐渐占领市场,如众所周知的React,Vue等等。但是在单页应用的趋势下,快速定位并解决JS错误却成为一大难题。在当下的互联网行业,对前端性能要求越来越高,前端性能监控的产品层出不穷,javascript错误诊断更是其中举足轻重的一个环节。帮助开发者排查线上bug,实现快速定位问题,高效解决问题,是我们努力的方向。

一、JS错误诊断

目前已经有了许多诸如Arms,Sentry等前端性能监控框架,都在一定程度上对JS错误诊断提供了相应的 支持,总体来说,大家的思路比较相似,可以总结为以下几个步骤:

1. 统计JS错误

每当上线一个新的产品或新的业务功能,往往伴随着一些不可避免的线上bug,这些bug发生的频率有多高、发生在什么页面、影响了多少用户等等,对于判断解决问题的优先级、帮助排查问题和优化性能来说是非常关键的。

图1是Arms前端性能监控的JS错误诊断诊断页面,可以清晰地看到错误发生的次数、影响用户数以及错误分布情况等信息,开发者可以根据这些统计数据更好地决策问题的轻重缓急,使性能优化有条不紊进行。

 

图1. JS错误总览

2. 精准定位错误

前端报错的原因有很多,网络因素、浏览器兼容性、用户操作逻辑、业务代码本身的问题等等都可能导致故障发生,在JS错误统计中我们已经知道了错误发生的页面,这在一定程度上缩小了排查范围,但这样还是不够的,我们还想要知道更多错误详情,比如:

1)现场信息

包括报错的设备、操作系统、浏览器等等,这些信息无疑可以帮助开发者更好地复现问题,进而修复bug。

 

图2. JS错误概要

2)代码追踪

利用error stack和source map来精准定位发生错误的代码位置。

 

a. 上传source map文件

b. 在代码中定位错误

图3. source map错误定位

3. 还原报错现场

还原错误发生时用户行为上下文是JS错误诊断的最后一步,也是最关键和最困难的一步。

假设以下场景:我们收到用户反馈说点了某按钮后没有反应……

面对用户反馈,我们不由得会想,没反应是什么原因呢,是点击事件的handler出错了导致接口请求没发出?还是接口挂了?或者是接口返回数据渲染失败了?

类似以上的困惑应该很多开发者都会时常遇到,我们不可能去指挥用户打开开发者工具再一步步debug给我们看,这就需要我们的前端监控平台具备还原报错现场的能力,帮助开发者了解错误发生时候的用户行为上下文,进而可以预想一下刚才的场景——

根据用户的uid等信息,我们可以回溯到该用户报错前后的一系列操作以及前端行为:
进入页面->点击按钮->发出api请求成功-> js error……

于是我们可以知道报错是发生在api请求成功后的数据处理环节,再依据步骤2中提供的错误详情快速解决问题。

二、用户行为回溯

已经有一些前端性能监控平台接入了用户行为监控,实现的方式也各有千秋,主要流程可以分为三个步骤:行为采集、行为上报、行为回溯。

1. 行为采集

1)哪些行为需要采集?

我们站在用户的立场去考虑一个单页应用的浏览周期内的可能流程:进入应用首页——加载页面内容——浏览页面内容——用户交互(鼠标交互/键盘交互等)——跳转到新页面……

要将用户行为串联成完整的行为链来为js error提供上下文,我们需要知道什么时间,什么位置,发生了什么事情。由此,以上用户浏览过程中的所有的页面行为(包括但不仅限于用户交互)可以用以下几类来大致概括:

Api请求,鼠标事件,键盘事件,路由跳转,error 等。

2)如何采集?

在确定了哪些行为需要上报以后,我们再在来看如何完成行为打点。

在过往的时代,我们有传统的手动埋点方法,它的缺点也是不言而喻的:手动埋点是容易混乱的,有时可能会出现错埋、漏埋等情况,每每上线一个新功能,需要开发团队和数据团队进行埋点沟通,徒增了时间和人力成本;其次时常因为产品排期紧张,功能急于上线,就不得不先砍掉了埋点的需求,在后续的版本更新中再补上,这使得新上线的功能得不到验证,而新上线的功能对业务和产品性能的影响都很关键。

现如今,一个好的前端监控产品需要实现“无埋点”监控,充当一双眼睛,时时刻刻监控着产品的运作情况,全量采集页面事件和用户行为,为业务分析和错误诊断都提供充足的信息。

 

图4. 用户行为采集流程图

以上流程图为Arms做行为采集的大致步骤,首先需要在正常的html页面中插入一小段js代码,即引入我们具有行为日志采集功能的SDK,如下代码所示,通过createElement(“script”)在Dom节点添加script的元素,并将SDK的js文件引入进来,用于收集用户行为,并在适当的时候上报到后端,具体方法如下代码所示,其中bl.js为SDK文件。

<script>
!(function(c,b,d,a){c[a]||(c[a]={});c[a].config={pid:"xxxxxxx",appType:"web",imgUrl:"https://arms-retcode.aliyuncs.com/r.png?"};
with(b)with(body)with(insertBefore(createElement("script"),firstChild))setAttribute("crossorigin","",src=d)
})(window,document,"https://retcode.alicdn.com/retcode/bl.js","__bl");
</script>

3)SDK中行为采集的实现

  • API行为采集
    重写原生XMLHttpRequest或fetch方法,采集必要的API信息(如url,状态码,状态message等)。
reWrite(XMLHttpRequest.send,originalSend =>function(...args){const xhr = this;function onreadystatechangeHandler(){if (xhr.readyState === 4) {//记录API行为}}if ('onreadystatechange' in xhr && typeof xhr.onreadystatechange === 'function') {reWrite(xhr.onreadystatechange, original=> function(...innerargs){//记录API行为original.apply(this, innerargs);});} else {xhr.onreadystatechange = onreadystatechangeHandler;}return originalSend.apply(this, args);
});
  • 控制台行为采集
    重写console的常见控制台输出方法,比如: log,warning,error等。
var consoleType = ['debug', 'info', 'warn', 'log', 'error', 'assert'];
for (var i = 0; consoleType.length; i++) {var type = consoleType[i];reWrite(console.type, function (orig) {var thisType = type;return function (...args) {// 添加console行为if (orig) {Function.prototype.apply.call(orig, window.console, args);}};});
}

注意,通过重写 console 对象监控浏览器控制台的打印信息,这样会导致在控制台下打印的日志无法正确看到原代码文件中的位置,console的位置会定位到SDK的代码中,可以通过配置浏览器 Blackboxing来解决。

 

图5. console定位在SDK代码中

  • 用户交互行为采集(鼠标键盘事件等): 
    可以在顶层的document上全面监听各类用户交互事件,如click,keypress,mousemove,scroll等等。但是这种方法也有一个明显的缺陷,假设用户监听了某个dom上的click事件,并且设置了event.stopPropagation(),这种情况的点击事件是无法被document监听到的,而往往这类行为对于错误诊断和业务分析都尤为重要。解决方法是在addEventListener中埋入钩子。
var bhEventHandler = function(){//记录用户行为
}
document.addEventListener('click', bhEventHandler, false);
var types = ['EventTarget', 'Node'];
for (var i = 0; i < types.length; i++) {var type = types[i];var proto = window[type] && window[type].prototype;reWrite(proto.addEventListener, function (orig) {//重写addEventListener,记录用户行为});
}
  • 路由跳转行为采集
    路由跳转无疑会触发浏览器历史记录的改变,每当处于激活状态的历史记录条目发生变化时,window的popstate事件会触发,但是调用history.pushState()或者history.replaceState()不会触发popstate事件。因此路由跳转的监控可以分为两个方面,一方面在window. onpopstate中埋入钩子,另一方面在history.pushState和history.replaceState中埋入钩子。
var origPopstate = window.onpopstate;
window.onpopstate = function () {//记录路由行为    if (origPopstate) {return origPopstate.apply(this, args);}
};
var dosomething = function (orig) {return function (...args) {//记录路由行为    return orig.apply(this, args);};
};
reWrite(window.history.pushState, dosomething);
reWrite(window.history.replaceState, dosomething);
  • js error
    全局监听js error:
window.addEventListener('error', function(event){...})

监听全局未处理的rejection:

window.addEventListener('unhandledrejection', function(event){...})

2. 行为上报

SDK采集到用户行为后,以一定的格式进行信息拼接,然后伪装成图片发送给后端。为什么要使用图片来发送日志信息而不是直接使用ajax呢?这是因为SDK的script文件和后端分析的代码可能不在相同的域内,而将image对象的src属性指向后端脚本并携带参数,可以轻松实现跨域请求。不同平台对于前端监控行为的类别都比较类似,但上报的方式还是不尽相同的,服务于不同的业务需求。以下是两种比较典型的行为上报形式:

1)持续全量上报

图6是截取的New relic的行为日志上报信息,为什么称之为持续全量上报呢?“持续”是指它的行为日志是定时上报的,每隔几秒便会上报一次,上报请求非常密集。“全量”则是指它采集的行为类型覆盖面很广,可以从上报的Request Payload中看到,它采集的不仅限于我们上面提到的一些主要的页面行为,它几乎覆盖了所有的页面事件,包括鼠标移动等等。而这种上报方式也是利弊参半:

优点:它可以更真实地还原用户在整个页面周期内的行为,保真度很高,对于还原现场来说是有一定优势的。

缺陷:首先是无差别的行为采集,这显然增大了行为日志的数据体量,在上报中对流量的消耗很大,日志存储成本也很高,而这巨大的损耗所带来的信息价值呢?几乎大部分都是鼠标移动或者滑轮滚动的大量重复信息,无论是对业务分析还是错误诊断都没有太大贡献,甚至增加了分析问题的复杂性。

其次是行为日志的频繁上报,这对业务方来说可能也是不太友好的,性能监控请求发的比本身的业务请求都多。

图6. 行为日志全量上报

2)场景触发上报

场景触发上报即是指,当符合一定条件或者场景时才上报行为日志,对于JS错误诊断中的用户行为回溯场景而言,当然就是错误触发上报,当页面监听到error时,便把当前采集到的行为列表伴随error详情一并上报,作为错误诊断的辅助信息。

行为日志伴随错误一起上报的方式需要维护一个行为队列,队列应设有最大长度,当捕获到js error的时候,将行为队列作为js错误日志的一个补充信息一起上报,图7所示为sentry错误日志上报的request payload,其用户行为队列包含在错误日志的“breadcrumbs”字段中。

这种用户行为伴随错误上报的方式就相对轻量很多,首先错误和行为一起上报减少了请求数量;其次对用户行为选择性采集,避免了大量冗余信息对流量和存储的消耗,就js错误诊断而言会使得错误现场变得更清晰,对分析错误有利。

当然这种行为上报的方式也是有不可忽视的问题,即行为和js error的强耦合,使得用户行为信息失去了业务分析的扩展性,仅适用于JS错误诊断。

图7. 行为日志breadcrumbs上报

三、用户行为回溯在js错误诊断中的应用

图8展示了Arms前端性能监控的JS错误诊断中用户行为回溯的情况,在错误详情中复原出错现场,辅助排查。下图展示了用户在进行了“接口请求-控制台输出-点击按钮-控制台输出”的一系列行为后发生了JS错误,即可从按钮的点击事件的处理函数中进行错误排查。

 

图8. Arms前端性能监控的用户行为回溯


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/518126.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android Studio 创建第一个Android工程项目

1、打开Android Studio 2、点击 New Project 选择 Empty Activity 3、点击 Next 4、点击 Finish 等待加载完成&#xff0c;取决于网络&#xff0c;第一次加载可能要很久。。。 5、下载完成 可以在右上角切换为 Project 模式 6、创建一个虚拟设备 https://www.bilibili…

我竟然混进了 Python 高级圈子!

现如今&#xff0c;计算机科学、人工智能、数据科学已成为技术发展的主要推动力。无论是要翻阅这些领域的文章&#xff0c;还是要参与相关任务&#xff0c;你马上就会遇到一些拦路虎&#xff1a;想过滤垃圾邮件&#xff0c;不具备概率论中的贝叶斯思维恐怕不行&#xff1b;想试…

Tablestore + Blink实战:交易数据的实时统计

背景 交易数据的实时统计是电商网站一个核心功能&#xff0c;可以帮助用户实时统计网站的整体销售情况&#xff0c;快速验证“新销售策略”的效果。我们今天介绍一个基于表格存储(Tablestore)实现交易数据的实时计算&#xff0c;给大家提供一个新使用方式。 Tablestore作为在…

无标注数据是鸡肋还是宝藏?阿里工程师这样用它

阿里妹导读&#xff1a;针对业务场景中标注数据不足、大量的无标注数据又难以有效利用的问题&#xff0c;我们提出了一种面向行为序列数据的深度学习风控算法 Auto Risk&#xff0c;提出通过代理任务从无标注数据中学习通用的特征表示。这种思想与目前 NLP 领域前沿的 Bert 等预…

Android 控件 - TextView

1、TextView https://www.bilibili.com/video/BV13y4y1E7pF?p3 1.1、layout_width、layout_height match_parent&#xff1a;表示让当前控件的大小和父布局的大小一样&#xff0c;也就是由父布局来决定当前控件的大小 wrap_content&#xff1a;表示让当前的控件大小能够刚好…

为什么选择Cassandra

cassandra概况 为什么选择Cassandra&#xff1f;cassandra到底有那些令人印象深刻的特点呢&#xff1f;不防我们先来看下cassandra目前的大体概况。 理论扎实&#xff0c;师出名门 cassandra不仅吸收了dynamo论文中的如何做分布式&#xff0c;如何做副本复制&#xff0c;故障…

加速开放混合云技术开发,满足客户新需求,红帽打出这套组合拳!

云计算发展有几十年的历史了&#xff0c;随着科技的进步和发展&#xff0c;云技术慢慢渗透到各行各业&#xff0c;企业上云也不再是新鲜事&#xff0c;据《2020-2026年中国云计算行业市场分析预测及战略咨询研究报告》数据显示&#xff1a;2018年&#xff0c;以IaaS、PaaS和Saa…

系统性能提升利刃 | 缓存技术使用的实践与思考

导读 按照现在流行的互联网分层架构模型&#xff0c;最简单的架构当属Web响应层DB存储层的架构。从最开始的单机混合部署Web和DB&#xff0c;到后来将二者拆分到不同物理机以避免共享机器硬件带来的性能瓶颈&#xff0c;再随着流量的增长&#xff0c;Web应用变为集群部署模式&…

Android 控件 - Button

1、Button 1.1、新建 mybutton 模块 在原有项目基础上新建 mybutton项目 1.2、Button基础 在源码中Button继承TextView&#xff0c;所以TextView有的功能Button基本都有&#xff0c;重复功能不在赘述 1.2.1 设置button背景颜色 当使用background不起作用时&#xff0c…

通过SQL即可让监控分析更简单更高效

1.前言 阿里时序时空数据库TSDB最新推出TSQL&#xff0c;支持标准SQL的语法和函数。用户使用熟悉的SQL&#xff0c;不仅仅查询更简单易用&#xff0c;用户还可以利用SQL强大的功能&#xff0c;实现更加复杂的计算分析。 2. 为什么需要用SQL做时序查询&#xff1f; 2.1 SQL拥…

深度好文 | 战“疫”上云正当时:打开云计算的正确姿势

作者 | 马超责编 | Carol封图 | CSDN 付费下载于视觉中国4月29日&#xff0c;谷歌的母公司Alphabet正式发布了2020年第一季度财报&#xff0c;报告显示&#xff0c;Alphabet比去年同期的363.39亿美元增长13%&#xff0c;不计入汇率变动的影响为同比增长15%&#xff1b;在业绩公…

Windows批处理文件(.bat文件和.cmd文件)简单使用

cmd文件和bat文件的区别&#xff0c;从文件描述中的区别是&#xff0c;cmd文件叫做&#xff1a;Windows命令脚本&#xff0c;bat文件叫&#xff1a;批处理文件&#xff0c;两者都可以使用任意一款文本编辑器进行创建、编辑和修改&#xff0c;只是在cmd中支持的命令要多于bat。 …

AnalyticDB for MySQL:PB级云数仓核心技术和场景解析

2019阿里云峰会上海开发者大会于7月24日盛大开幕&#xff0c;本次峰会与未来世界的开发者们分享开源大数据、IT基础设施云化、数据库、云原生、物联网等领域的技术干货&#xff0c;共同探讨前沿科技趋势。本文整理自数据库专场中阿里云智能高级技术专家南仙的精彩演讲&#xff…

UML科普文,一篇文章掌握14种UML图

来源 | 如逆水行舟责编 | Carol封图 | CSDN 付费下载于视觉中国什么是UML&#xff1f;UML是Unified Model Language的缩写&#xff0c;中文是统一建模语言&#xff0c;是由一整套图表组成的标准化建模语言。为什么要用UML&#xff1f;通过使用UML使得在软件开发之前&#xff0c…

企业级数据库新型研发模式——数据管理DMS实践

2019阿里云峰会上海开发者大会于7月24日盛大开幕&#xff0c;本次峰会与未来世界的开发者们分享开源大数据、IT基础设施云化、数据库、云原生、物联网等领域的技术干货&#xff0c;共同探讨前沿科技趋势。本文整理自数据库专场中阿里云智能技术专家王天振 (为知)的精彩演讲&…

linux-centos7环境搭建

1、下载centos7 官网地址&#xff1a; http://isoredirect.centos.org/centos/7/isos/x86_64/ 阿里云&#xff1a; http://mirrors.aliyun.com/centos/ 以下针对各个版本的ISO镜像文件&#xff0c;进行一一说明&#xff1a; CentOS-7-x86_64-DVD-1708.iso 标准安装版&#x…

揭秘!机器人和你对话时在想什么?

阿里妹导读&#xff1a;为什么聊天机器人越来越普及&#xff1f;聊天机器人不仅可以节省时间&#xff0c;提升效率&#xff0c;还能一天24小时提供服务&#xff0c;更是可以减少误差。聊天机器人背后的问题原理是什么&#xff1f;效率如何提升&#xff1f;就是今天我们要了解的…

阿里云与A站在一起后,悄悄干了件大事

八月盛夏&#xff0c;“AcFun弹幕视频网站”&#xff08;简称“A站”&#xff09;的视频服务器全面迁移上阿里云&#xff08;此处应有掌声&#xff09;&#xff01; A站去年与阿里云达成此项合作。在迁移过程中&#xff0c;阿里云提供专业技术解决方案团队&#xff0c;为A站建立…

科大讯飞营收破百亿,员工涨薪27%,羡慕这个AI“老大哥”​了!

科大讯飞&#xff0c;中国AI公司“老大哥”&#xff0c;交出2019年成绩单。营收达到100.79亿&#xff0c;首次破百亿&#xff1b;净利润同比增长51.12%&#xff0c;达到8.19亿&#xff0c;日均盈利224万元&#xff0c;创下历史最佳业绩。与此同时&#xff0c;5大厂2020年应届生…

Knative Serving 之路由管理和 Ingress

Knative 默认会为每一个 Service 生成一个域名&#xff0c;并且 Istio Gateway 要根据域名判断当前的请求应该转发给哪个 Knative Service。Knative 默认使用的主域名是 example.com&#xff0c;这个域名是不能作为线上服务的。本文我首先介绍一下如何修改 默认主域名&#xff…