头大了,我的Sentry为什么上报错误不准

“瞎子过河记”

项目的监控报错机制使用 Sentry,为了更好的定位到错误,所以需要上传 sourcemap

最终踩坑完毕Sentry列表展示

  • 接口信息与页面报错区分
  • 提供更多有效自定义tag帮助快速定位

头大了,我的Sentry为什么上报错误不准_第1张图片
头大了,我的Sentry为什么上报错误不准_第2张图片

分享一下我的踩坑之路(基础教程这里就不在重复了,网上一搜一大堆,给大家来点不一样的干货~)

坑1:已经上传sourceMap了但是只能看到报错,还是看不到源码。
头大了,我的Sentry为什么上报错误不准_第3张图片

const sentryConfig = {
  url: 'https://sentry.xxx.com/',
  authToken: '***',
  org: 'frontend',
  project: 'cms',
  release: version,
  sourceMaps: {
    include: ['./build/static/js'],
    ignore: ['node_modules'],
    urlPrefix: '~/sub-wechat/static/js',
  },
};

比如线上访问地址是 https://www.**.com/sub-wechat/index urlPrefix 必须得在域名根目录下访问到,所以必须设置为 ~/sub-wechat/static/js(sub-wechat/static/js 文件夹下面都是.js)

坑2:终于可以看到源代码了,但是看到的源码是错行的,不是正确位置。Why?!

头大了,我的Sentry为什么上报错误不准_第4张图片

头大了,我的Sentry为什么上报错误不准_第5张图片
头大了,我的Sentry为什么上报错误不准_第6张图片

刚开始还怀疑Sentry的问题,本着我做了完我没有错,甩锅哈哈哈哈哈。
后来吃了个晚饭冷静了下来仔细排查发现浏览器查看报错也是错的,最后发现罪魁祸首,懒加载css。到现在也没搞懂为什么这个会影响sourcemap报错位置??求问

https://github.com/vitejs/vit...

头大了,我的Sentry为什么上报错误不准_第7张图片

为什么要统一封装Sentry

  • 项目多了上报信息错误不统一
  • 主动上报错误(比如log、warn、debug、fatal、error)
  • TAG上报的信息等级统一

为什么要监控接口错误

  • 错误监控及日志排查,提供更多有效信息;
  • 接口异常状态,根据异常状态发现代码的漏洞;
  • 有统一的一个request SDK,处理起来非常简单,

    sentry.js
    import * as Sentry from '@sentry/browser';
    import { Integrations } from '@sentry/tracing';
    /**
     * fatal: 很严重的系统异常,系统无法继续运行,必须处理,重要级别与uncaught的error类似
     * error(默认值): 系统异常,无法正常运行,如果type是uncaught,该报错必须由开发人员确定是否需要修复,如果是caught,表示可预见的报错,看情况解决
     * debug: 协助解决线上问题
     * warn: 系统可继续运行下去,用户可继续操作,用于上报一些警示线的错误信息
     * log: 简单的日志打点
     */
    
    /**
     * @description sentry的初始化配置,仅在线上及beta环境进行
     * @param {string} env 环境
     * @param {string} dsn sentry生成的dsn值。
     * @param {string} release 项目版本
     * @param {array} tags Sentry对应的tags
     * @examplenpm r
     *
     * Capture.init({ env: 'production', dsn: '1231afaf1', release: '1.0.0', tags: {TIME: new Date()})
     *
     */
    
    const Severity = {
    Fatal: 'fatal',
    Error: 'error',
    Warning: 'warning',
    Log: 'log',
    Info: 'info',
    Debug: 'debug',
    };
    class Capture {
    constructor(options) {
      const {
        env,
        dsn,
        release,
        tags,
      } = options;
      if (env === 'production') {
        Sentry.init({
          dsn,
          release,
          integrations: [new Integrations.BrowserTracing()],
          tracesSampleRate: 1.0,
          beforeSend(event) {
            const { exception } = event;
            // 接口请求错误主动上报了,这里就直接忽略掉
            const requestErr = exception.values.find((item) => item.value.startsWith('Request failed with status code'));
            if (requestErr) return null;
            const sendUser = event;
            // 在这里可根据业务情况发送用户信息
            const userData = localStorage.getItem('userData');
            let user = {
              cellphone: null,
              realName: null,
            };
            if (userData) {
              const userObj = JSON.parse(userData);
              user = {
                cellphone: userObj.cellphone,
                realName: userObj.realName,
                company: userObj.manageDepartmentNames,
                companyId: userObj.companyId,
              };
            }
            sendUser.user = user;
            return event;
          },
          ignoreErrors: [
            'Failed to fetch',
            'NetworkError when attempting to fetch resource.',
            'ResizeObserver loop limit exceeded',
            'ResizeObserver loop completed with undelivered notifications',
            'Loading chunk',
            'Unable to preload CSS for',
            'Request aborted',
          ],
        });
    
        Sentry.configureScope((scope) => {
          const date = new Date();
          const ymdDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`;
          const hour = date.getHours().toString();
          scope.setTag('ERRORTYPE', 'uncaught');
          scope.setTag('ENV', env);
          scope.setTag('DATE', ymdDate);
          scope.setTag('HOUR', hour);
          scope.setLevel(Severity.Error);
          if (tags && typeof tags === 'object') {
            Object.keys(tags).forEach((key) => {
              scope.setTag(key, tags[key]);
            });
          }
        });
      }
    }
    
    // eslint-disable-next-line class-methods-use-this
    sentryCapture({
      error = '',
      extra,
      level,
      tags,
    }) {
      Sentry.withScope((scope) => {
        scope.setTag('ERRORTYPE', 'caught');
        scope.setLevel(level);
        let reportError = error;
        if (error instanceof Error) {
          reportError = error.toString();
        } else if (typeof error === 'object') {
          reportError = JSON.stringify(error);
        }
    
        if (extra && typeof extra === 'object') {
          Object.keys(extra).forEach((key) => {
            scope.setExtra(key, extra[key]);
          });
        }
    
        if (tags && typeof tags === 'object') {
          Object.keys(tags).forEach((key) => {
            scope.setTag(key, tags[key]);
          });
        }
        if (reportError === 'CANCEL') return;
        Sentry.captureException(new Error(reportError));
      });
    }
    
    fatal(param) {
      this.sentryCapture({ ...param, level: Severity.Fatal });
    }
    
    error(param) {
      this.sentryCapture({ ...param, level: Severity.Error });
    }
    
    warn(param) {
      this.sentryCapture({ ...param, level: Severity.Warning });
    }
    
    debug(param) {
      this.sentryCapture({ ...param, level: Severity.Debug });
    }
    
    log(param) {
      this.sentryCapture({ ...param, level: Severity.Log });
    }
    }
    
    export default Capture;
    

    使用

    import Capture from 'sentry.js';
    
    const capture = new Capture({
      dsn: '*****',
      release: version,
      env: import.meta.env.MODE,
    });

请教下大神 为什么懒加载会影响sourceMap位置?

你可能感兴趣的:(前端html)