阿里UC百亿级PV的前端监控平台实践
前言
Web承载的业务越来越复杂,用户对于Web的体验要求也越来越高,Web性能的优劣对业务收益也有着非常直接的影响。
阿里UC在移动Web领域深耕十年,线上业务大量承载在Web上;本文主要介绍阿里UC百亿级PV前端监控平台,岳鹰全景监控平台的实践历程,阅读时长 10 分钟。
本文篇幅较长,大家可以查阅 阿里UC百亿PV的岳鹰全景监控平台实践 系列文章,选择自己感兴趣的章节:
- 阿里UC百亿PV的前端监控平台:(1)概述
- 阿里UC百亿PV的前端监控平台:(2)前端采集上报
- 阿里UC百亿PV的前端监控平台:(3)日志存储
- 阿里UC百亿PV的前端监控平台:(4)大数据分析
- 阿里UC百亿PV的前端监控平台:(5)数据可视化
背景
为什么要打造前端监控系统?
前端的开发环境比较复杂,页面在不同浏览器、微信等APP都可能展现不同,用户的网络网速、手机性能等,也会影响页面访问速度。在移动端可能更为明显,移动端用户对页面响应延迟、页面无法使用的容忍度更低。
这些都有可能影响用户体验,从而导致业务访问量下降、用户流失等问题。
前端页面对用户体验和业务收益的重要性不言而喻。这也是我们打造前端监控系统的初衷,希望达到以下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个步骤之后,通过数据来定位解决问题的方法思路已经妥妥的存储在后端服务器;接下来要做的就是把数据可视化的呈现给开发者,让数据会说话。
实时数据
通过数据的实时展现,可以第一时间发现异常指标,并且对这一时刻的指标进行分析,例如截图中的「资源加载异常」。
趋势数据
对于页面性能这种周期指标,可以更长时间周期的观察。另外,页面性能的均值作为用户体验的衡量,还需要考虑长尾用户的体验,因此我们也提供了 页面性能区间分布的统计,可以直接定位到页面访问缓慢的日志。
分析定位
通过对数据统计聚类,发生异常的情况进行统计,从时间、地域、网络等不同维度加以统计,找出规律,找到问题影响范围进一步分析。
对于JS异常,还可以通过 source map 映射源码,快速定位到报错的具体代码。
岳鹰-WEB前端监控
经过1年左右时间的不断打磨,阿里UC出品的岳鹰WEB前端监控已经对外开放,欢迎免费体验试用。
技术交流、第一时间掌握产品动态,欢迎联系我们~
联系微信小助手(微信号 effirst-assistant)
加入钉钉群讨论(群号21964256)
参考资料
移动WEB应用路线图-性能和调优 https://www.w3.org/2018/12/web-roadmaps/mobile/performance.zh.html
前端异常处理 http://jartto.wang/2018/11/20/js-exception-handling/
监听AJAX请求 https://dsb123dsb.github.io/2017/05/02/JavaScript监听全部Ajax请求事件的方法/
Script error https://sentry.io/answers/javascript-script-error/