zoukankan      html  css  js  c++  java
  • 前端异常监控

    sentry

    1. 静态资源加载异常
      静态资源加载失败,可以通过window的error事件进行捕获。核心代码
    // 全局监控资源加载错误
    window.addEventListener(
      'error',
      (event) => {
        // 过滤 js error
        const target = event.target || event.srcElement;
        const isElementTarget =
          target instanceof HTMLScriptElement ||
          target instanceof HTMLLinkElement ||
          target instanceof HTMLImageElement;
        if (!isElementTarget) {
          return false;
        }
        // 上报资源地址
        const url =
          (target as HTMLScriptElement | HTMLImageElement).src ||
          (target as HTMLLinkElement).href;
    
        this.log({
          error: new Error(`ResourceLoadError: ${url}`),
          type: 'resource load'
        });
      },
      true
    );
    
    1. 接口异常(后端和 native 的接口)
      可以通过在封装的 http 模块中,全局集成上报错误函数(native 接口的错误上报类似,可在项目中查看)。核心代码如下:
    function errorReport(
      url: string,
      error: string | Error,
      requestOptions: AxiosRequestConfig,
      response?: AnyObject
    ) {
      if (window.$sentry) {
        const errorInfo: RequestErrorInfo = {
          error: typeof error === 'string' ? new Error(error) : error,
          type: 'request',
          requestUrl: url,
          requestOptions: JSON.stringify(requestOptions)
        };
    
        if (response) {
          errorInfo.response = JSON.stringify(response);
        }
    
        window.$sentry.log(errorInfo);
      }
    }
    
    1. js 报错
      关于全局 js 报错,sentry 针对的前端的 sdk 已经通过 window.onerror 和 window.addEventListener('unhandledrejection', ..., false) 进行全局监听并上报。

    需要注意的是其中 window.onerror = (message, source, lineno, colno, error) =>{} 不同于 window.addEventListener('error', ...),window.onerror 捕获的信息更丰富,包括了错误字符串信息、发生错误的 js 文件,错误所在的行数、列数、和 Error 对象(其中还会有调用堆栈信息等)。所以 sentry 会选择 window.onerror 进行 js 全局监控。

    但有一种错误是 window.onerror 监听不到的,那就是 unhandledrejection 错误,这个错误是当 promise reject 后没有 catch 住所引起的。当然 sentry 的 sdk 也已经做了监听。

    针对 vue 项目,也可对 errorHandler 钩子进行全局监听,react 的话可以通过 componentDidCatch 钩子,vue 相关代码如下:

    // 全局监控 Vue errorHandler
    Vue.config.errorHandler = (error, vm, info) => {
      window.$sentry.log({
        error,
        type: 'vue errorHandler',
        vm,
        info
      });
    };
    
    1. 网页崩溃
      为部署到线上的代码一般都是经过压缩混淆的,如果没有上传 sourcemap 的话,是无法定位到具体源码的,可以现在 项目中添加 .sentryclirc 文件,其中内容可参考本项目的 .sentryclirc,然后通过 sentry-cli (需要全局全装 sentry-cli 即npm install sentry-cli)命令行工具进行上传,命令如下:
    sentry-cli releases -o 机构名 -p 项目名 files 版本 upload-sourcemaps sourcemap 文件相对位置 --url-prefix js 在线上相对根目录的位置 --rewrite
    // 示例
    sentry-cli releases -o mcukingdom -p hello-world files 0.2.1 upload-sourcemaps dist/js --url-prefix '~/js/' --rewrite
    

    官方也提供了 webpack 插件 sentry-webpack-plugin,当打包时触发 webpack 的 after-emit 事件钩子(即生成资源到 output 目录之后),插件会自动上传打包目录中的 sourcemap 和关联的 js,vue.config.js相关配置:

    const path = require('path');
    const webpack = require('webpack');
    const SentryPlugin = require('@sentry/webpack-plugin');
    const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
    const IS_PRO = NODE_ENV === 'production';
    
    const commonPlugins = [
      new webpack.DefinePlugin({
        __VERSION__: JSON.stringify(version)
      })
    ];
    module.exports = {
        ...
        configureWebpack: () => {
            if (IS_PRO) {
                const productionPlugins = [new LodashModuleReplacementPlugin()];
                productionPlugins.push(
                new SentryPlugin({
                    release: version, //发布的版本
                    include: path.join(__dirname, './dist/js'), //需要上传到sentry服务器的资源目录,会自动匹配 js 以及 map 文件
                    urlPrefix: '~/mobile-web-best-practice/js', //线上对应的 url 资源的相对路径
                    ignore: ['node_modules'] //忽略文件目录, 当然我们在 inlcude 中制定了文件路径,这个忽略目录可以不加
                })
                );
    
                return {
                    plugins: [...commonPlugins, ...productionPlugins],
                    externals: {
                    // key 是给 import 的时候用的,value 表示的是如何在 global 中访问到该对象
                    vue: 'Vue',
                    vuex: 'Vuex',
                    'vue-router': 'VueRouter'
                    }
                };
            } else {
                return {
                    plugins: [...commonPlugins]
                };
            }
        }
        ...
    }
    

    通常为了安全,是不允许在线上部署 sourcemap 文件的,所以上传 sourcemap 到 sentry 后,可手动删除线上 sourcemap 文件。

    资料参考

  • 相关阅读:
    201506022038_《JavaScript权威指南》(p48-58)
    201506022038_《JavaScript权威指南-判断两个数组相等》(p38-48)
    201506021641_《JavaScript权威指南》(p25-38)
    Linux平台上转换文件编码
    一台服务器上部署多个Terracotta的方法
    Subversion Backup and Restore
    How to name a slf4j logger
    基于ScheduledExecutorService的并发定时任务处理能力测试
    CodeReview of JDK Source Code
    Share Keyboard, Mouse and Clipboard between Multiple Computers
  • 原文地址:https://www.cnblogs.com/gongxiansheng/p/11717101.html
Copyright © 2011-2022 走看看