“瞎子过河记”
项目的监控报错机制使用 Sentry,为了更好的定位到错误,所以需要上传 sourcemap
最终踩坑完毕Sentry列表展示
- 接口信息与页面报错区分
- 提供更多有效自定义tag帮助快速定位
分享一下我的踩坑之路(基础教程这里就不在重复了,网上一搜一大堆,给大家来点不一样的干货~)
坑1:已经上传sourceMap了但是只能看到报错,还是看不到源码。
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的问题,本着我做了完我没有错,甩锅哈哈哈哈哈。
后来吃了个晚饭冷静了下来仔细排查发现浏览器查看报错也是错的,最后发现罪魁祸首,懒加载css。到现在也没搞懂为什么这个会影响sourcemap报错位置??求问
https://github.com/vitejs/vit...
为什么要统一封装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, });
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。