UNPKG

sentry-configuration

Version:

sentry的公共配置文件

238 lines (216 loc) 8.48 kB
import * as Sentry from "@sentry/vue"; export default { install (Vue, options) { this.init(Vue, options); if(Vue.version.startsWith('2')){ Vue.prototype.$sentry = Sentry; Vue.prototype.$httpSentryCaptureMessage = this.httpSentryCaptureMessage; Vue.prototype.$captureMessage = this.captureMessage; }else if(Vue.version.startsWith('3')) { // 在 Vue 实例上挂载 Sentry 对象 Vue.config.globalProperties.$sentry = Sentry; // 在 Vue 实例上挂载自定义的错误捕获方法 Vue.config.globalProperties.$httpSentryCaptureMessage = this.httpSentryCaptureMessage; Vue.config.globalProperties.$captureMessage = this.captureMessage; }else { console.error('Vue版本不支持'); } }, init (Vue, {router, sentryOptions={}}={}) { this.checkOptiions(sentryOptions); const integrations = [ Sentry.replayIntegration({ // Additional SDK configuration goes in here, for example: maskAllText: true, //是否屏蔽所有文本内容,默认为false blockAllMedia: true, //是否阻止所有媒体内容的回放,默认为false networkDetailAllowUrls: [ window?.location?.origin, 'https://test-unite.scxljs.cn', 'https://unite.scxljs.cn', 'https://test-accesscontrol.scxljs.cn', 'https://fat.newmlife.com', 'https://newmlife.com', ...sentryOptions.networkDetailAllowUrls ], networkRequestHeaders: ['newhope-unite-auth', 'newhope-smart-auth', ...sentryOptions.networkRequestHeaders] //请求标头或正文 }), ] // 启用浏览器性能追踪 if (router) { integrations.push(Sentry.browserTracingIntegration({ router })) } let dsn = '', release= '', environment = '' if (Vue.version.startsWith('2')) { try { dsn = process.env.VUE_APP_DSN release = process.env.VUE_APP_RELEASE environment = process.env.VUE_APP_CURRENTENV } catch (error) { } } else { dsn = sentryOptions.dsn release = sentryOptions.release environment = sentryOptions.environment } /** 外部运行环境配置参数检查 */ if (!dsn || !release || !environment) { console.error(`请检查Sentry环境配置参数\nwebpack-vue2|VUE_APP_DSN、VUE_APP_RELEASE、VUE_APP_CURRENTENV\nvue3|请在安装sentry插件options的sentryOptions对象里传入dsn、release、environment变量`) return false } Sentry.init({ Vue, dsn, release, // 和 `vue.config` 中的保持一致 environment, debug: sentryOptions.debug, // http:{"verify_ssl": false}, integrations, initialScope: { // level: "info", ...sentryOptions.initialScope }, // 钩子函数,在每次发送 event 前触发 beforeSend(event) { // event.level = "warning" event.tags.location = window.location?.href || 'none'; sentryOptions?.beforeSend(event) return event; }, // Set `tracePropagationTargets` to control for which URLs distributed tracing should be enabled tracePropagationTargets: [], // Performance Monitoring tracesSampleRate: 1.0, // Capture 100% of the transactions // Session Replay replaysSessionSampleRate: sentryOptions.replaysSessionSampleRate, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production. replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur. }); }, checkOptiions(sentryOptions = {}){ const { networkDetailAllowUrls, networkRequestHeaders, initialScope, replaysSessionSampleRate, beforeSend,debug } = sentryOptions; if(Object.prototype.toString.call(networkDetailAllowUrls) !== '[object Array]'){ sentryOptions.networkDetailAllowUrls = []; } if(Object.prototype.toString.call(networkRequestHeaders) !== '[object Array]'){ sentryOptions.networkRequestHeaders = []; } if(Object.prototype.toString.call(initialScope) !== '[object Object]'){ sentryOptions.initialScope = {}; } if(typeof(replaysSessionSampleRate) !== 'number'){ sentryOptions.replaysSessionSampleRate = 1; } if(typeof(debug) !== 'boolean'){ sentryOptions.debug = false; } if(typeof(beforeSend) !== 'function'){ sentryOptions.beforeSend = ()=>{}; } }, /** * @name 主动上报捕获异常 * @param { title } title 标识 * @param { object } params 参数 * @param { object } stack 错误对象或微信返回对象 */ async captureMessage(title, params, stack = {}) { try { const isError = typeof stack === 'object' && !!stack.stack; const errorName = (isError ? stack.message : stack.errMsg) || 'unknows'; const extra = { params, errMsg: isError ? stack : stack.errMsg || '', href: location.href, }; // 上报错误 Sentry.withScope((scope) => { scope.setFingerprint([title, errorName]); const errMessage = new Error(errorName); errMessage.name = `前端异常上报:${title}`; console.log('前端异常:', title); Sentry.captureException(errMessage, { extra, level: 'error', }); }); } catch (error) { console.log('sentry:', error); } }, /** * 上报服务请求异常 * @param {*} stack * @returns */ async httpSentryCaptureMessage(stack) { try { // 错误信息 const errorMsg = stack.message; const errorCode = (stack.response && stack.response.status) || 0; // 排除业务报错400的情况 const isExtra = ['/unite/unite-system/staff/doAddStaff'].includes(stack.config.url) && errorCode===400; if (errorCode === 401 || errorCode === 403 || errorCode === 40301 || isExtra) { // 过滤403类凭证错误 return; } // 检测是否过期 let errorName; if (/timeout/i.test(errorMsg) || errorCode===504) { errorName = '接口超时'; } else if (/^4\d{2}$/.test(errorCode) || /^5\d{2}$/.test(errorCode)) { errorName = `服务端${errorCode}错误`; } else { errorName = '调用异常'; } const extra = { ...(stack.config || {}), errMsg: stack, href: location.href, }; //接口超时,上报接口的参数 errorName === '客户端接口超时' && (extra.networkInfo = await this.getResourceLoad('xmlhttprequest', extra.url)); Sentry.withScope((scope) => { if(stack.response.headers && ['1', '2'].includes(stack.response.headers['log-screen'])){ scope.setTag('newhope-traceid', stack.response.headers['newhope-traceid']) } scope.setFingerprint([extra.method, extra.url, errorName]); const errMessage = new Error(`异常接口地址: ${extra.url}`); errMessage.name = errorName; Sentry.captureException(errMessage, { extra, level: 'error', }); }); } catch (error) { console.log('sentry:', error); } }, /** * @name * @param { string } type 资源类型 * @param { string } name 资源名称匹配 */ getResourceLoad(type = 'xmlhttprequest', name = '') { return new Promise((resolve) => { if (!window.performance) { resolve({}); return; } setTimeout(() => { // 存入资源信息 const list = window.performance.getEntries().filter((item) => item.initiatorType === type) || []; if (!name) { resolve(list); return; } let result = {}; for (let i = list.length - 1; i >= 0; i -= 1) { if (list[i].name && list[i].name.indexOf(name) >= 0) { result = list[i]; break; } } resolve(result); }, 50); }); } } // export default sentrycommon