关于前端:钉钉前端如何设计前端实时分析及报警系统

26次阅读

共计 4721 个字符,预计需要花费 12 分钟才能阅读完成。

开发者工具
打造围绕开发者全生命周期的工具产品
https://developer.aliyun.com/…

对于钉钉前端

钉钉从 2014 年底守业至今,倒退极其迅速,钉钉前端监控也在相应的演进。咱们有亿级的用户和千万级的企业用户,前端产品有安卓、iOS、桌面端、小程序、H5 等,前端利用的公布也涵盖全量公布、灰度公布的状况。

亿级流量的挑战

对于这样一个亿级平台,除了做前端监控零碎之外,我置信很多小伙伴也有体感,要保障整体钉钉前端的稳定性,还须要有一些技术经营的伎俩,包含人的一些状况。咱们当初整体有 100 多个前端开发成员,而后咱们的技术模块下面有 IM、通讯录、直播、教育、文档、硬件等等十分具备 B 端属性的业务。

成绩


我先说一下咱们的成绩: 100% 笼罩了咱们明天所有的 h5 和小程序、撑持了 100 多个前端人员的监控需要。前端监控的日志量达到百亿,监控大盘个数超过 100 个,能做到线上问题一分钟感知和一分钟含糊问题定位。在人力投入下面,始终维持在两个负责人员以内,大部分状况下是我一个人为主在负责整体的一个监控状况,所以在人力投入下面,咱们的老本是绝对比拟低的。
上图中的两张趋势图是咱们监控的次要产品构造,一张是咱们的监控趋势图,另一张是咱们的业务大盘文件夹用于承载各个业务,同时,咱们有一个生产环境的对立小程序、H5 监控大盘。

演进之路

接下来我会讲一下,对于钉钉前端监控,咱们是如何对系统进行演进,拿到一个不错的后果。

思考到有很多小伙伴们不是搞前端监控的,所以这边我会先讲一些基础知识来开展如何设计一个前端监控零碎。
咱们来看一下下面这段代码,const 创立一个对象,而后 foot.a.b = c。能够看到 这是段十分经典的 NPE 代码,就是 null point exception,在前端代码中非常容易呈现。这边会抛出一个谬误: Uncaught TypeError: Cannot set property ‘b’ of undefined
对于这样一个谬误,在用户侧产生之后,咱们的前端监控零碎是怎么去捕捉这个谬误,并且在一分钟之内发现?咱们来看一下一传统的做法是怎么做的:
• 首先写一个前端监控 SDK,用于进行数据采集
• 选型一个告诉计划,将这条前端日志告诉到服务端
我这边演示的是用 image 标签,创立一个 image 标签,设置它的 src 指向对应的日志服务器来发送对应的日志。
咱们对谬误的采集采纳的是 window.onerror 来捕捉全局谬误。而后将捕捉的谬误通过创立 image 标签模式发送到上图右侧的前端监控服务端。
如上的代码只是一个伪代码演示,我写的比较简单。
对于一个传统的基于日志剖析的监控零碎,你首先要晓得这条日志到底是来自哪里,所以咱们对每一条日志在前端采集的时候,都有一个利用 id,权且我这边称之为 spmId,通过 spmId 来标识日志源,而后将这条日志存储到对应的监控服务端,这样就实现了一个非常简单的从前到后的一个链路。
日志产生、采集,而后再到存储的一个闭环 ,非常简单。其实见微知著,看到这么一个简略的实现,再把 日志类型进行丰盛,采集和存储做的弱小一点 ,基本上就能够去搭建一个比较简单的前端监控零碎了。

一般而言,一个简略的前端监控剖析零碎须要蕴含如下三个维度:
• 第 1 个是稳定性相干的 js error
• 第 2 个是性能相干的 performance
• 第 3 个是 api 成功率相干的
在监控平台,咱们须要做一些日志存储,将监控日志提供给可视化平台服务器,通过提供一些 API 服务就能够画出下面这样一个图。比方第 1 个是接口成功率。
我感觉在技术选型下面,对于很多略微有点 Node 或者服务端根底的前端同学来说,基本上能做出一个简略的 Demo。然而,这样一个看似性能很齐备的零碎,对于做前端监控来说,有没有什么问题?是不是可能满足钉钉这样一个亿级流量平台的监控需要?

上图右边展现的是咱们的开发人员接入前端监控的过程,包含开发阶段、测试阶段、上线阶段。在前端监控推广的过程中,咱们要求所有的开发人员在利用迭代上线后,要被动察看监控大盘至多 30 分钟,察看三个指标:

  1. js error
  2. performance
  3. api 成功率
    对于目前咱们 100 多个前端同学的团队规模来说,人力老本是 100 乘以 30 分钟,同时对于钉钉这个企业级产品而言,咱们对线上的稳定性要求是十分高的,对线上故障容忍度极低,因而还要求每日对线上利用进行巡检,因而人力老本十分高。
    从开发人员的体验角度看,一个开发人员查看监控的时候:第 1 个他会去可视化剖析平台下来看有没有谬误日志。这边有一个十分重要的点,就是说咱们监控剖析平台看到的日志,是不是 ” 前端页面 ” 的日志?
    不肯定是。为什么?因为对于用户来说,它不仅仅是关上了前端页面,这个前端页面背地还有容器的 webview、利用容器、运营商等。
    举个例子,咱们一个页面能够在微信的容器外面关上、能够在头条的容器外面关上、能够在钉钉容器外面关上。所以你 采集的日志源不仅仅是一个前端页面 ,还有容器的 webview,同时咱们还会面临很多的运营商。比如说咱们常常看到前端页面里插了一段广告,而后咱们还有一些手机的制造商,比方 vivo、华为等,也会在咱们的页面外面插入相干的脚本。所以监控剖析平台采集到的日志不仅仅是前端日志,他采集到的范畴实际上是前端页面对应的用户终端日志。
    个别咱们会碰到如下三种烦扰日志:
    • 第 1 个是第三方脚本注入
    • 第 2 个是容器脚本的注入
    • 第 3 个是由手机制造商脚本注入

    举个例子,如上是咱们线上的一个利用,大略 js error 率是 0.08%,对于钉钉这样的体量来说,这个错误率影响用户的数量曾经十分大了。
    咱们来看一下它对应的谬误实际上是什么?Script error,WeixinJSBridge is not defined, toutiaoJSBridge is not defined, 20 vivoNewsDetailPage,这些货色从错误信息基本上能够判断跟业务谬误根本没啥关系。
    所以咱们能够失去第 1 个论断,就是前端监控产生的一部分谬误实际上跟业务无关,这个可能跟很多人的认知是相悖的。

    咱们再来看一个问题,左图是咱们桌面端的公布曲线,钉钉是国内甚至是寰球为数不多的十分重桌面端的平台。钉钉桌面端基本上是一个礼拜或者两个礼拜一个迭代,因为桌面端的前端代码是采纳离线包的模式,因而代码的更新修复是比拟艰难的,对前端稳定性的要求十分的高。
    对于咱们明天的桌面端而言,曾经有 100 多个线上公布版本了,这么多的版本上报的日志采纳的是同一个利用 id,咱们如何去做分层监控,线上流量的不均如何做好分层监控,防止小流量的发版监控被吞没?
    这些问题在钉钉的业务场景是常常碰到的,咱们的监控颗粒度须要和前端的发版相适应,并且监控的日志须要反对更多的维度。比如说以利用和公布版本,这两个变量为单位进行监控。

    咱们再看一个案例,钉钉有几百个前端利用,每个利用报警 1 次就十分夸大了,基本上一天报警群就有 500 多条日志,刷屏景象十分重大,而且很多谬误是线上的长尾谬误。也就是它尽管有报警,然而不须要去批改等等。长尾谬误呈现的起因是我尽管修复了问题,然而用户那边不肯定齐全拜访的是最新的版本。
    所以论断 3 就是咱们监控经营的人力老本十分高,对于前端监控的要求不仅仅是要报警报进去,还须要你的报警是直观的、实时的,同时要反对一些短时敞开和谬误过滤等等伎俩。
    看完下面这三个案例后,咱们来看一下到底该如何设计一个可能服务 3 亿体量的监控零碎。

    首先,咱们先界定监控设计的指标,钉钉企业级前端监控须要做到的事件是: 一分钟感知、5 分钟定位、10 分钟复原。权且称这个监控零碎为 2.0 零碎。

    咱们对于前端监控 2.0 在 1.0 的根底上定义了如下的能力水位。
    第 1 个是要贴近理论业务,升高人力经营老本、业务方可能低成本染指。同时对于报警体系,要求做到快报警、准报警,并且反对自定义报警。咱们外部定了一个基准线,就是前端监控精度必须达到 90% 以上,人力老本必须缩小 20 分钟每一个人,并且报警和大盘须要可能反对自定义配置。

    上图是整体的监控的组件编排计划。右边是一个图例,蓝色局部代表的是 1.0 的监控组件,墨绿色的局部代表 2.0 新增的监控组件。
    自定义采集
    第 1 个在日志采集端,除了采集惯例的业务数据和监控数据之外,反对自定义采集。
    剖析智能化
    剖析智能化这一块减少了剖析可自定义的能力。
    报警实时化
    在报警实时化这一块,减少了线上 1 分钟报警和 5 分钟定位的要求。
    最要害的技术实现

    同样,蓝色局部是原有的 1.0 的一个体系,墨绿色局部是咱们新增的体系。咱们会发现在日志采集在和日志生产端,咱们减少了一个模块叫做 日志双写。
    一份日志被两个零碎所生产,一份零碎用于实时去报警,一份零碎用于去做剖析:
    • 服务器拿到日志后,一块去做存储剖析以便做一些监控报表服务;
    • 第二块引入了日志分钟计算零碎去做实时的报警。
    很多同学会感觉日志双写其实是一个十分大的零碎的节约,一份日志被两个零碎所生产了。实际上钉钉前端监控借助了阿里十分成熟的日志生产零碎和基础设施。通过日志散发两路被疾速生产,让分钟计算零碎在整个监控体系外面的编排是前置的,达到 1 分钟报警的要求,这是咱们在这一块外面最外围的一个技术思路。
    在上图的紫色虚线下方,是咱们的用户视角。用户侧触碰到的是两块,第 1 块是前端监控 SDK,咱们有 H5 和小程序的 SDK,第二块是平台,包含剖析平台和报警平台。
    实在案例

    咱们来看一个实在的案例。用户碰到了两个 js error。这两个 js error 都是前端经典的 NPE 谬误。
    第 1 个是产生在 iPad + 百度浏览器。第 2 个是产生在安卓 + 头条 webview,后果咱们会发现,咱们客户端上报过去的谬误有两种:
  4. 实在谬误: Uncaught TypeError: Cannot set property ‘b’ of undefined。
  5. 宿主注入的很多烦扰信息,比如说百度浏览器会注入 MyAppHrefLink is not defined。
    可能很多同学没有察看过。咱们是认真去排查过的。百度浏览器会注入 MyAppHrefLink is not defined。头条的也会去注入一些头条 jsBridge。
    日志达到服务端后,咱们先对 日志进行荡涤,把所有宿主的烦扰日志都过滤掉 ,确保咱们的报警零碎是生产的真正的业务产生的日志谬误。这是黄色区域的第一个模块: 日志荡涤

    接下来咱们进行日志分组,将利用 A spmId=A 和利用 B 的日志进行分组,通过利用标识 A 和 B 进行分组。将过滤过去的日志进行实时计算。
    通过这一步后,再将 日志流转到报警指标项进行实时计算 ,这个报警规定引擎下发相干的指令到 Map Reduce 对应的机器下来做一些解决。
    比方 JS Error 失败率 = JS Error 日志条数除以 PV 条数。当对日志进行计算的后果大于 6%,则进行钉钉群报警,当失败率大于 15% 则进行短信报警。

    钉钉前端监控 2.0

    监控日志

    通过将同样的流程利用到各个不同的指标项,比方 api 成功率、js error 失败率、pv 数据等咱们就能够在分钟计算零碎搭建出一套满足 1 分钟感知的监控零碎。
    报警零碎架构

    对于报警零碎,上图咱们阿里研发事业部那边的一个十分经典的监控零碎,有趣味的同学能够在 infoQ 上搜寻 sunfire 看到更具体的架构介绍,这里不做过多开展。
    整体日志架构总结

    基本上这就是我明天想要分享的,钉钉前端监控在从 1.0 演进到 2.0 的过程中,咱们是如何思考和如何落地的。这边的话我给大家略微简略总结一下:

  6. 最要害的技术思路是将日志报警组件的编排进行前置,咱们的实现是采纳日志双写到剖析零碎和报警零碎。
  7. 在报警平台反对报警规定引擎,真正做到报警自定义、报警可分级等。
  8. 对于前端而言,咱们不仅仅是前端页面,咱们更多的面对的是用户终端。
正文完
 0