You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
4.6 KiB

2 years ago
/**
* Used to configure the global error handling function, which can monitor vue errors, script errors, static resource errors and Promise errors
*/
import type { ErrorLogInfo } from '@/types/store'
import { useErrorLogStoreWithOut } from '@/store/modules/errorLog'
import { ErrorTypeEnum } from '@/enums/exceptionEnum'
import { App } from 'vue'
import projectSetting from '@/settings/projectSetting'
/**
* Handling error stack information
* @param error
*/
function processStackMsg(error: Error) {
if (!error.stack) {
return ''
}
let stack = error.stack
.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)
const msg = error.toString()
if (stack.indexOf(msg) < 0) {
stack = msg + '@' + stack
}
return stack
}
/**
* get comp name
* @param vm
*/
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
}
}
/**
* Configure Vue error handling function
*/
function vueErrorHandler(err: Error, vm: any, info: string) {
const errorLogStore = useErrorLogStoreWithOut()
const { name, path } = formatComponentName(vm)
errorLogStore.addErrorLogInfo({
type: ErrorTypeEnum.VUE,
name,
file: path,
message: err.message,
stack: processStackMsg(err),
detail: info,
url: window.location.href
})
}
/**
* Configure script error handling function
*/
export function scriptErrorHandler(event: Event | string, source?: string, lineno?: number, colno?: number, error?: Error) {
if (event === 'Script error.' && !source) {
return false
}
const errorInfo: Partial<ErrorLogInfo> = {}
colno = colno || (window.event && (window.event as any).errorCharacter) || 0
errorInfo.message = event as string
if (error?.stack) {
errorInfo.stack = error.stack
} else {
errorInfo.stack = ''
}
const name = source ? source.substr(source.lastIndexOf('/') + 1) : 'script'
const errorLogStore = useErrorLogStoreWithOut()
errorLogStore.addErrorLogInfo({
type: ErrorTypeEnum.SCRIPT,
name: name,
file: source as string,
detail: 'lineno' + lineno,
url: window.location.href,
...(errorInfo as Pick<ErrorLogInfo, 'message' | 'stack'>)
})
return true
}
/**
* Configure Promise error handling function
*/
function registerPromiseErrorHandler() {
window.addEventListener(
'unhandledrejection',
function (event) {
const errorLogStore = useErrorLogStoreWithOut()
errorLogStore.addErrorLogInfo({
type: ErrorTypeEnum.PROMISE,
name: 'Promise Error!',
file: 'none',
detail: 'promise error!',
url: window.location.href,
stack: 'promise error!',
message: event.reason
})
},
true
)
}
/**
* Configure monitoring resource loading error handling function
*/
function registerResourceErrorHandler() {
// Monitoring resource loading error(img,script,css,and jsonp)
window.addEventListener(
'error',
function (e: Event) {
const target = e.target ? e.target : (e.srcElement as any)
const errorLogStore = useErrorLogStoreWithOut()
errorLogStore.addErrorLogInfo({
type: ErrorTypeEnum.RESOURCE,
name: 'Resource Error!',
file: (e.target || ({} as any)).currentSrc,
detail: JSON.stringify({
tagName: target.localName,
html: target.outerHTML,
type: e.type
}),
url: window.location.href,
stack: 'resource is not found',
message: (e.target || ({} as any)).localName + ' is load error'
})
},
true
)
}
/**
* Configure global error handling
* @param app
*/
export function setupErrorHandle(app: App) {
const { useErrorHandle } = projectSetting
if (!useErrorHandle) {
return
}
// Vue exception monitoring;
app.config.errorHandler = vueErrorHandler
// script error
window.onerror = scriptErrorHandler
// promise exception
registerPromiseErrorHandler()
// Static resource exception
registerResourceErrorHandler()
}