如何搭建前端异常监控系统 #102

简介: 如何搭建前端异常监控系统 #102

什么是异常


是指用户在使用应用时,无法得到预期的结果。不同的异常带来的后果程度不同,轻则引起用户使用不悦,重则导致产品无法使用,从而使用户丧失对产品的认可。


为什么要处理异常


  • 增强用户体验
  • 远程定位问题
  • 无法复现问题,特别是移动端,各种原因,可能是系统版本,机型等等

前端有哪些异常


异常 频率
JavaScript 异常(语法错误、代码错误) 经常
静态资源加载异常(img、js、css) 偶尔
Ajax 请求异常 偶尔
承诺异常 较少
iframe 异常 较少


如何捕获异常


尝试捕获

try-catch只能捕获同步运行错误,对语法和异步错误却捕获不到。

1、同步运行错误

try {
    kill;
} catch(err) {
    console.error('try: ', err);
}

结果:try: ReferenceError: kill is not defined

2、无法捕获语法错误

try {
    let name = '1;
} catch(err) {
    console.error('try: ', err);
}

结果:Unterminated string constant

编译器能够阻止运行语法错误。

3、无法捕获异步错误

try {
    setTimeout(() => {
        undefined.map(v => v);
    }, 1000);
} catch(err) {
    console.error('try: ', err);
}

结果:Uncaught TypeError: Cannot read property 'map' of undefined


窗口错误

当 运行时错误(包括语法错误)发生时, 会触发一个 接口的 事件,并执行 若该函数返回 ,则阻止执行默认事件处理函数。JavaScriptwindowErrorEventerrorwindow.onerror()true

1、同步运行错误

/**
* @param {String}  message   错误信息
* @param {String}  source    出错文件
* @param {Number}  lineno    行号
* @param {Number}  colno     列号
* @param {Object}  error     error对象
*/
window.onerror = (message, source, lineno, colno, error) => {
    console.error('捕获异常:', message, source, lineno, colno, error);
    return true;
};
kill;

结果:捕获异常: Uncaught ReferenceError: kill is not defined

2、无法捕获语法错误

/**
* @param {String}  message   错误信息
* @param {String}  source    出错文件
* @param {Number}  lineno    行号
* @param {Number}  colno     列号
* @param {Object}  error     error对象
*/
window.onerror = (message, source, lineno, colno, error) => {
    console.error('捕获异常:', message, source, lineno, colno, error);
    return true;
};
let name = '1;

结果:Unterminated string constant

编译器能够阻止运行语法错误。

3、异步错误

/**
* @param {String}  message   错误信息
* @param {String}  source    出错文件
* @param {Number}  lineno    行号
* @param {Number}  colno     列号
* @param {Object}  error     error对象
*/
window.onerror = (message, source, lineno, colno, error) => {
    console.error('捕获异常:', message, source, lineno, colno, error);
    return true;
};
setTimeout(() => {
    undefined.map(v => v);
}, 1000);

结果:捕获异常: Uncaught TypeError: Cannot read property 'map' of undefined`

window.addEventListener('error')

当一项资源(如 或 )加载失败,加载资源的元素会触发一个 接口的 事件,并执行该元素上的 处理函数。这些 事件不会向上冒泡到 ,不过(至少在 Firefox 中)能被单一的 . 捕获。<img><script>Eventerroronerror()errorwindowwindowaddEventListener

<script>
window.addEventListener('error', (err) => {
    console.error('捕获异常:', err);
}, true);
</script>
<img src="./test.jpg" />

结果:捕获异常:Event {isTrusted: true, type: "error", target: img, currentTarget: Window, eventPhase: 1, …}


window.addEventListener('unhandledrejection')


当 被 且没有 处理器的时候,会触发 事件;这可能发生在 下,但也可能发生在 中。 这对于调试回退错误处理非常有用。PromiserejectrejectunhandledrejectionwindowWorker

window.addEventListener("unhandledrejection", (err) => {
    err.preventDefault();
    console.error('捕获异常:', err);
});
Promise.reject('promise');

结果:捕获异常:PromiseRejectionEvent {isTrusted: true, promise: Promise, reason: "promise", type: "unhandledrejection", target: Window, …}


Vue

Vue.config.errorHandler = (err, vm, info) => {
  console.error('捕获异常:', err, vm, info);
}


React

React16,提供了一个内置函数 ,使用它可以非常简单的获取到 下的错误信息。componentDidCatchReact

componentDidCatch(error, info) {
    console.error('捕获异常:', error, info);
}

但是,推荐ErrorBoundary

用户界面中的 错误不应破坏整个应用程序。为了为 用户解决此问题, 引入了“错误边界”的新概念。JavaScriptReactReact16

新建 组件:ErrorBoundary.jsx

import React from 'react';
import { Result, Button } from 'antd';
class ErrorBoundary extends React.Component {
    constructor(props) {
        super(props);
        this.state = { hasError: false, info: '' };
    }
    static getDerivedStateFromError(error) {
        return { hasError: true };
    }
    componentDidCatch(error, info) {
        this.setState({
            info: error + ''
        });
    }
    render() {
        if (this.state.hasError) {
            // 你可以渲染任何自定义的降级 UI
            return (
                <Result
                    status="500"
                    title="500"
                    subTitle={this.state.info}
                    extra={<Button type="primary">Report feedback</Button>}
                />
            );
        }
        return this.props.children;
    }
}
export default ErrorBoundary;

使用:

<ErrorBoundary>
    <App />
</ErrorBoundary>

注意

错误边界不会捕获以下方面的错误:

  • 事件处理程序
  • 异步代码(例如 或 回调)setTimeoutrequestAnimationFrame
  • 服务器端渲染
  • 在错误边界本身(而不是其子级)中引发的错误

iframe

由于浏览器设置的“同源策略”,无法非常优雅的处理 异常,除了基本属性(例如其宽度和高度)之外,无法从 获得很多信息。iframeiframe

<script>
    document.getElementById("myiframe").onload = () => {
        const self = document.getElementById('myiframe');
        try {
            (self.contentWindow || self.contentDocument).location.href;
        } catch(err) {
            console.log('捕获异常:' + err);
        }
    };
</script>
<iframe id="myiframe" src="https://nibuzhidao.com" frameBorder="0" />


哨兵

业界非常优秀的一款监控异常的产品,作者也是用的这款,文档齐全。


需要上报哪些信息


  • 错误 id
  • 用户 ID
  • 用户名
  • 用户 IP
  • 设备
  • 错误信息
  • 游览器
  • 系统版本
  • 应用版本
  • 机型
  • 时间戳
  • 异常级别(错误、警告、信息)

异常上报


1、Ajax 发送数据

2、动态创建 img 标签

如果异常数据量大,导致服务器负载高,调整发送频率(可以考虑把异常信息存储在客户端,设定时间阀值,进行上报)或设置采集率(采集率应该通过实际情况来设定,随机数,或者某些用户特征都是不错的选择)。


流程图



参考资料


目录
相关文章
|
7月前
|
Web App开发 前端开发
【前端异常】Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
【前端异常】Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
472 0
|
10天前
|
前端开发 JavaScript 索引
【Web 前端】JS的几种具体异常类型(报错)
【4月更文挑战第22天】【Web 前端】JS的几种具体异常类型(报错)
|
7月前
|
前端开发
【前端异常】Module build failed: Error: ENOENT: no such file or directory, scandir ‘G:\OPWeb\public\node_m
【前端异常】Module build failed: Error: ENOENT: no such file or directory, scandir ‘G:\OPWeb\public\node_m
73 0
|
7月前
|
前端开发
【前端异常】解决前端引入Bootstrap的dropdowns 菜单时报错,Uncaught TypeError: Bootstrap‘s dropdowns require Popper.js
【前端异常】解决前端引入Bootstrap的dropdowns 菜单时报错,Uncaught TypeError: Bootstrap‘s dropdowns require Popper.js
61 0
|
9月前
|
前端开发 JavaScript
前端学习笔记202306学习笔记第三十七天-js中得错误和异常2
前端学习笔记202306学习笔记第三十七天-js中得错误和异常2
46 0
|
5月前
|
监控 前端开发 应用服务中间件
Zabbix【部署 01】Zabbix企业级分布式监控系统部署配置使用实例(在线安装及问题处理)程序安装+数据库初始+前端配置+服务启动+Web登录
Zabbix【部署 01】Zabbix企业级分布式监控系统部署配置使用实例(在线安装及问题处理)程序安装+数据库初始+前端配置+服务启动+Web登录
417 0
|
7月前
|
前端开发 JavaScript 编译器
【前端异常】vscode:无法将“cnpm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称,Cannot find module ”webpack“
【前端异常】vscode:无法将“cnpm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称,Cannot find module ”webpack“
323 0
|
9月前
|
监控 前端开发 小程序
前端异常监控平台对比
前端异常监控平台对比
282 0
|
9月前
|
前端开发 JavaScript
前端学习笔记202306学习笔记第三十七天-js中得错误和异常1
前端学习笔记202306学习笔记第三十七天-js中得错误和异常1
31 0
|
9月前
|
前端开发 JavaScript
前端学习笔记202306学习笔记第三十七天-js中得错误和异常3
前端学习笔记202306学习笔记第三十七天-js中得错误和异常3
32 0