你尚未登录,仅允许查看本站部分内容。请登录使用邀请码注册
kericw

logline,来自腾讯的前端日志工具 2个回复 专栏 @ Javascript

kericw 发布于 7 月前

原文:http://kezhen.info/2016/10/29/logline-logs-for-the-frontends/
项目:https://github.com/latel/logline

从事Web前端同学对此肯定深有体会,代码发出去之后,犹如脱缰的野马,运行在万千的客户终端上,等到产品和后台反馈问题到我们这边,很多时候定位问题只能靠猜,尤其是一些偶发诱因,因为根本不知道用户是如何操作的,真实环境遇到的问题通常是很多随机因素叠加的形成的,因此很难回放用户的操作来还原现场找到原因。

现在的痛点

  • 用户反馈问题后,虽然我们查询了js报错日志和cgi调用,但是并没有发现任何错误,我们根本不知道用户的终端上到底发生了什么。
  • 目前使用的js错误上报系统,看到上报有一定的延时,作为一款金融产品,分秒必争,这短暂的延时可能是致命的,我们必须快速的找到原因并予以修复。

经过一段时间经验的累积,我们想到,如果我们有一个同后台一样详实的可分类和检索的代码运行日志,无疑将会提供巨大的帮助。

我们的探索

一个健壮的日志系统大致包含日志记录、日志上传和日志分析三个主要部分,在这次的实践中,我们对这三方面都有所探索。

日志到底存哪里?

由于前端受到很多限制,不能同APP一样可以在文件沙箱内存取文件,因此如何持久化的存储日志成了一个问题。目前H5也支持若干种本地存储方案,cookie, localStorage, indexedDB和websql等,其他的由插件提供的能力不在考虑的范围之类,如flash,移动端的可用性会是一个很大的问题。

  • Cookie

    不用想,应该没有人会考虑吧, Cookie的原则应该是尽可能的精简避免浪费带宽。

  • localStorage

    localStorage大家应该都很熟悉,一个简单的键值存储系统,接口简单实用,兼容性也非常的棒。但是考虑到目前很多项目都有使用localStorage来做缓存,而localStorage本身是有大小限制的。根据日志记录的细粒度,很可能会产生较多的日志内容,如果也记录在localStorage里,可能会有超出容量限制的风险。因此,localStorage应该作为一个备用的持久化方案。

  • websql

    websql作为一项W3C标准,目前已经被废弃,但是各大桌面浏览器和移动端浏览器都有很好的实现这个接口,兼容性问题不大,底层基本上都是sqlite(正是因为这样,作为一个web标准是不可接受的)。因而日志作为大量的结构化数据,应用场景非常的适合。经测试,在iOS上容量最大支持50MB,不过如果使用系统自带的safari,超过5MB时,会主动提醒用户是否要增加数据库的大小,不是很友好,不过微信里到是不会。想想5MB独占作为日志存储基本上够用了,处理好过旧日志的清理工作即可。因此我们觉得websql应当作为当前阶段主要的解决方案。

  • indexedDB

    IndexedDB 是一种可以让你在用户的浏览器内持久化存储数据的方法,作为下一代的客户端结构化数据持久存储方案,足够的强大和高效,目前在各大浏览器中也有很好的支持,是未来用来替换websql的方案,应当在日后的迭代中主要支持,用来替代websql方案。

什么样的日志格式堪称优雅?

  • 时间戳,这个无需多说,时间戳是日志的基本要义。
  • 多会话,一个前端工程中可能同时存在多个独立的模块,这些模块很可能会同时互不干扰的记录各自的日志。如果每个模块都在自己的会话下记录日志,就不会相互干扰,并且提供了另一个维度的过滤能力。
  • 错误等级,如 info, warning, error, critical 等,以提供最为基本的过滤能力。
  • 描述符,如 verify.request.start, submit.prevented 等等。尽可能的以便用户一眼就可以知晓日志的大致内容,也方便代码中日志记录代码的可读性,也更易于在代码中搜索。
  • 数据和详情,有时候一个简单的描述符并不能说明问题,可能需要记录更多的描述性文本或者数据来分析问题。

日志怎么如何获取?

由于我们并不需要实时的获取来自客户端的大量日志,因此日志是存储在用户客户端本地的,我们需要后台配合开发一个用于接收客户端通过网络上传的日志内容并存储起来的接口。同时可能要考虑一些安全性问题,如引入token机制和验证登录态等等。目前我们腾讯微证券采用的方案为:用户在微信公众号中发送消息“问题反馈”(直接使用日志上报等关键词可能会引起用户的反感),后台会返回日志上传页面地址链接,用户点击链接进入后,在获取登录态后自动上报日志。大家可以微信关注腾讯微证券公众号尝试一下。

日志分析如何分析?

由于Logline上传的日志格式符合标准,具有良好的可阅读性,因此我们可以在某种程度上直接使用命令行工具或者编辑器来阅读。但是对命令行不熟悉的用户使用可能仍然有困难,因此有必要使用Web技术栈搭建一个易于使用并且视觉良好的工具。我们希望这套工具可以不依赖与后端,既可以部署在服务器端,也可以当做本地网页直接双击打开,也可以被简单的包一层外壳而当做桌面APP来使用。

作为日志,承载的最主要的内容便是大量的纯文本,在调研了一些方案后,我们认为H5规范中的FileReader.readAsText可以很好的做到这一点,结合拖放事件,我们便可以很大致构建出一个不错的方案:用户将一个或者多个日志文件拖放至网页中,即可对这些日志批量分析和检索。

我们构建了一个仅供体验的版本 [logline-viewer]。

Logline

基于以上工作,我们腾讯微证券项目组推出了自己的解决方案:Logline,一个轻量,实用和客户端级的前端日志记录工具。

DEMO

http://kezhen.info/logline/example/

应用场景

  • 核心流程监控

    在产品的一些核心流程中,我们可以在用户出错的情况下主动上传用户日志,以便我们可以快速统计和定位用户遇到的问题。

  • 主动抓取用户的日志分析用户行为

    有时候在用户不配合开发人员的时候,我们可以设计一种策略,比如我们在线上发布一个json文件,里面配置一个希望主动抓取日志的用户列表,当我们的产品在用户手机上被打开后,延时下载(避免影响主流程性能)这个json,当匹配当前用户时,直接主动上报该用户的日志。

  • 统计和辅助分析JS错误

    我们可以记录js的报错,包含调用队列一起记录,直接上传此错误日志或者在累计达到一个阈值的时候统一上传。

特性支持

  • 核心日志记录功能
  • 命名空间
  • websql/localStorage/indexedDB三种存储方案
  • 等级分类
  • 日志清理
  • 日志上传
  • 无外部依赖

快速上手

1. 引入脚本,并选择期望使用的协议

目前一共支持三个协议, 三个协议都被直接挂载在Logline对象上以便一些特殊的应用场景,也更好的符合语义化:

  • websql: Logline.PROTOCOL.WEBSQL
  • indexeddb: Logline.PROTOCOL.INDEXEDDB
  • localstorage: Logline.PROTOCOL.LOCALSTORAGE
// AMD/CMD
// 使用websql协议
var Logline = require('./mod/logline.min');
Logline.using(Logline.PROTOCOL.WEBSQL);

// Script Tag
<script src="./mod/logline.min.js"></script>
<script>
// 使用indexedDB协议
Logline.using(Logline.PROTOCOL.INDEXEDDB);
</script>

2. 清理日志

Logline.keep(.5); // 保留半天以内的日志,如果不传参则清空日志
Logline.clean(); // 清空日志并删除数据库

3. 记录日志

// 不同的模块使用不同的日志会话
var spaLog = new Logline('spa'),
sdkLog = new Logline('sdk');

// 不包含数据的,描述为 init.succeed 的记录
spaLog.info('init.succeed');

// 包含错误描述数据,描述为 init.failed 的记录
spaLog.error('init.failed', {
retcode: 'EINIT',
retmsg: 'invalid signature'
});

// 不包含数据的,描述为 outdated 的记录
sdkLog.warning('outdated');

// 包含错误描述数据,描述为 system.vanish 的记录
sdkLog.critical('system.vanish', {
    // debug infos here
});

4. 读取日志

Logline.getAll(function(logs) {
    // process logs here
});

自定义构建

目前Logline一共实现了localstoragewebsqlindexeddb三个日志协议,默认是全部打包,可能你只想使用其中某个协议而已,你可以通过npm run configure来自定义构建你需要的版本。这样有利于减小包的大小。

// 不跟参数默认构建所有协议
npm run configure
// 配置你需要的协议,去掉不需要的协议申明--with-xxx
npm run configure -- --with-localstorage --with-websql --with-indexeddb
// 重新打包
npm run build
// 去dist目录寻找新构建的打包文件

我们都在用

腾讯微证券

在腾讯微证券中使用的案例

开户流程监控

开户流程作为核心的流程之一,一直以来都有着比较完善的监控数据,在某次改版之后,我们发现用户开户提交失败的比例有着显著的上升,很多用户在最终提交开户资料时,后端校验发现某些用户资料尚未被设置这种情况很让我们困惑。也是促使我们开发这个工具原因。在部署了Logline这套方案后,我们在开户流程的代码中添加了较为详实的日志记录,并在出错的情况下主动上报日志到后端。发现是在某些机型中,用户点击下一步后,全局的loading遮罩显示较慢,导致用户快速连续2次点击了下一步,导致开户流程控制器连续2次触发下一步操作,使得某些页面被跳过导致。

修复JS报错

目前和财付通很多前端产品一样,我们接入了财付通统一日志上报平台,但是我们上传的内容很有限,访问性能也不是很好,也没法看到js错误的调用队列,甚至没法看到用户的useragent。在使用我们自己的Logline上报系统后,这一切都得到了解决,发现了一些由微信jssdk自身产生的错误如 'WeixinJSBridge is not defined'和一些上报量比较大的js错误,有效的保证了代码的质量,甚至还可以做一个错误实时曲线统计。

基于配置的主动抓取

由于产品正处于快速的功能迭代中,目前不论是业务代码还是核心模块的代码都会经常被改动,不可避免的会产生一些意想不到的问题。有时候,我们会去找到用户希望用户配合帮忙定位问题,但是并不是所有的用户都会愿意配合。于是我们设计了一套主动抓取用户日志的策略:在我们的产品页面被打开后,会延时一定的时间去下载一个logcat.json的文件,文件中会包含我们期望可以主动上报日志的用户列表,当和用户吻合时,该用户的日志将会被自动上传。在需要的时候,我们只需要维护这样一个配置文件即可,当配置中的用户日志被上传后,我们将会受到一封邮件提醒。也可以使用此配置文件来配置客户端JS是否要自动上报js错误。

CONTRIBUTING

我们相信前端的社区应该是开放和合作的。

Logline - 日志记录和上报模块

[logline]

Logline-viewer - 日志分析平台

[logline-viewer]

WIP

[√] 添加 IndexedDB 协议的支持
[√] 剥离日志上传实现,由使用方自行决策上传途径,改为暴露获取所有日志的方法
[√] 允许自定义编译,只打包自己需要的协议,以减小打包文件的大小
[ ] 不使用 webpack 编译,以减小打包文件的大小

未来规划

在这次的实践中,我们有意保持模块的独立性,并没有使用任何外部依赖,因此很容易复用到别的业务或者绑定自己的业务逻辑。不过在未来,我们更喜欢Logline作为前端日志的一整套解决方案提供,而无需业务在上传和分析部分要做出自己的实现。

更为可用的应用场景应该是业务放在我们的平台上申请一个appid,然后使用我们的统计脚本,所以日志将统一上报到我们的平台,业务方可以使用此appid在我们的系统中浏览、分析和检索所需的日志。

本方案使用的技术和实现难度并不困难,重要的是一种解决痛点的思路。

  • Cupid

    没有没那种记录js报错的时候输出报错内容的系统!PC端,可以通过浏览器的console面板查看,手机端没发捕捉这个错误;

    #1
  • Cupid

    这种前端日志统计,很多公司都有吧,比如比较成熟的易达统计系统;

    #2
登录后回复,如无账号,请使用邀请码注册