本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!
前言
还记得小编之前的一篇文章 - 如何优雅的解决 Qiankun 下 Sentry 异常上报无法自动区分项目的问题 ? 吗?在这篇文章中,小编针对 Qiankun
下 Sentry
异常上报无法自动区分项目的问题,提供了一种行之有效的解决方案,切实帮助了不少同学,成就感直接拉满,😄。
不过在后续使用过程中,小编发现该方案并不完整。使用 Sentry
时,如果开启了性能监控功能,客户端上报的性能指标数据,会和之前的异常数据一样,全部上报到主应用对应的 project
中。出现这种情况,当然是不合理的,我们需要性能指标数据也和异常数据一样,能上报到正确的 project
中, 方便开发人员去做性能分析。
有了之前的经验,这个问题解决起来可以说是非常简单,就是拦截性能指标数据上报接口,将数据做分发,然后重新上报。本文,小编会在之前的异常上报解决方案的基础上,添加性能指标数据上报解决方案,给大家提供一个完整版的解决方案。
本文的目录结构:
解决方案
简单来说,不管是异常数据上报分发,还是性能指标数据上报分发,我们的解决思路都是分为 3
步:
-
通过自定义
transport
去拦截数据上报接口; -
对异常(性能指标)数据做分发,然后重组上报接口需要的
url
; -
使用新的
url
重新上报数据;
拦截数据上报接口
拦截数据上报接口,我们可以直接复用原来的技术方案,代码如下:
-
6.x
版本// 6.x 版本 import { Transports, init } from '@sentry/browser'; import { Integrations } from '@sentry/tracing'; const fetchImpl = (url, options) => { // 根据 options 中的异常(性能指标)信息,返回新的 url 和 options const [newUrl, newOptions] = sentryFilter(url, options); // 使用原生的 fetch 去上报数据 return originFetch(newUrl, newOptions); } // 通过继承的方式,定义一个 CustomerTransport class CustomerTransport extends Transports.FetchTransport { constructor(options) { // 将自定义 fetchImpl 传入 super(options, fetchImpl) } } init({ dsn: 'xxxx', enabled: true, integrations: [ // 性能监控必须使用 BrowserTracing new Integrations.BrowserTracing({ idleTimeout: 2000, }), ], // 如果要开启性能监控,tracesSampleRate 必须要有值 tracesSampleRate: 1, // 使用自定义的 CustomerTransport transport: CustomerTransport, // 其他配置项 ... });
-
7.x
版本import { init, makeFetchTransport } from '@sentry/browser'; import { Integrations } from '@sentry/tracing'; const CustomeTransport = (options) => { const fetchImpl = (url, options) => { // 根据 options 中的异常(性能指标)信息,返回新的 url 和 options const [newUrl, newOptions] = sentryFilter(url, options); // 使用原生的 fetch 去上报数据 return window.fetch(newUrl, newOptions); }; // 7.x 版本不需要继承 Transports.FetchTransport return makeFetchTransport(options, fetchImpl); }; init({ dsn: 'xxxx', enabled: true, integrations: [ // 性能监控必须使用 BrowserTracing new Integrations.BrowserTracing({ idleTimeout: 2000, }), ], // 如果要开启性能监控,tracesSampleRate 必须要有值 tracesSampleRate: 1, // 使用自定义的 CustomerTransport transport: CustomerTransport, // 其他配置项 ... });
数据分发、重组 url
不管是异常数据上报,还是性能指标数据上报,上报接口的 url
其实都是由 project
对应的 dsn
信息转化而来的。
具体的转化过程如下:
// https://62187b367e474822bb9cb733c8a89814@sentry.byai.com/56
dsn - https://{param1}@{param2}/{param3}
|
|
v
errorUrl - https://{param2}/api/{param3}/store/?sentry_key={param1}&sentry_version=7
performanceUrl - https://{param2}/api/{param3}/envelope/?sentry_key={param1}&sentry_version=7
异常上报的 url
和性能指标上报的 url
看起来几乎一样,只有关键字不同。其中,异常上报 url
的关键字是 store
,性能指标手上报 url
的关键字是 envelope
。
只要我们能根据上报的异常(性能指标)数据找到正确的 project
,就可以根据 project
的 dsn
重组 url
。
首先,我们来创建一个 project
注册表。
const PROJECT_CONFIG = {
'project-1': {
// 子应用唯一标识
project: 'project-1',
// dsn 重组以后的异常上报 url
errorUrl:
'https://sentry.xxx.com/api/1/store/?sentry_key=a&sentry_version=7',
// 异常数据分发方法
errorCheck: (url: string) => url.includes('/project-1/'),
// dsn 重组以后的性能指标上报 url
performanceUrl:
'https://sentry.xxx.com/api/1/envelope/?sentry_key=a&sentry_version=7',
// 性能指标数据分发方法
performanceCheck: (url: string) => url.includes('/project-1/'),
},
'project-2': {
project: 'project-2',
errorUrl:
'https://sentry.xxx.com/api/2/store/?sentry_key=b&sentry_version=7',
errorCheck: (url: string) => url.includes('/project-2/'),
performanceUrl:
'https://sentry.xxx.com/api/2/envelope/?sentry_key=b&sentry_version=7',
performanceCheck: (url: string) => url.includes('/project-2/'),
},
'project-3': {
project: 'project-3',
errorUrl:
'https://sentry.xxx.com/api/3/store/?sentry_key=c&sentry_version=7',
errorCheck: (url: string) => url.includes('/project-3/'),
performanceUrl:
'https://sentry.xxx.com/api/56/envelope/?sentry_key=a&sentry_version=7',
performanceCheck: (url: string) => url.includes('/project-3/'),
},
'project-4': {
project: 'project-4',
errorUrl:
'https://sentry.xxx.com/api/4/store/?sentry_key=d&sentry_version=7',
errorCheck: (url: string) => url.includes('/project-4/'),
performanceUrl:
'https://sentry.xxx.com/api/56/envelope/?sentry_key=a&sentry_version=7',
performanceCheck: (url: string) => url.includes('/project-4/'),
},
...
};
上述 project
注册表中的 errorUrl
、performanceUrl
是数据分发以后重组的 url
,根据实际项目中各个 project
真实的 dsn
信息生成;errorCheck
、performanceCheck
是 project
分发的判断方法。
接下来,我们来实现数据分发,分为异常数据分发和性能指标数据分发:
-
异常数据分发
异常数据的分发,需要分析异常追踪栈中发生异常的文件对应的
url
。const findErrorProject = (filename: string) => { const keys = Object.keys(PROJECT_CONFIG); for (const key of keys) { const project = PROJECT_CONFIG[key]; // 找到可以分发的项目 if (project.errorCheck(filename)) { return project; } } // 没有返回 null return null; }; const sentryErrorFilter = (url: string, options: any) => { let project = null; // 拿到 sentry 生成的异常信息 const error = JSON.parse(options.body).exception; if (error && error.values && error.values.length) { // 找到异常追踪栈信息 const stacktrace = error.values[0].stacktrace; if (stacktrace && stacktrace.frames && stacktrace.frames.length) { // 找到发生异常的文件对应的文件名 const filename = stacktrace.frames[stacktrace.frames.length - 1].filename; // 根据文件名判断是那个子应用 project = findErrorProject(filename); } } return project // 能找到子应用,返回重组以后的 url ? [project.errorUrl, { release: project.project, ...options }] // 没有匹配的子应用,返回原来的 url : [url, options]; };
-
性能数据分发
性能数据的分发就比较简单了,直接根据当前应用的路由信息判断即可。
const findPerformanceProject = (pathname: string) => { const keys = Object.keys(PROJECT_CONFIG); for (const key of keys) { const project = PROJECT_CONFIG[key]; // 找到可以分发的项目 if (project.performanceCheck(pathname)) { return project; } } // 没有返回 null return null; }; const sentryProformanceFilter = (url: string, options: any) => { // 应用当前路由信息 const pathname = window.location.pathname; // 根据路由信息判断是哪个子应用 const project = findPerformanceProject(pathname); return project // 能找到子应用,返回重组以后的 url ? [project.performanceUrl, options] // 没有匹配的子应用,返回原来的 url : [url, options]; };
最后,我们来实现如何区分异常数据上报和性能指标数据上报。 方法也非常简单。如果是性能指标数据上报, Sentry
会给上报的数据添加 type: 'transaction'
信息。通过这一点,可以很方便的区分异常数据和性能指标数据,代码如下:
const sentryFilter = (url, options) => {
const body = options.body || '';
// 性能
if (body.includes('"type":"transaction"')) {
return sentryProformanceFilter(url, options);
} else {
return sentryErrorFilter(url, options);
}
};
这就是 Qiankun
架构下关于异常监控和性能监控的完整版技术方案了。亲测有效哦!
结束语
到这里,关于如何使用 Sentry
做异常监控、性能监控就暂时告一段落了。
简单做一下回顾。小编通过 6
篇文章,梳理了 Sentry
做异常、性能监控的原理, 如何自动推送 Sentry
告警, 如何分析性能监控数据。阅读完这 6
篇文章,想必大家对 Sentry
的使用已经有一个初步的认识了吧。
其实,关于 Sentry
的使用,小编也只是了解一些皮毛, 还需要再继续深入了解。后续小编还会持续跟进,将自己新的使用心得总结出来,感兴趣的小伙伴们可以一直关注哦。