网易云音乐大前端监控产品(代号:Corona)支持 Web、React Native、Node.js、Flutter、Android、iOS、Windows CEF 多种应用类型。当前已接入了网易集团包括云音乐在内数十个事业部的大前端应用,为业务提供异常、性能监控、问题排查、实时告警等能力。
背景介绍
Corona 异常监控部分的产品研发是从 2020 年初开始的,当时云音乐大前端团队内不同的职能使用着不同的开源 or 商用监控产品。
前端团队私有化部署了 Sentry
;Android 团队同时接入了网易集团的云捕和腾讯的 bugly
;iOS 团队主要使用 Google 的 Firebase Crashlytics
;桌面端团队(Window CEF 应用)则没有平台型的监控产品,上报异常日志后再使用 breakpad
工具解析日志来排查问题。
这些割裂的产品在实际业务使用中存在如下问题,导致未能有效的度量应用质量、发现和治理线上问题:
- 无效日志问题,大前端 - 特别是 Web 应用运行环境复杂,有很多异常日志都是运行环境导致的而非代码逻辑 bug,并不影响用户,比如各种第三方浏览器注入的代码、插件注入的代码、弱网导致的请求失败、爬虫引发的报错等,这些日志严重干扰了开发者排查问题的效率;
- 告警问题,不同产品告警功能的设计差异很大,有的是应用整体基线类告警,有的是单问题视角的趋势告警等等,无法制定统一的告警闭环策略;
- 流程闭环问题,团队规模大了之后,依赖复杂的研发流程才能高效运转,离散的监控产品开放能力参差不一,成为了流程中的断点;
- 查询分析能力,在排查疑难问题时,需要特定维度下精确的事件数和影响用户数、时间趋势,以及此维度下其他特征维度的分布情况,这一能力在其他产品中都是缺失的;
- 自定义上报能力,业务特殊的运行状态需要主动上报自定义日志进行监控,并给出趋势、维度分布等统计数据,并具备告警能力,这在其他产品中都比较薄弱;
- 复杂问题的排查,需要联动其他业务埋点、网络日志等跨平台组合上下文进行分析;
- 业务视角的质量、体验度量,需要跨应用类型、综合多平台的日志做大数据分析,这和以上「复杂问题的排查」都需要原始日志成为团队可完全掌控的数据资产;
而且随着云音乐开始推进 React Native 跨端技术栈后,不同职能角色的边界被打破了,大前端团队也做了合并,割裂的监控产品对职能角色融合、合作、研发流程的收敛造成了很大的阻碍。于是建设一个跨多职能角色的、覆盖所有业务形态的、产品能力和数据资产掌握在团队自己手中的监控产品就此展开。
非功能设计
监控产品的价值是快速发现异常、快速定位问题以及辅助应用修复故障、提升质量与性能。同时考虑到集团内事业部众多,在通用性基础上也要具备一定的业务数据定制化处理。为了做到这些,我们对 Corona 的非功能设计做了如下要求:
- 实时性高:在异常发现、处理过程中,信息的价值会随着时间锐减;
- 全量数据:产品定位是从异常监控领域切入,不放过每一条异常日志;
- 高可用:必须比被监控的应用更稳定,才能在应用无法正常运行时告诉开发者发生了什么;
- 高吞吐:要有超强的日志处理吞吐能力;
- 故障容忍:Corona 本身的 SDK 以及服务不应该影响业务正常运转;
- 可扩展:特殊服务节点可插拔、可替换设计;
为了达到以上技术目标,我们对整个系统的架构设计如下:
其中:
①
是日志上报、接收、采集的链路。云音乐的日志上报服务对接了内部其他中台服务,可以根据日志携带的 cookie 解析出用户 id 等业务属性的信息,这对后续排查具体问题很有帮助。因此这个服务节点也被设计为可替换的,替换为其他事业部的中台服务从而在日志中自动塞入更多业务属性的信息。
②
是在多次突发大流量导致系统崩溃后加入的分流服务。该服务会识别异常、性能、流量日志然后分流到不同的应用层消费服务中去,其中异常日志消费服务实时性最高、日志流量最小;性能日志消费服务流量最大、对实时性要求最低;应用流量计算服务实时性高、日志流量居中。分流后可以确保 3 种日志消费服务互相解耦,不会因为一种日志突增而导致所有服务都挂掉,也能根据不同的日志的流量大小、消费成本配置合理的服务器资源,达到降本的目的。
③
是针对异常日志消费服务的设计。异常日志消费服务是一个近似实时的批处理任务,设计有等同于上游消息队列分区数的消费进程,每一个进程会积累 30s 的日志量或者 3000 条日志后进行批量消费(30s 和 3000 条是由配置中心下发的),这个配置可以随着日志流量的变化调整,在实时性与服务器负载之间取舍。将消费服务设计为近似实时的批任务也是为了降低数据库操作的 TPS,提升日志消费服务的稳定性,极端情况下即使日志流量突增百倍,MySQL 和 ES 的写入 TPS 只会增加数倍。
④
是中心化的日志过滤功能,目的有两个,一是紧急应对突然出现的流量高峰,保证稳定性;二是为用户提供过滤服务,使用户可以很便捷的丢弃噪声数据。过滤配置在应用层的消费服务节点和数据链路层的日志分流服务节点均可以生效。消费进程从 kafka 订阅到日志后,会读取配置并判断是否要丢弃,但是当线上日志量突增了百倍千倍后,已经到达并发消费能力的上限,仅仅执行过滤计算都已经变成了 cpu 密集型操作,这个时候就可以在更前置的分流服务节点配置丢弃日志,保证应用层服务稳定。
⑤
是将能异步实现的功能都通过定时任务来实现,比如告警检测、日志的错误类型分析、反混淆等等,使得同步处理链路最精简,同时及时这些异步任务挂了,也不会影响监控主流程的服务,只是部分功能缺失。
⑥
将原始日志存储到 HBase,作为数据资产备份,同时开放给业务自助分析、或者其他平台进行用户链路分析。其他存储中间件的数据作为 Corona 的私有资产,为具体产品功能提供服务,只通过开放接口进行查询。
Corona 与其他开源 or 商业化产品在架构设计上的核心差异可总结为以下两点:
- 增强存储层的能力,多数据引擎 + 冗余存储,为应用层复杂功能设计和数据开放提供支撑;
- 轻量化数据采集,重数据链路和消费层的设计,比如不同类型日志的分流、独立消费链路、日志过滤、特征信息提取、堆栈解析等,使得大部分新功能的上线、变更无需接入的应用升级 SDK;
篇幅有限,对于 Corona 平台的整体架构就介绍到这里,未来会对具体节点单独写文章展开介绍,敬请期待。
适配多端的日志协议
Corona 定义了适配多端的、可扩展的日志协议,各端 SDK 采集并生成符合该协议的日志。
Corona 定位是适配大前端多端技术栈的监控产品,不同技术栈应用的编程语言、研发流程、运行方式等等都有很大的差异,对于线上异常的分析、解决流程也不尽相同。Corona 设计了可扩展的日志协议,配合多态设计模式的软件架构,实现对不同技术栈的适配以及新应用类型的快速接入。
不同技术栈的应用对一个异常事件描述的差异,本质上是数据结构的差异,大前端领域编程语言的不同并不会导致监控功能的变化。Corona 的日志协议解构如下:
异常对象 是一条异常日志的最小核心单元,多端一致,由异常类型、异常描述和异常堆栈 3 部分组成,消费服务的主链路即是对异常对象做解析、聚合处理。同时应用层查询服务会提供此最小核心单元 精确搜索
和 模糊搜索
两种查询能力。
特征维度数据 用于完整描述异常发生时的环境信息,例如图中所示的日志时间、设备型号、应用版本、操作系统等等基础信息,同时也会针对不同技术栈的应用采集独有的特征信息,比如:
-
React Native 应用
,bundle 包版本,RN 框架版本等 -
Android 应用
,是否 root,应用下载渠道等 -
Node.js 应用
,Node 版本,主机名等
应用层的查询服务会提供所有特征维度数据 精确搜索
和 分布统计
两种查询能力。
上下文扩展数据 用于补充描述异常发生时的上下文信息,帮助开发者还原现场、定位问题。包括但不局限于:
-
Web 应用
,异常发生前的用户行为数据,点击、请求、页面跳转、控制台输出等信息; -
Android 应用
,异常发生时的系统运行状态,内存占用、CPU 负载等; -
iOS 应用
,异常发生时的系统日志;
这部分数据支持用户侧高度自定义,跟随异常日志上报,平台侧只做关联展示,查询服务不提供针对其内容的模糊搜索能力。
可扩展的日志协议配合多态模式的软件架构,使同一个功能在不同技术栈应用上有差异化实现方式,最终使用户在产品侧体验一致。
例如异常堆栈的源码还原功能,用户在平台侧可以体验到 Corona 在 Web、Node.js、React Native 应用中均提供了如右图一致的源码还原功能,但实际上在整个系统的 Client 层和 Server 层,针对不同应用类型对源码还原的实现是完全差异化的。
Web 应用在构建时由打包工具产出 SourceMap 文件上传至 CDN,同时在打包后的资源中记录该文件和对应的 SourceMap 文件的映射关系,JS SDK 捕获异常日志上报后,消费服务会解析堆栈并下载线上 js 文件,然后根据映射关系下载 SourceMap 文件,最后根据堆栈记录的行列号找出对应的源码,存储后提供后前端展示。
Node.js 应用的 SDK 在捕获到异常时,会直接解析堆栈并读取堆栈中关联的、发生异常的文件,根据行列号截取源码片段,作为附加信息携带在异常日志中上报。消费服务仅做存储后提供给前端展示。
React Native 应用的源码还原过程类似 Web 应用,在消费服务中下载 bundle 文件后根据异常堆栈记录的行列号查找源码片段。
各端 SDK 的设计未来会单独写文章展开介绍,敬请期待。
功能设计
在面向用户的功能设计上,把目标抽象如下:
- 具备一个监控产品核心的能力,比如异常捕获、异常分析、可视化界面、告警等;
- 能支持云音乐所有大前端技术栈的应用;
- 能满足大型研发团队协同使用;
在综合了各职能团队使用不同监控产品中积累的问题后,以异常监控为例,我们为 Corona 划分了如下 10 大功能模块进行具象化的设计。
这些功能模块都已经产品中上线,接下来从用户视角做简单预览:
1.应用实时质量指标、趋势
数据延迟约 1 分钟,提供应用维度整体的质量指标以及时间维度的趋势数据。
2.异常精准聚合
- 解析上报堆栈,识别关键信息,聚合;
- 自动计算聚合后异常的趋势、时间范围、版本范围、影响用户数等关键信息;
3.中心化数据去噪
误上报的日志,不影响应用功能的、由环境导致的异常等,可在平台上中心化的自定义过滤规则,作用粒度可达到单条日志级别;
过滤规则实时生效,无需下发至应用。
4.特征信息提取及分布统计
帮助用户在大量异常日志中快速找到共性的特征。
5.精确搜索能力
Corona 提供多种特征值的精确搜索能力和针对堆栈信息的模糊搜索能力。
相比 firebase、bugly、Sentry 等同类产品,Corona 的精确搜索能力体现在,无论是应用还是聚合 issue 维度的指标、趋势,都会随着搜索条件精确计算。
6.堆栈解析
无论哪种应用,Corona 均支持对堆栈进行解析使之成为可读堆栈,或是采用 SourceMap 方案,或是支持反混淆,或是符号化解析。
所有的解析过程均提供自动化的流程,诸如 mapping 文件、符号表等对接一次即可。
7.多维、多通道告警以及告警抑制
多维告警
- 阈值告警模型:作用于单条异常 issue,连续时间内数量超过一定值时触发;
- 环比告警模型:作用于单条异常 issue,数量突增触发;
- 基线模型:应用 or 应用版本的异常率超过基线时触发;
多通道
- 邮件
- popo
- 短信
告警抑制
- 高频抑制
- 梯度抑制
8.自定义上报
按照上文数据传输协议,Corona 对所有应用类型均开放自定义上报的能力,用户可用于新增埋点辅助分析疑难问题,也可以用于增加业务属性的指标。
9.状态流转、用户交互、工单机制
Corona 具备 gitlab issue 的分配、评论功能,评论支持 markdown 格式书写,小型团队可使用此功能实现异常的闭环处理。
大型研发团队,Corona 支持对接工单系统进行建单。
10.前沿探索型功能-AI 分析
Corona 会跟进业界一些具备实用价值的技术热点,比如 ChatGPT,为用户带来更快捷的堆栈分析、信息检索。