文 | 元三 网易智企资深前端开发工程师前端
笔者所在的公司业务主要是为企业提供全流程的企业服务和一整套 SaaS 解决方案。对于企业服务 SaaS 产品来讲,客户完成购买并不意味着产品价值已经彻底交付,由于客户在首次购买产品时,每每须要通过一系列培训并使用后,才能真正产生价值。所以从本质上来看帮助客户解决在使用过程当中出现的问题是 B 端产品中提供的有偿服务,是产品价值链条中很是重要的一环。git
本文将着重介绍开发者排查客户反馈问题这个场景下前端日志库的应用,以及如何设计开发适用于此类场景的前端日志库。github
笔者之前是作 C 端业务出身,自然带着 C 端业务的思惟,以为前端把产品交互体验作到极致就够了。当我这个作法套用到作 SaaS 业务上,着实吃了很多亏。B 端产品和 C 端产品在付费方式的差别、购买决策人和实际使用者不一样、产品用途不一样(B 端客户购买产品的根本缘由是为了帮助企业赚钱,C 端产品购买决策有可能只是一时冲动好玩),致使 SaaS 企业经营关注的指标和 C 端产品存在较大差别,间接致使了对研发侧的导向不一样。C 端业务前端在研发资源投入上可能为了用户体验不计成本,优化网页性能以提高用户粘性,表如今移动互联网、电商等行业每每关注 DAU、MAU、GMV 等量级指标。B 端产品的核心关注大部分可否帮助客户提高效率,产品可否帮助客户达成他的工做目标、可否帮他快速达成目标比产品界面是否美观重要得多。衡量一家优秀的 SaaS 企业有一项比较重要的指标——NDR(收入留存率),对 SaaS 业务的前端开发来讲,首要解决的挑战来自如何经过软件研发工做去提高产品易用性、任务效率、服务效率等指标,从而为企业带来提升 NDR 的分子(存量客户的续费+增购)的效果。算法
B 端 | C 端 | |
---|---|---|
用户场景 | 清晰的目的,帮助企业提高效率和质量。 | 用户目的不清晰,主要是为了愉悦和消磨时间。 |
页面交互方式 | 流程严谨、低风险、高效率 | 操做简便,信息简洁,有娱乐性、社交性 |
常见付费方式 | 按年预付 | 免费 |
经常使用经营指标 | NDR、CAC | DAU、MAU、GMV |
值得一说的是,在这方面《云计算软件产品使用体验质量 度量模型及度量方法》也提出5项指标维度用于衡量产品使用体验,很是具备参考性。这些指标维度包括易用性、任务效率、满意度、一致性、页面性能。其中易用性包括易操做性、易学性、清晰性,任务效率包括功能利用率、任务完成率、任务完成耗时。基于 SaaS 产品收入可持续性的考量,SaaS 企业的目标之一是提升依靠软件产品输出价值的比重,下降依靠人工服务输出价值的比重,由于只有软件产品输出价值边际成本最低,才能不断提高产品服务效率。在这一点上,纯粹依靠人工服务终归是边际成本很是高的,所以在 SaaS 业务场景下依靠技术创新去提高解决问题的效率是前端可以提供的很是大的产品价值。数据库
当咱们把视角汇集到客户反馈问题的解决上时,能够先将客户反馈问题分为功能咨询类、问题报障类、售前咨询类。其中开发者主要关注的是问题报障类,也存在一些技术支持回答不了的功能咨询类问题会流向开发者,针对这类问题通常能够采用建设内部的问题排查系统来解决。其中前端开发者主要遇到的反馈问题既有来自于 SDK 接入这一类的咨询,也有客户认为产品功能不符合预期的问题报告。编程
针对此,前端为了有效且快速定位这些问题缘由,一方面能够在客户端打日志并上报到问题排查系统之中,另外一方面,对于 S 类 A 类客户(基于 SaaS 企业针对客户企业规模的分层模型)的紧急问题,若有必要能够迅速和客户沟通,使用远程协助之类的工具在客户的设备中复现并定位问题缘由。对于后者,咱们设计开发了基于 Chrome 浏览器 Chrome DevTools 协议的远程调试解决方案 woodpecker-remote,它可以支持网站开发者对网站用户的 Chrome 浏览器直接进行远程调试。对于前者来讲,咱们设计开发了前端日志库 woodpecker-log 以支持将客户端运行状态等信息进行持久化存储供开发者调试排查问题。后端
这里先介绍一下前端日志的概念。一般来讲通常在后端开发时常常会听到日志的概念,对后端来讲日志是指一种用于记录服务端启动、运行状态的文件。这里的前端日志指的也是用于记录客户端运行状态在客户端存储或者上传到服务器存储造成的日志文件。通常前端在开发、测试环境使用 Console 记录运行状态就够了,但在生产环境就须要将客户端日志信息发送到服务端存储起来,方便往后排查定位用户反馈问题时使用。前端工程化
上述问题中,首要解决的是日志和用户反馈问题相关度的问题。核心思路是使用客户端进行日志存储,在发生问题时由用户或者程序发现进行主动上报,而不是定时定频率上报到服务器。这里留两个问题:用户如何发现问题?程序(员)如何发现问题?另外,性能问题和JS异常也是产生客户反馈的问题来源之一,但从平常SaaS业务的客户反馈问题来源统计来看,这两块并非主要来源。另外的JS异常监控、性能监控两个领域已经有比较成熟的前端基建支持。所以,非JS异常和性能问题致使的客户反馈问题是前端日志库主要覆盖并解决的问题。浏览器
首先在开始设计以前,先思考一下,前端会如何使用日志库。有这些典型场景可能须要前端记录日志。服务器
对第3种场景,这里简单列了在程序断言为 false 时使用前端日志库记录日志的 Demo:
相比于几千行代码在单一文件内维护,将 SDK 独立成项目并采起前端工程化方式开发更具有可维护性。前端工程化是指采用模块化、组件化、规范化、自动化的技术方案从软件工程的角度解决工程的质量、可维护性问题。这里列举了一些关键技术选型:
对于 SDK 相对底层的代码来讲,Typescript 语言自然提供的类型文档具有可读性和易读性,静态类型检查能够帮助框架或库的使用者在代码运行阶段以前发现错误,智能语法感知能够提供有用的 API 类型提示。
须要考虑为 SDK 的使用者提供多种 JS 模块规范的支持,以 rollup 为例,配置以下:
在开发阶段对 SDK 的自动化测试主要关注单元测试和集成测试。单元测试是用于对模块、函数或类进行正确性检验,能够采用 jest 框架。值得注意的是,对 indexedDB 存储和查询进行单元测试时须要模拟数据库,可使用 fake-indexeddb 来 Mock。集成测试的目的是将系统之间的各个模块组装起来并使用真正的外部依赖、访问真正的 indexedDB 数据库对代码进行正确性检验。此例中咱们采用了 Karma + Mocha + chai 的方案,对 ChromeHeadless、FirefoxHeadless、Safari 浏览器进行测试。
基于语义化版本规范 semver 进行版本控制。
localStorage 适合对少许数据进行 key-value 存储,在客户端日志存储的场景中使用 indexedDB 更加合适,它具有如下优势:
假定使用 10M 容量,300bytes 的日志,能够存 34952 条;最长支持循环录制 8 天日均 4369 条。
网络性能(延迟、请求失败率)——日志长度、请求体积
日志存储前进行字符串压缩
sendBeacon
合并请求
运行性能
参数 | 类型 | 释义 | 默认值 | 是否可选 |
---|---|---|---|---|
options.appKey | String | 实例记录日志时会存储的应用名称,用于区分不一样应用记录的日志,不传时实例使用 $anonymous 做为应用名 | $anonymous | 可选 |
options.bytesQuota | Number | 设定客户端可以使用的 indexedDB 存储上限,单位为 MBytes。不一样应用共用存储上限,超出上限后,将启用循环记录功能,自动删除最先的日志 | 10 | 可选 |
options.reportUrl | String | 传入后 report 方法将使用该地址做为上报日志的服务器地址,如不传,则须要在调用 report 时指定该参数 | -- | 可选 |
options.enableSendBeacon | Boolean | 开启后使用 sendBeacon 上报日志 | FALSE | 可选 |
options.debug | Boolean | 开启后在客户端 console 控制台打印调试信息 | FALSE | 可选 |
方法 | 释义 | 示例 |
---|---|---|
trace/info/warn/error/fatal | 日志记录到客户端 | wpLog.trace(content: string); |
queryByDate | 按发生时间检索日志 | wpLog.queryByDate(startDate?: number, endDate?: number); |
queryByContent | 按关键字检索日志 | wpLog.queryByContent(content: string); |
report | 日志上报到服务器 | wpLog.report(startDate?: number, days?: number, reportUrl?: string, session?: boolean, env?: boolean); |
咱们经常须要发布前就在代码中设计好业务关键流程执行时须要打印的日志。不然,当咱们须要定位问题的时候,才发现本身并无输出相关的日志,这样就会比较被动。此时只能临时改代码加日志,从新发布。有没有一种方案,能够在遇到问题的时候,再去代码中相应位置加日志,用户执行改业务流程时就能马上打印出相关日志,而不用从新走一遍发布流程。 这里介绍一种在 woodpecker-proxy 中的实现,借助 MutationObserver 接口监听 script 插入 DOM 事件,改写浏览器 JS 请求,将其代理到目标服务器,从而实如今目标服务器修改 JS 加入日志代码便可在用户浏览器记录日志。Demo 地址:DEMO。
遵循良好规范记录的日志,有利于排查问题时可以快速根据信息级别、应用进行日志筛选。
分级别
日志级别 | 释义 |
---|---|
trace | 主要输出调试性质的内容。 |
info | 记录系统的正常运行状态,某些重要的业务处理已经结束。 |
warn | 发生这个级别问题时,处理过程能够继续,但必须对这个问题给予额外关注。 |
error | 错误发生时,已经影响了用户的正常访问,也须要立刻被处理,可是紧急程度要低于 FATAL 级别。 |
fatal | 致命错误,系统中发生了很是严重的问题,必须立刻有人进行处理。 |
分应用
因为客户端存储受同源限制,日志访问只能在自身域名下进行。多个应用可能会在同一域名下记录日志,区分应用名进行存储易于隔离不一样应用的日志信息。
增强可靠性
更直观的问题上下文环境
更友好的客户通知和告警