日志监控
普通上报
日志上报的常见方式,各有优缺:
- fetch/xhr:最常见的上报方式,可能遇到跨域问题。页面卸载时,采用异步上报可能导致数据丢失,同步上报将阻塞浏览器的关闭,导致页面卡顿。
- img:简单且,不会遇到跨域问题。退出页面的日志可能上报失败,数据丢失。
- sendBeacon:该api保证页面完全卸载前将数据上报,无数据丢失风险。兼容性:除了IE,其余浏览器都广泛支持。
(1)xhr上报
window.addEventListener("beforeunload", function (e) { var client = new XMLHttpRequest(); client.open("POST", "/log"); client.send(data); }); |
---|
但是会发现根本没有收到消息,因为我们发的是异步的请求,请请求发出去之前当前页面的上下文环境已经被销毁了,因此什么也发不出去。
按照这个思路是不是把异步改成同步就可以了,修改发送请求的代码:
window.addEventListener("unload", function (e) { var client = new XMLHttpRequest(); client.open("POST", "/log", false); client.send(data); }); |
---|
看起来功能实现了,不过现在有一个问题,我们为什么平时不实用同步请求,因为 js 是单线程的主线程阻塞用户侧会卡住,卡住的时间和网络状况有关,可能会较长。那么这个场景是否会存在卡住的问题呢?肯定是会的,用户想关闭或刷新页面,这时我们在等待请求返回,出现的现象就好像是卡死了关不掉,体验很不好。
(2)Beacon上报
我们需要一个 API 能保证在页面销毁之前发出请求,还不能阻塞页面,为了处理这个场景的问题,浏览器推出了 Beacon API。
sendBeacon 方法位于 navigator 上,可以在浏览器中使用,调用 sendBeacon 会发送一个异步的 post 请求,这个请求可以保证在页面完成卸载前发送出去,且不会阻塞页面卸载过程,调用起来就很简单
window.addEventListener("unload", function (e) { navigator.sendBeacon("/log", data); }); |
---|
Beacon API 被设计出来就是用于发送分析统计数据的,不建议用做其他用途。
sendBeacon 可以发送 ArrayBufferView, Blob, DOMString, FormData 多种数据类型。
sendBeacon 的返回值为布尔类型,表示浏览器是否成功把请求加入发送队列。
Beacon API 不能在 web worker 中使用。一般需要跟浏览器环境相关的变量 需要在主线程获取,web worker里只做一些计算性的事情,然后把计算结果发送给主线程。WebWorker介绍参考:https://juejin.cn/post/7139718200177983524
(3)img上报
因为img资源浏览器不会阻止,跨域会针对xhr这种请求才会生效,一般前端监控上报通过一个1*1的gif进行上报。然后服务端应该是对请求会有日志打印或上报。
function sendSomething(data, done, fail) { var img = new Image() img.onload = done img.onerror = fail img.src = '<https://tracking.volument.com>?' $.param(data) } |
---|
badjs
badjs-web是腾讯开源的一款前端监控系统。
badjs-web Github:https://github.com/BetterJS/badjs-web
badjs-report GItHub:https://github.com/BetterJS/badjs-report
sentry
sentry是一款开源的支持多语言(JS、Go、Python等)的错误日志监控系统。
star数:33.3k
Github地址:https://github.com/getsentry/sentry
官网:https://sentry.io/welcome/
本地部署:https://blog.csdn.net/zzddada/article/details/119716725
落地方案:https://www.jianshu.com/p/559f70bbfcdc
监控页面示例:https://raw.githubusercontent.com/getsentry/sentry/master/.github/screenshots/projects.png