::: tip
插件文档详细说明请参考 @shencom/plugins 文档
:::

初始化文件

  1. # 安装依赖
  2. yarn add @shencom/plugins
  3. # 创建 setup/sentry.ts 文件,存在则用不创建
  4. mkdir src/setup && touch src/setup/sentry.ts
  5. # 创建 `src/setup/index.ts` 入口文件
  6. touch src/setup/index.ts

添加下面代码

src/setup/sentry.ts

  1. // 示例, 按需修改
  2. import { VueConstructor } from 'vue';
  3. import { Sentry } from '@shencom/plugins'; // 二次封装类
  4. import router from '../router'; // 路由
  5. const dsn = 'https://xxxx@sentry.shencom.cn/n';
  6. /** 初始化 */
  7. export default function install(Vue: VueConstructor) {
  8. const { $utils, $config } = Vue.prototype as Vue;
  9. const { _IsPro, _IsDev, _FormatDateTime } = $utils;
  10. const { scid, version } = $config;
  11. const release = version + (_IsPro ? '' : '.tst');
  12. Sentry.install({
  13. Vue,
  14. dsn,
  15. scid,
  16. isDev: _IsDev,
  17. isPro: _IsPro,
  18. release,
  19. BrowserTracingOption: {
  20. routingInstrumentation: Sentry.context.vueRouterInstrumentation(router),
  21. },
  22. beforeSend(event) {
  23. // 上报拦截,根据需要自定义上报数据
  24. const base = {
  25. scid,
  26. date: _FormatDateTime(),
  27. environment: _IsPro ? '正式' : '测试',
  28. origin: window.location.origin,
  29. hash: window.location.hash,
  30. search: window.location.search,
  31. };
  32. // 上报 tag.name 可以通过当前用户名来查找全部出现异常的情况
  33. // const user = _UserInfo._GetUserInfo() || {};
  34. // const username = user.realname || user.nickname;
  35. // if (username) {
  36. // if (!event.tags) event.tags = {};
  37. // Object.assign(event.tags, { username });
  38. // }
  39. if (!event.extra) event.extra = {};
  40. Object.assign(event.extra, base);
  41. return event;
  42. },
  43. });
  44. }

src/setup/index.ts

  1. import { VueConstructor } from 'vue';
  2. + import Sentry from './sentry';
  3. export default function install(Vue: VueConstructor) {
  4. + Vue.use(Sentry);
  5. }

src/main.ts

  1. import Vue from 'vue';
  2. ...
  3. + import Init from './setup';
  4. + Vue.use(Init);

错误上报

::: tip
sentry.ts 中,进行初始化 @shencom/plugins 包的 Sentry 方法,根据需求进行改动;
通过创建一个 src/lib/utils/error.ts 文件,再进行集中处理不同类型的错误上报
:::

  1. // src/lib/utils/error.ts
  2. /* eslint-disable import/prefer-default-export */
  3. import { AxiosError } from 'axios';
  4. import { Sentry } from '@shencom/plugins';
  5. const responseError = (error: AxiosError) => {
  6. console.log('请求错误--- :', error, { ...error });
  7. if (!error || !error.response) return;
  8. const { response, message } = error;
  9. const { config, data, status } = response;
  10. const method = (config.method && config.method.toLocaleUpperCase()) || '';
  11. Sentry.setRequest({
  12. data,
  13. status,
  14. method,
  15. message,
  16. url: config.url || '',
  17. body: JSON.parse(config.data || '{}'),
  18. header: config.headers || {},
  19. });
  20. };
  21. const tryError = (error: Error) => {
  22. console.log('脚本错误--- :', error);
  23. Sentry.captureException(error);
  24. };
  25. /** 全局错误处理
  26. *
  27. * @param {(Error | AxiosError)} error 错误信息
  28. * @param {boolean} [isHttp=false] 在请求拦截中传 `true` 为了防止请求错误重复上报
  29. * @return {*}
  30. */
  31. export const _GlobalError = (error: any, isHttp = false) => {
  32. if (!error) return;
  33. if (isHttp && error.response) {
  34. responseError(error as AxiosError);
  35. } else {
  36. tryError(error as Error);
  37. }
  38. };

请求错误

:::warning 请求错误上报,是在 axios 中的 请求拦截响应拦截 中使用 _GlobalError 第二个参数需要传一个 true :::

axios.ts

  1. import axios from 'axios';
  2. import { _GlobalError } from '../utils/error';
  3. axios.interceptors.response.use(
  4. () => {},
  5. (error) => {
  6. // code ...
  7. _GlobalError(error, true);
  8. },
  9. );
  10. axios.interceptors.request.use(
  11. () => {},
  12. (error) => {
  13. // code ...
  14. _GlobalError(error, true);
  15. },
  16. );

脚本错误

脚本错误上报,一般为自动上报,如果手动上报可以参考下面代码

  1. onError() {
  2. try {
  3. const a: any = {};
  4. const num = Math.floor(Math.random() * 10);
  5. a.b[num].d.c = '1';
  6. } catch (error) {
  7. this.$utils._GlobalError(error); // _GlobalError 已经挂载到 Vue 实例上
  8. }
  9. }

::: tip
try/catch 里面的请求,如果报错,已经在 axios 中的拦截器中已经进行上报;
这里面的错误请求将被过滤掉;
:::

  1. async onSendRequest() {
  2. try {
  3. const data = await this.$http.post<{data:{a:number}}>(this.$api.login, { a: 12 });
  4. data.a.b.c = ''; // 抛出异常
  5. } catch (error) {
  6. this.$utils._GlobalError(error);
  7. }
  8. }

加载优化

使用方式 1

配置 .babelrc 使用按需加载 @shencom/plugins 内容

  1. {
  2. "plugins": [
  3. [
  4. "import",
  5. {
  6. "libraryName": "@shencom/plugins",
  7. "libraryDirectory": "es",
  8. "camel2DashComponentName": false
  9. }
  10. ]
  11. ]
  12. }

使用方式 2

  1. import Sentry from '@shencom/plugins/es/sentry';
  2. Sentry.install({
  3. // ...
  4. });