sentry-configuration
Version:
sentry的公共配置文件
238 lines (216 loc) • 8.48 kB
JavaScript
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