阿里UC百亿级PV的前端监控平台实践

阿里UC百亿级PV的前端监控平台实践

前言

Web承载的业务越来越复杂,用户对于Web的体验要求也越来越高,Web性能的优劣对业务收益也有着非常直接的影响。

阿里UC在移动Web领域深耕十年,线上业务大量承载在Web上;本文主要介绍阿里UC百亿级PV前端监控平台,岳鹰全景监控平台的实践历程,阅读时长 10 分钟。

本文篇幅较长,大家可以查阅 阿里UC百亿PV的岳鹰全景监控平台实践 系列文章,选择自己感兴趣的章节:


背景

为什么要打造前端监控系统?

前端的开发环境比较复杂,页面在不同浏览器、微信等APP都可能展现不同,用户的网络网速、手机性能等,也会影响页面访问速度。在移动端可能更为明显,移动端用户对页面响应延迟、页面无法使用的容忍度更低。

这些都有可能影响用户体验,从而导致业务访问量下降、用户流失等问题。

(来自FEX的统计)

前端页面对用户体验和业务收益的重要性不言而喻。这也是我们打造前端监控系统的初衷,希望达到以下3点效果。

  • 获取用户的使用产品的相关数据和体验
  • 当前端页面出现异常时,能第一时间通知到研发负责人,定位和解决问题,及时止损
  • 获取用户使用产品的真实体验,并以监控数据为基础,指导页面的优化方向。

前端监控包括哪些内容,如何打造?

一般而言,一个监控系统大致包括四个阶段:日志采集上报、日志存储、统计与分析、数据展示。下文会从这 4个阶段展开阐述岳鹰前端监控平台的实践过程。

  • 采集上报

收集性能和异常日志,在本地做一定的处理过滤等,将数据上报到服务器。

  • 日志存储

后端接收前端上报日志后会鉴权、过滤、清洗后存储入库,用于用户查看分析问题;一般选择搜索数据库和时序数据库。

  • 统计分析

通过预设的条件和规则,对存储的日志信息进行统计和筛选,用于用户进一步的分析规律找到问题根因。

  • 数据展示

通过提供一个可视化的数据面板,让用户可以看到统计趋势数据和具体日志信息,提供丰富的分析、对比、OLAP,更快速的定位和解决问题。

采集上报

日志采集

日志采集是打造前端监控系统最关键的第一步。采集日志的准确性,是平台不漏报不误报的核心;日志信息的完整性,直接影响开发者能否获取到关键错误代码来解决问题。

对于前端而言,一般的监控指标都会包含 页面性能、JS异常,资源加载异常;而前端页面通常还需要请求后端服务器数据,因此需要把API请求失败也监控起来,从而覆盖页面访问的全过程。

  • 前端异常

前端异常包括JS异常、资源加载异常、API请求异常。其中JS异常种类繁多,分为 JS语法错误、代码运行时异常、异步执行Promise异常、跨域 Script error等。对于这些异常问题,浏览器给开发者提供了对应的API,下面表格总结了采集前端异常问题的常见方案和优缺点。

浏览器提供的API繁多而且面向场景各有不同,因此使用上较为繁琐,容易踩坑。经过我们实践,以上方案可以捕获大部分常见的前端异常,效果比较符合预期。

  • 页面性能

对于页面性能的采集,常见的方案是通过 performance.timing API 获取;最新的浏览器提供了更高API等级的 performance .getEntriesByType('navigation') API 。其中,值得重点关注的是浏览器对于W3C最新标准的实现,包括FP、FMP、FCP 等指标的演进,另外就是SPA页面的监控,有兴趣可以查看我们的这篇文章 《10分钟彻底搞懂前端页面性能监控》

  • PVUV

PVUV日志采集相对简单,关键点在于采集时机,通常选择在head执行或者onload事件回调,从前端监控的角度我们通常选择 onload 时机;另外,需要考虑SPA页面的支持。

除了上述指标日志的采集,通常我们还会上报更多的环境信息,有利于更快速的定位问题。具体字段有 网络环境,设备型号,操作系统版本,客户端版本,前端版本,API接口版本等。

日志上报

上报的环节分为 上报前的处理,上报请求。

最简单粗暴的做法可能是直接写一个AJAX请求上报,但这种方式成功率不稳定,极易在页面切换时丢失日志;并且,对于大流量站点还需要考虑 带宽节流等诉求。完整考虑,一个相对完善的上报逻辑需要包括 数据过滤、截断、采样、合并以及加密压缩等大量细节设计。

如果你的采集上报脚本部署域名和前端页面域名不同,很可能遇到 Script Error 的问题。具体解决办法上文有提到,这里就不展开了。

日志清洗存储

日志采集上报到服务器,接下来需要在服务端清洗存储,用于后续问题的查询分析。对于小应用,可能用数据库单库单表加索引优化就足够了。而一个成规模甚至大流量的应用,需要建设更稳定、高效的日志监控服务,就得在日志存储架构上下一些功夫。

目前业界有不少比较完备的日志存储方案,主要有Hbase系和Lucene系,应用在监控领域比较有代表性的有 时序数据库 OpenTSDB 和 全文检索搜索引擎 Elasticsearch

在数据存储阶段,核心的使用场景在于 不同数据维度的灵活查询,逐层分析对比各个维度的数据快速定位到问题,而这恰好可以利用elasticsearch的检索特性,因此我们选择使用elasticsearch作为主要的存储方案。

即使对于一个最小集合的elasticsearch集群,也可以比较轻松实现每天千万级别的日志量的存储和查询。而在每天上亿甚至几十亿日志的场景下,日志存储系统就需要通过一些架构设计来解决 数据量大,数据结构不规律,写入并发高,查询统计需求大等特性带来的问题。

在我们的实践场景下,通过利用 批量写入、写入缓冲、表设计(按照时间/业务扩展)等索引设计和优化,可以实现 每天100亿级别的日志存储秒级查询,并且随时通过横向扩展实现扩容。具体方案业界上也比较成熟,这里就不再做更多讨论。

数据统计分析

获取到数据仅仅是第一步,一个极致的监控系统需要沉淀有效的分析方法,帮忙开发者高效的定位和解决问题。

基于Elasticsearch存储的日志,可以非常方便的聚合各种维度报表;在海量数据的场景下,还可以引入Spark Streaming等实时计算引擎达到「1分钟实时分析」,更快速的发现问题,把问题影响面控制到最小。

这里介绍的更多是我们如何通过自动的聚类和维度统计,提供一套高效的监控分析手段。对于数据分析,我们分为大盘分析和单用户分析,大盘分析指的是通过各个维度快速识别 规模性的问题,而单用户分析则是分析 单点问题的利器。

大盘分析

时间维度

按照时间线的粒度,通常可以分为 分钟级别、小时级别、天级别的统计;对于异常问题,分钟级别的时间粒度统计,可以在问题发生的第一时间通知到开发者;而对于性能这种周期指标,通过小时和天级别的时间粒度统计,可以观察更长时间的变化趋势。

运行环境维度

前端页面的运行环境,例如网络类型、运营商、地域,操作系统,设备机型信息等。为什么运行环境维度的分析也这么重要?页面加载的大量静态资源和AJAX请求都需要经过网络运营商、CDN厂商,劫持、网络/CDN抖动、资源404等情况比比皆是。

细粒度的代码追踪

JS异常的代码栈顶信息,定位到发生异常的代码位置和异常堆栈;API请求异常的响应错误码和响应内容,定位到具体的API错误类型和原因。毫无疑问这是开发者解决问题是最需要等信息了。

单用户分析

一个异常是怎么发生的,需要将异常操作的前后时间线串联起来观察。它不单单涉及一次用户操作,甚至不限于某一个页面,而是一连串事件的表现。

通过将用户访问过程的异常和请求日志连接起来,形成用户访问页面的时序,以动态的效果输出发生异常的过程;并且可以把业务的关键节点也关联起来,例如页面的点击操作等。这样可以提供非常详细的现场还原效果,在解决具体用户遇到的错误时非常有效。

数据展示

经过数据清洗存储、统计分析这2个步骤之后,通过数据来定位解决问题的方法思路已经妥妥的存储在后端服务器;接下来要做的就是把数据可视化的呈现给开发者,让数据会说话。

实时数据

通过数据的实时展现,可以第一时间发现异常指标,并且对这一时刻的指标进行分析,例如截图中的「资源加载异常」。

图1:实时大盘


图2:定位到这一分钟的资源加载异常


趋势数据

对于页面性能这种周期指标,可以更长时间周期的观察。另外,页面性能的均值作为用户体验的衡量,还需要考虑长尾用户的体验,因此我们也提供了 页面性能区间分布的统计,可以直接定位到页面访问缓慢的日志。

图1:页面性能趋势
图2:页面性能样本分布

分析定位

通过对数据统计聚类,发生异常的情况进行统计,从时间、地域、网络等不同维度加以统计,找出规律,找到问题影响范围进一步分析。

对于JS异常,还可以通过 source map 映射源码,快速定位到报错的具体代码。

图1:维度统计分析
图2:source map

岳鹰-WEB前端监控

经过1年左右时间的不断打磨,阿里UC出品的岳鹰WEB前端监控已经对外开放,欢迎免费体验试用。


技术交流、第一时间掌握产品动态,欢迎联系我们~

联系微信小助手(微信号 effirst-assistant)


加入钉钉群讨论(群号21964256)



参考资料

评估关键渲染路径 developers.google.com/w

移动WEB应用路线图-性能和调优 w3.org/2018/12/web-road

前端异常处理 jartto.wang/2018/11/20/

监听AJAX请求 https://dsb123dsb.github.io/2017/05/02/JavaScript监听全部Ajax请求事件的方法/

Script error sentry.io/answers/javas

编辑于 2019-10-29 10:14

文章被以下专栏收录