相对于技术开发,项目的监控上报就仿佛现实世界中的摄像头,每一个打点上报就相当于增加一个探头,努力的将监控死角去除。一个好的监控系统要有高质量的摄像头(上报SDK), 合理的探头数量(多维度数据上报),还要具备强大的视频汇总界面(监控数据大盘)。
因此,建设一个高质量的监控可视化数据大盘,可以合理的将上报数据汇总,将项目运行情况“高清”的展示到我们的眼前。
相信各位如果已经看了前一篇文章
应该会有印象我们在建设基于监控可视化大盘(没看过的建议您看一下,变身成为高手),文章发出后笔者也收到许多小伙伴私信好奇我们的大盘目前的形态和效果。
这篇文章,就是将QQ直播前端团队在监控升级改造过程中,对于监控可视化建设的实践和经验进行介绍,希望能给各位看官带来一些帮助!
想象一下,如果没有监控能力的接入,那么业务的运行状况对我们就是黑盒,完全不会感知到运行状况的好坏,也就谈不到进一步对业务性能的提升。
而对于前端开发来讲,监控能力建设更是不可或缺的一环,因为前端其实是整个业务真正要接触用户的一环,承担着对于业务效果的展示以及业务功能入口。良好的监控能力将有助于我们对于产品效果的评估,有助于保持业务运行的稳定性以及对于产品性能的提升,也对于前端依赖的其他端口如后台客户端等问题的排查起到正向的辅助作用。
因此对前端监控的平台的选择,我们保持有谨慎的尝试,不止需要有强大的监控能力,更需要对业务接入没有侵入性,也希望监控平台具备长期的稳定性,还要有足够的配套能力来辅助我们进行监控更多能力的支持。
在经过接入 badjs,aegis等多个监控sdk之后,我们选择了接入基于aegis的RUM(腾讯云监控团队公有云前端监控产品)
aegis 的前身是公司在 github 上开源的 badJS,早期主要致力于错误收集,目前 aegis 已经是是一个前端日志平台 + 监控平台,主要功能有:错误日志,历史日志,实时日志,离线日志,白名单日志,cgi 测速,页面测速,静态资源测速,返回码统计,地区统计,系统分析,平台分析,pv 统计,错误率统计,慢速cgi追踪,错误日报,质量评分,监控告警等功能。
基于aegis, 衍生出了一体化前端监控解决方案 TAM (Tencent Application Monitor)以及基于TAM的腾讯云前端监控产品RUM.
选择RUM,一方面是因为aegis丰富的监控能力,另一方面是基于目前公司对上云的大力支持,而RUM是腾讯云直接对外的产品,有着腾讯云团队的维护,产品的稳定性也有很好的保障。
总体来讲前端监控主要的目的有两个:
保证业务稳定性主要的监控方向是异常监控, 包括 JavaScript 代码错误,Promsie 错误,接口错误,资源加载错误等,这些错误大多会导致页面功能异常甚至白屏。
提升用户体验主要的监控方向则是性能监控, 包括页面的加载时间,资源加载时间,接口响应时间等,侧面反应了用户体验的好坏。
我们目前可以对监控数据进行预设条件阈值和计算公式来实时筛选,设置告警规则,通过监控平台来进行告警,接收告警后需要对本次错误日志进行进一步分析,而建设可视化的监控看板,则可以把多次的上报汇总,有利于我们把控数据细节,从根源发现问题。
因此我们对于监控可视化建设的诉求就是将SDK上报的错误监控日志以及性能监控日志数据可视化的形式展现。
监控可视化的主要优点有以下方面:
基于RUM的监控能力,并根据上文归纳出的监控可视化的诉求中主要的监控方向,我们梳理出了监控上报的可视化的数据维度,整个监控数据可以分成以下三类:
运行数据监控:目前主要是页面的PV,UV数据来评估项目的访问量级,后续可以加入对于用户操作的一些数据上报,例如项目运行时长统计,不同时段留存率统计等
异常监控数据:主要分成以下三个方面:页面执行错误、资源加载错误以及请求错误。
这三个方面又可以进一步细化
页面执行错误主要包括 js错误以及promise错误;
资源加载错误主要可以分成 js加载错误、css加载错误,图片加载错误以及音视频等资源的加载错误;
请求错误则可以分成http请求状态错误的ajax错误或是fetch错误以及请求结果错误的retcode错误等。
性能监控数据:主要可以分成整体性的页面加载耗时,在用户角度描述性能的core webvitals指标,请求耗时数据以及作为辅助的自定义测速数据。
页面加载耗时包含页面加载的整个流程,具体可以分为以下几个方面:
Core Web Vitals (核心页面指标)是一种新的速度指标,是 Google 用于衡量用户体验的页面体验信号的一部分。主要分成三个方面:
页面自定义测速是RUM的特性上报,在前面的上报数据不满足需求的场景下,用来补充自定义的业务上报耗时数据,具体的事件名称可以自定义添加,其基本的事件如下:
请求耗时统计是一个重要的性能指标,偏重项目的加过程的性能监控,上面的结果指标都会受到请求耗时的影响,主要可以分成两类,接口请求的CGI耗时以及资源加载的请求耗时。
前文介绍过, 我们最终采用Grafana进行了数据大盘的建设。Grafana是一款开源的数据可视化工具,支持众多的图表插件,可以将我们的上报数据灵活的展示成各种图表格式。
通过合适的设置,我们使用Grafana可以非常轻松的将数据转成图表(如下图)的展现形式来做到数据监控以及数据统计。
TAM平台在搭建的时候,已经搭建了Grafana的服务,将监控上报数据整理成了基于influxdb数据源格式,并且,TAM与RUM是一母同胞的兄弟产品,那么数据格式自然是一致的,通过对Grafana的后台数据服务的改造,我们成功的打通了RUM的数据,最终使得【QQ直播前端监控数据大盘】建设完成。
那么,话不多说,直接看效果!
整体效果如下:
【汇总大盘】
【详情大盘】
万丈高楼平地起,大海汹涌靠水滴
接下来我将分版块拆分,给各位看官介绍具体一下的构建过程。
通过对现有上报数据的分类,我们将数据可视化看板的建设可以主要分成三个类别
对于PV,UV这类数据,其实有着明确的时间属性,我们对于这类数据可视化的目的一是能够希望清晰的看到项目的整体数据,二是希望能看到针对每个时间段,项目PV数据的变化趋势。
因此我们选择了折线图来展现数据时间维度的变化趋势,然后图例中标明每个项目整体的数据情况,这样我们的需求都达到了满足。不同项目根据颜色来标记和区分,最后的效果如下:
根据上文对异常监控数据分类,前端主要的异常数据可以分为 JS错误,promise错误,JS加载错误,CSS加载错误,图片加载错误,AJAX或是fetch错误,retcode错误 以及某些业务场景下的音视频加载错误这八类数据。
在 RUM的时序数据上报中,直接将这这些类别的异常数据统一上报的一个数据表中,用不同的等级level字段来区分,并且,RUM中对异常情况的分类甚至更多,它还算入了手动console.error, 自定义上报错误。
和PV/UV的数据面板一样,我们对于这些异常数据的可视化,也是希望看到整体以及具体时间段的变化趋势,因此也选择了用折线图来进行可视化的展示。但是数据的区分这时候会有两个维度,一个是项目维度,另一个是level维度,如果全部都集中到一个数据面板中,那么无疑可读性会变得非常的差,因此为了保证数据可视化展示的可读性,也为了能更好的分类展示异常数据,我们可以按照异常数据的等级区分,为每一个异常等级都创建了一个折线图数据面板,不同的项目采用图例以及颜色来进行区分。
如下图所示
但这里其实是有优化的空间的,上面我们提到了,RUM的异常数据是上报到同一张数据表中,那么也就意味着如果我们按照上面的方案来建设的面板的话,需要重复的查询语句来书写八次,只是变化一下查询参数的等级值,相应的面板的其他属性设置也要重复进行八次。
身为程序员的我们知道,这绝对不是一个优雅的操作,也非常不屑这样操作(虽然这样操作简单不费脑)。
那么有没有更好的解决办法呢?
没错,有的!
Grafana 作为一个优秀的开源可视化工具,怎么能不具备设置变量的功能呢!
通过在看板中设置一个错误等级 $event_level
的变量, 然后我们将查询语句中涉及到异常等级的 level
字段引用我们设置的变量字段(看板标题中也可以进行变量的引用)
SELECT sum("count")
FROM "data_statistics"
WHERE ("instanceId" = 'rum-instanceid'
AND "level" =~ /^$event_level$/)
AND $timeFilter
GROUP BY time(5m), "id" fill(0)
ORDER BY time DESC
这样,我们就生成了一个数据看板的模板,这个模板可以随着不同的 $event_level
来进行数据的加载展示。
然后我们通过设置将错误等级变量在看板中展示出来,这样我们可以通过手动选择来控制看板内容的展示。
通过上面的设置我们已经实现了预想的功能,可以优雅的根据不同的错误等级来展示相应的异常数据的可视化,但是这样会存在一个问题, 就是如果我既想要JS错误数据的展示,又想要看到Promise错误数据的展示,甚至是其他的错误数据统一展示来进行对比,那现有的设置就不能满足了。
于是,我们将现在的设置进一步优化,将变量 $event_level
设置为可多选(Multi-value),并且将变量与面板的repeat属性相结合,规定面板横向扩展,每行可以容纳两个扩展面板
最终使得异常监控数据面板建设完成,终版的面板具备以下功能:
最终的效果如下图:
在前端项目中, 页面执行错误对于项目上报占比来讲几乎是全量的,只要页面加载并触发逻辑就会出现。
但是对于 资源加载错误 和 请求错误这两种类别来就多了些不确定性,这些类型的错误并不是百分之百会出现
错误的原因也不止一种:
我们在关注错误数量的同时,还要关注一下后两者请求的错误占比,这样才能比较全面的观察项目的运行情况
因此我们针对网络请求的异常情况,建立了错误比例的数据图表,用来综合分析项目。
异常请求错误占比情况,可视化的诉求和上面的异常错误数图表类似,可以根据时间看错误分布,也在图例中可以看到整体的平均值。
我们主要分成以下三种图表:
http status 错误
接口retcode成功率
静态资源加载错误
至此,对于异常监控数据的图表建设完成,通过变量的设置,我们能自定义控制数据的显隐,既可以从整体上看到每个项目不同时段错误的分布,也可以看到每一个项目的平均错误数据。
还可以通过错误数量和错误比例的搭配,综合起来看到项目的异常情况,清晰直观的评估项目的运行情况。
页面的性能数据指标根据RUM的上报数据,可以分成三类,页面的整体加载耗时数据,webvitals指标数据以及自定义测速数据,并且和上面两种图表有一点区别的是,关于性能的数据,业界是有阈值指标可以来衡量整体的性能情况的。
另外对于一个汇总的性能数据反馈,我们其实更主要关注的是整体性的指标数据,例如页面性能加载耗时数据里面, 我们重点关注firstScreenTiming即可,在多个项目对比的图表里关注 dnsLookup 这类的单一的指标其实并不能显示的发现问题。
因此,性能指标面板按照上面的三个维度分别进行可视化的展示时,某些维度选取了固定指标作为默认展示
如上文所言,页面加载耗时数据中,我们默认关注的指标数据是首屏耗时 firstScreenTiming(FMP),但是为了后续更加灵活的图表数据切换,我们还是设置了一个的变量,并在查询语句中引用了该变量,使得后期可以通过变量的切换来加载不同的耗时指标数据。
并且首屏耗时数据随着时间的波动变化也能从侧面反应出CDN资源的加载波动情况。于是,对于首屏加载数据,我们还是和上面的板块一致的折线图来可视化。
为了更直观的衡量出页面加载耗时的分布,我们对图表设置了三类阈值,并通过不同的颜色区分
阈值(ms) | 耗时评估 | 标记颜色 |
---|---|---|
0 ~ 2000 | 优秀 | 绿色 |
2000 ~ 5000 | 良好 | 黄色 |
> 5000 | 待提升 | 红色 |
于是最终的效果如下图
通过各项目首屏耗时的折线分布可以看出整体性的页面耗时在不同阈值区间的分布情况,图例中以表格的形式汇总出每一个项目的整体性的耗时数据。
自定义测速数据是RUM上报里面业务本身可以灵活上报的一个指标。业务可以自己定义上报测速的事件名称以及耗时,常用来精细化的分析某一个具体项目的各阶段加载情况,因此在整个汇总面板中,不同项目之间的加载事件可能是不同的,因此不能做到完全适配,并且,在汇总性的视图里面,本身也不利于去精细化分析具体某个项目的某个指标。
因此我们筛选了SDK提供的基础的测速事件作为指标,定义了页面加载自定义事件的变量来供查询语句引用,默认值为page_render,同时可以手动切换变量值加载其他数据。
自定义事件 | 描述 |
---|---|
page_start | 页面加载开始 |
main_start | 主逻辑开始 |
main_end | 主逻辑结束 |
js_ready | JS加载完成 |
css_ready | css 加载完成 |
page_render | 页面渲染完成 |
而对于面板展示的方面,对这几个自定义测速的事件,在汇总视图里面,我们把它作为了页面加载数据的一个参考,用来辅助衡量页面的加载耗时
因此,这里更加专注的是一个汇总性的数据指标,我们这里选择了用单一状态图来进行自定义事件耗时数据的展示,由于page_render的定义与首屏耗时数据几乎相同,因此也可以设置同样的阈值来进行更加明显的区分。
于是最终效果如下图:
核心web指标与上面的页面加载性能耗时侧重的角度不同,后者关注的是页面本身,而前者按照谷歌的定义,代表用户体验的不同方面,核心指标数据的关键结果, 可以一定程度的反应出用户的真实体验。除了核心指标的定义外,还给出了这些核心指标的阈值
对于core webvitals 指标数据,我们更关注整体总结性数值。想到这里,一开始根据上文自定义测速建表的经验,无脑直接就用上单一状态图。
但是由于webvitals 的指标数据不止一个!
每一个指标创建一个图表就要起码设置三个,不光排版是个难题,当项目多起来之后查看也会出现阻碍。
思来想去,要综合起来看的话还是建设在一个数据表里比较直观, 因此最终我们将webvitals的指标数据建设成 表格(table
), 这样,既能兼顾单一状态图的需求,也可以将多维度数据合并一起展示。然后搭配阈值的颜色区分
表现如下:
既然已经可以兼容多个指标维度的数据了,那么,不妨一不做二不休,于是也将FCP, FMP 也一起合并入表格中汇总展示,毕竟表格最大的功能就是方便统计数据,因此,我们进一步丰富了指标数据
效果如下:
在上面三类的性能数据面板建设中,虽然是分为页面加载时长统计,自定义测速以及以用户为主的webvitals指标三个维度,但其实都是最终结果的实际展现。
而在前端的页面项目中影响最终加载结果的耗时主要有以下两种:
因此,对于有资源请求相关的页面,衡量性能指标资源加载和请求耗时是必不可少的,于是,我们针对接口请求耗时和静态资源加载耗时分别建立了图表
对于接口的请求,我们肯定是期望越快越好,但肯定还是要在合理范围,我们对接口请求耗时的阈值设置如下:
阈值(ms) | 耗时评估 | 标记颜色 |
---|---|---|
0 ~ 800 | 优秀 | 绿色 |
800 ~ 1500 | 良好 | 黄色 |
> 1500 | 待提升 | 红色 |
搭配单一状态图良好的展示效果,最终的展示如下:
静态资源加载耗时的统计图表和接口请求耗时统计类似,单一状态图就可以有很好的展示效果,但是由于静态资源访问的数据相比接口会偏大,并且也会受到CDN的影响,阈值设置会宽容一点,因此对于静态加载的耗时阈值,有细微的调整
阈值(ms) | 耗时评估 | 标记颜色 |
---|---|---|
0 ~ 1000 | 优秀 | 绿色 |
1000 ~ 2000 | 良好 | 黄色 |
> 2000 | 待提升 | 红色 |
最终的图表效果如下:
至此,前端监控整体的的异常数据监控数据和性能数据监控就建设基本完成,接下来再进行一些细微的图表布局调整,例如尝试将接口耗时的数据与接口错误的数据进行并排展示,将静态资源耗时与静态资源加载错误数据并排展示等,这样可以进一步增加数据的一致性以及对比性。
上文介绍了建设整体监控数据数据大盘的思路方法以及效果,但是都是从整体的维度来展示数据,所有的项目之间进行的横向对比。
这种场景下,如果想要查看某一个项目具体的监控数据情况就会比较麻烦,如果在当前的整体大盘上操作,需要每一个图表都进行一次选择,才能特异性展示具体的项目监控数据,这种操作无疑会给大盘观测带来诸多不便,并且整体性大盘建设的时候侧重点并不在具体某个项目,这里可能展示也不是很全面。
那如何解决呢?
世界上没有问题是创建一个看板解决不了的,如果有,那就创建两个!(毕竟经验已经有了)
为了更加方便的查看具体项目的监控数据, 我们针对项目的详情建设了一系列的看板模板,查询语句里面全部引用具体的项目id的变量,然后通过在整体看板内设置跳转链接,携带具体的项目id, 通过这样的方式将变量传递到项目详情看板内,实现了点击链接可以直接下钻到具体的项目监控详情的功能,
具体的下钻设置原理可以看
入口集成到了汇总视图的webvitals的可视化表格中
同时,再次一不做二不休
既然已经集成了项目详情下钻的入口,为了能和RUM直接联动, 也集成了RUM日志查看的管理系统入口,这样,通过在全局观测项目运行情况后,可以点击具体的项目下钻到项目的监控详情进行专项排查,也可以直接跳转日志系统。
具体效果如下图:
项目详情的数据大盘建设主要的思路和整体的建设是一致的,也是主要分成三部分,PV/UV, 异常数据以及性能数据。但是由于是项目详情,会多出一下加载过程的数据以及更加细致的分析数据。
除了已有的首屏耗时分布图之外,还新增页面加载过程的耗时统计图,可以从整体的页面加载流程上评估各阶段的耗时数据。
我们知道,一个页面完全加载时间为TCP,DNS,SSL,TTFB,DOM解析和资源加载的时间之和, 因此这里期望的是可以做成瀑布流类型的数据。
具体效果如下
接口耗时图表和之前类似,但是因为是项目详情维度,可以直接按照颜色分类加载出每一个接口的请求耗时情况,进而可以监测每一条接口的性能情况。
具体效果如下:
静态资源耗时统计这里,本来设想是和接口耗时一样的建设逻辑,但是由于项目之间的不同,涉及到的静态资源数据量是不一致的,尤其是某些榜单类的数据,请求的静态资源数量级会非常高,因此全部都集成到折线图中会非常的耗费性能并且可视化效果不好,于是将其调整为表格的形式,按照耗时长短降序排列,这样就可以更好的观察到加载耗时较多的静态资源,有助于针对资源数据设计优化方案。
具体效果如下:
静态资源加载异常数据的展示思路与静态资源耗时统计是一样的 具体效果如下:
由于不再需要区分项目维度信息,因此这里可以直接根据错误信息的等级分类,按照不同的颜色作区分,将所有异常上报数据集成在一个图表中,需要观察某一类异常数据时也可以根据图例很方便的进行筛选,具体效果如下:
接口请求异常比例的展示在项目详情里,进行了细微的调整
将展示错误比例改为展示成功比例之后,大部分数据会集中展示在图表的上方,下方就会留出空间,然后将接口异常的上报数量展示在了图表的下方,纵坐标左右分别展示百分比和数据值
这样我们就完成了数据比例与数据值融合在一个图表里,毕竟有时候数据量小的话,单纯看比例值是不准确的,搭配好具体的数据值才能更好的评估接口质量, 具体效果如图:
并且,在接口请求异常数据这里,我们新增了接口返回错误码分布的可视化图表,毕竟有时候如果接口出现异常,有具体的错误码能更好的的分析和排查具体的错误原因。
参与过与客户端合作的项目的小伙伴一定知道,由于安卓和ios 底层的不一致,有时候某些问题可能只会出现在一端,因此错误码区分客户端也是非常重要的一部分,所以最终,接口返回错误码图表中有两个维度,一个是错误码的值,另一个是客户端的区分
具体效果如下:
监控的目的主要是为了能保证业务的稳定运行,而建设监控数据大盘则有利于我们将细碎的上报数据统一整理,构建成一个持续性,多维度的链路,有助于我们从宏观整体上观测到项目的持续运行情况,发现其中的不足亦或是暴露出的问题,从而更好的推进业务方或者是我们自身去有针对性的解决问题以及设计优化方案。
RUM丰富的上报数据加上Grafana强大的能力,让快速建设前端监控数据大盘成为了可能,我们根据已有的上报数据为基础,按照前端项目的特性进行了总结分类, 将监控大盘的建设主要分成了三大类:pv/uv, 异常监控数据图表以及性能指标图表。
以这主要的三大分类分别从整体和项目详情的角度出发,分别建设成了前端监控大盘,项目详情监控大盘,并通过Grafana的链接属性,将两个数据大盘通过变量来联系起来,实现从整体大盘可以下钻到详情大盘。
通过对前端监控数据大盘的建设,让我们更加真实的接触到了项目的上报监控数据,也更加清晰的了解到项目的运行情况。
我们利用这些数据也发现了一些目前存在的问题,例如某个依赖的业务方接口存在的性能问题,某些静态资源加载耗时过长的问题等等,通过大盘,也反推我们的项目和业务方进行了项目的优化,真正形成了一个良性的循环。
另外,目前的数据大盘远没有达到最终版,大盘的建设将会是一个持续性的工作,例如专门针对接口或是其他的报错数据,再进行一个下钻的操作,能够具体分析报错的日志数据或是单一接口的各种耗时,错误分布等等。
总之,数据大盘的建设不是目的,通过监控能够更好的提升项目质量才是目的!