Blame view

src/logics/error-handle/index.ts 4.66 KB
vben authored
1
2
3
4
/**
 * Used to configure the global error handling function, which can monitor vue errors, script errors, static resource errors and Promise errors
 */
Vben authored
5
6
7
8
import type { ErrorLogInfo } from '/#/store';

import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog';
vben authored
9
10
import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
import { App } from 'vue';
11
import projectSetting from '/@/settings/projectSetting';
vben authored
12
13
14
15
16

/**
 * Handling error stack information
 * @param error
 */
vben authored
17
18
19
20
21
function processStackMsg(error: Error) {
  if (!error.stack) {
    return '';
  }
  let stack = error.stack
vben authored
22
23
24
25
26
27
28
    .replace(/\n/gi, '') // Remove line breaks to save the size of the transmitted content
    .replace(/\bat\b/gi, '@') // At in chrome, @ in ff
    .split('@') // Split information with @
    .slice(0, 9) // The maximum stack length (Error.stackTraceLimit = 10), so only take the first 10
    .map((v) => v.replace(/^\s*|\s*$/g, '')) // Remove extra spaces
    .join('~') // Manually add separators for later display
    .replace(/\?[^:]+/gi, ''); // Remove redundant parameters of js file links (?x=1 and the like)
vben authored
29
30
31
32
33
34
35
  const msg = error.toString();
  if (stack.indexOf(msg) < 0) {
    stack = msg + '@' + stack;
  }
  return stack;
}
vben authored
36
37
38
39
/**
 * get comp name
 * @param vm
 */
vben authored
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
function formatComponentName(vm: any) {
  if (vm.$root === vm) {
    return {
      name: 'root',
      path: 'root',
    };
  }

  const options = vm.$options as any;
  if (!options) {
    return {
      name: 'anonymous',
      path: 'anonymous',
    };
  }
  const name = options.name || options._componentTag;
  return {
    name: name,
    path: options.__file,
  };
}
vben authored
62
63
64
65
/**
 * Configure Vue error handling function
 */
vben authored
66
function vueErrorHandler(err: Error, vm: any, info: string) {
Vben authored
67
  const errorLogStore = useErrorLogStoreWithOut();
vben authored
68
  const { name, path } = formatComponentName(vm);
Vben authored
69
  errorLogStore.addErrorLogInfo({
vben authored
70
71
72
73
74
75
76
77
78
79
    type: ErrorTypeEnum.VUE,
    name,
    file: path,
    message: err.message,
    stack: processStackMsg(err),
    detail: info,
    url: window.location.href,
  });
}
vben authored
80
81
82
/**
 * Configure script error handling function
 */
vben authored
83
84
85
86
87
88
89
90
91
92
export function scriptErrorHandler(
  event: Event | string,
  source?: string,
  lineno?: number,
  colno?: number,
  error?: Error
) {
  if (event === 'Script error.' && !source) {
    return false;
  }
Vben authored
93
  const errorInfo: Partial<ErrorLogInfo> = {};
vben authored
94
95
  colno = colno || (window.event && (window.event as any).errorCharacter) || 0;
  errorInfo.message = event as string;
vben authored
96
  if (error?.stack) {
vben authored
97
98
99
100
101
    errorInfo.stack = error.stack;
  } else {
    errorInfo.stack = '';
  }
  const name = source ? source.substr(source.lastIndexOf('/') + 1) : 'script';
Vben authored
102
103
  const errorLogStore = useErrorLogStoreWithOut();
  errorLogStore.addErrorLogInfo({
vben authored
104
105
106
107
108
    type: ErrorTypeEnum.SCRIPT,
    name: name,
    file: source as string,
    detail: 'lineno' + lineno,
    url: window.location.href,
Vben authored
109
    ...(errorInfo as Pick<ErrorLogInfo, 'message' | 'stack'>),
vben authored
110
  });
vben authored
111
112
113
  return true;
}
vben authored
114
115
116
/**
 * Configure Promise error handling function
 */
vben authored
117
118
119
function registerPromiseErrorHandler() {
  window.addEventListener(
    'unhandledrejection',
Vben authored
120
121
122
    function (event) {
      const errorLogStore = useErrorLogStoreWithOut();
      errorLogStore.addErrorLogInfo({
vben authored
123
124
125
126
127
128
129
130
131
132
133
134
135
        type: ErrorTypeEnum.PROMISE,
        name: 'Promise Error!',
        file: 'none',
        detail: 'promise error!',
        url: window.location.href,
        stack: 'promise error!',
        message: event.reason,
      });
    },
    true
  );
}
vben authored
136
137
138
/**
 * Configure monitoring resource loading error handling function
 */
vben authored
139
function registerResourceErrorHandler() {
vben authored
140
  // Monitoring resource loading error(img,script,css,and jsonp)
vben authored
141
142
143
144
  window.addEventListener(
    'error',
    function (e: Event) {
      const target = e.target ? e.target : (e.srcElement as any);
Vben authored
145
146
      const errorLogStore = useErrorLogStoreWithOut();
      errorLogStore.addErrorLogInfo({
vben authored
147
        type: ErrorTypeEnum.RESOURCE,
Vben authored
148
        name: 'Resource Error!',
vben authored
149
150
151
152
153
154
155
        file: (e.target || ({} as any)).currentSrc,
        detail: JSON.stringify({
          tagName: target.localName,
          html: target.outerHTML,
          type: e.type,
        }),
        url: window.location.href,
Vben authored
156
        stack: 'resource is not found',
vben authored
157
158
159
160
161
162
163
        message: (e.target || ({} as any)).localName + ' is load error',
      });
    },
    true
  );
}
vben authored
164
165
166
167
/**
 * Configure global error handling
 * @param app
 */
vben authored
168
export function setupErrorHandle(app: App) {
169
  const { useErrorHandle } = projectSetting;
Vben authored
170
171
172
  if (!useErrorHandle) {
    return;
  }
vben authored
173
  // Vue exception monitoring;
vben authored
174
  app.config.errorHandler = vueErrorHandler;
vben authored
175
176

  // script error
vben authored
177
  window.onerror = scriptErrorHandler;
vben authored
178
179

  //  promise exception
vben authored
180
181
  registerPromiseErrorHandler();
vben authored
182
  // Static resource exception
vben authored
183
184
  registerResourceErrorHandler();
}