错误类型讲解:异常与监控

项目接入

前端

Vue

yarn add @sentry/vue @sentry/tracing 更详细的请查看 官网文档

2.x

  1. import Vue from "vue";
  2. import Router from "vue-router";
  3. import * as Sentry from "@sentry/vue";
  4. import { Integrations } from "@sentry/tracing";
  5. Vue.use(Router);
  6. const router = new Router({
  7. // ...
  8. });
  9. Sentry.init({
  10. Vue,
  11. dsn: "https://138b35a0c5584646944565b51fa8a3f3@o1064497.ingest.xxxx.io/6055444",
  12. integrations: [
  13. new Integrations.BrowserTracing({
  14. routingInstrumentation: Sentry.vueRouterInstrumentation(router),
  15. tracingOrigins: ["localhost", "my-site-url.com", /^\//],
  16. }),
  17. ],
  18. // Set tracesSampleRate to 1.0 to capture 100%
  19. // of transactions for performance monitoring.
  20. // We recommend adjusting this value in production
  21. tracesSampleRate: 1.0,
  22. // 添加用户崩溃反馈弹窗
  23. beforeSend(event, hint) {
  24. // Check if it is an exception, and if so, show the report dialog
  25. if (event.exception) {
  26. Sentry.showReportDialog({ eventId: event.event_id });
  27. }
  28. return event;
  29. },
  30. });
  31. // ...
  32. new Vue({
  33. router,
  34. render: h => h(App),
  35. }).$mount("#app");

3.x

  1. // yarn add @sentry/browser @sentry/tracing
  2. import * as Sentry from "@sentry/browser";
  3. import { Integrations } from "@sentry/tracing";
  4. // init
  5. Sentry.init({
  6. dsn: "https://aabfe2180673babf842912aifd3863141519d@sentry.io/3806182",
  7. // 统计后台接口在前端的响应时间
  8. integrations: [new Integrations.BrowserTracing()],
  9. });

React

yarn add @sentry/react @sentry/tracing

umijs 创建项目在 app.ts 中初始化 sentry.init 配置 更详细的请查看 官网文档

  1. import React from "react";
  2. import ReactDOM from "react-dom";
  3. import * as Sentry from "@sentry/react";
  4. import { Integrations } from "@sentry/tracing";
  5. import App from "./App";
  6. Sentry.init({
  7. dsn: "https://138b35a0c5584646944565b51fa8a3f3@o1064497.ingest.sentry.io/6055459",
  8. integrations: [new Integrations.BrowserTracing()],
  9. // Set tracesSampleRate to 1.0 to capture 100%
  10. // of transactions for performance monitoring.
  11. // We recommend adjusting this value in production
  12. tracesSampleRate: 1.0,
  13. });
  14. ReactDOM.render(<App />, document.getElementById("root"));
  15. // Can also use with React Concurrent Mode
  16. // ReactDOM.createRoot(document.getElementById('root')).render(<App />);

主动上报错误

有时候我们觉得它是个错误,但是sentry没这么认为,所以需要主动上报,这里sentry提供两个 API(captureException 与 captureMessage)

captureException:主动上报错误,这会触发系统内部钩子(webhooks) captureMessage:可以理解为埋点,不会触发系统内部钩子(webhooks),这里的 level: info

  1. import * as Sentry from '@sentry/vue';
  2. export type ISentry = typeof Sentry;
  3. class TrackError {
  4. public sentry?: ISentry;
  5. constructor(sentry?: ISentry) {
  6. this.sentry = sentry;
  7. }
  8. captureException(exception: any) {
  9. if (!this.sentry || !exception) return;
  10. this.sentry.captureException(exception);
  11. }
  12. }
  13. export default TrackError;

SourceMap

官网有三种做法如下:

  1. sentry 提供 webpack-plugin (链接)
  2. 脚手架工具 sentry-cli
  3. 直接调用 sentry API(有点麻烦,参数配置有点多)

这里介绍 @sentry/webpack-plugin 方式(方便接入现有 CI/CD)

.sentryclirc

  1. [auth]
  2. token=42b21a34ca654530af08 授权令牌,认证凭证token(Settings/Auth Tokens)
  3. [defaults]
  4. url = https://sentry.io/ 上报 sentry 地址
  5. org = ws-ap 组织名称(Organization)
  6. project = qv-h5 项目名称

vue.config.js

  1. const SentryCliPlugin = require('@sentry/webpack-plugin');
  2. module.exports = {
  3. // 开启 source map
  4. productionSourceMap: true,
  5. configureWebpack: config => {
  6. config.plugins.push(
  7. new SentryCliPlugin({
  8. include: './dist/',
  9. configFile: 'sentry.properties',
  10. // 版本(如果没有指定,sentry会自动创建 string 类型版本号),记得跟 init 版本一致sourceMap才会生效
  11. release: process.env.VUE_APP_PROJECT_RELEASE,
  12. ignore: ['node_modules'],
  13. urlPrefix: `${process.env.VUE_APP_COS_URL}/`
  14. })
  15. )
  16. }
  17. };

Tips

urlPrefix 可以为上传的 map 文件添加前缀,默认是 ~/sentry 需要根据 js 文件的 sourceMappingURL 来解析 map 文件路径,所以 SourceMap 级别不能用 hide-source-map 或者类似的。

很多人反馈错误没有定位到源码,很多就是错在这个配置(urlPrefix),这里解释下,
关于这个,是要看你项目的资源地址,比如,你前端访问页面是:http://test.com.cn/test/login,同时你的资源地址是:http://test.com.cn/test/dist/js/app.ecbb420f.js,那么,配置就应该是(urlPrefix~/test/(注意:非ip地址test)。
怎么看资源地址呢, 例如谷歌浏览器, F12控制台, 或者去 Application 里面找到对应资源打开。例如下图
image.png

再或者, 打开你的项目看看 build 下打的 assetsPublicPath 是什么,如果是:assetsPublicPath: '/test/',那你的 urlPrefix: '~/test/' 就是这个, 如果是 '/' ,那可以不配置,采用默认('~/')的即可。