本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!
前言
之前,小编写过一篇关于使用 Sentry
做异常监控的文章 - 使用 Sentry 做异常监控 - 如何优雅的解决 Qiankun 下 Sentry 异常上报无法自动区分项目的问题 ?。在这篇文章中,小编就 求教一下 主子应用的sentry应该如何实践 #1088 这个问题,提出了最终解决方案,并得到了不错的反响。
在这篇文章发表以后,陆续有小伙伴询问使用该方案后,Source Maps
自定义版本号的问题该怎么处理。说来惭愧,关于这个问题,小编一开始并没有怎么正视,只是提供了一种比较粗暴的解决方案 - 根据项目写死 release
配置。后来随着询问的小伙伴越来越多,小编觉得以前提供的解决方案不太好,就想着看能不能用一种更优雅的方式来解决问题。
经过一番思考和实践,小编 get
到了一种比较好的解决方案,然后通过本文展示给大家,希望能给到有同样困扰的小伙伴们一些启发。
本文的目录结构如下:
Sentry 上传 Source Maps
在使用 Sentry
做异常监控时,为了能更准确的定位异常在源文件中发生的行列位置,我们通常需要将项目打包时生成 Source Maps
文件上传到 Sentry
。
在上传 Source Maps
文件时,Sentry
提供了两种方式: webpack plugin
和 sentry cli
:
-
webpack plugin
webpack plugin
的使用方式非常简单,我们只需要安装一个@sentry/webpack-plugin
插件,然后在项目的webpack
配置中使用这个插件就好了。具体如下:
// 安装插件 yarn add @sentry/webpack-plugin --dev npm install @sentry/webpack-plugin --save-dev
// 使用插件 const SentryCliPlugin = require('@sentry/webpack-plugin'); const config = { plugins: [ new SentryCliPlugin({ include: path.resolve(__dirname, './build/static/js'), ignore: ['node_modules', 'webpack.config.js'], release: 'xxx', project: 'xxx', urlPrefix: 'xxxx', url: 'xxx', ... }), ], };
更多情况详见: 官网:webpack plugin。
-
sentry cli
sentry cli
的方式也非常简单, 只要在需要上传的时候,执行以下命令即可:npx sentry-cli releases files <release_name> upload-sourcemaps xxx --url-prefix=xxx
更多情况详见: 官网: sentry cli。
有了这两种方法,我们就在可以上传 Source Maps
文件时,根据项目情况做出灵活选择。如果我们的项目是使用 Webpack
工具打包,那么我们可以使用 webpack plugin
的方式去上传 sourcemap
文件;而如果项目是使用非 Webpack
工具打包,比如说 Parcel
、Vite
,那我们就可以采用 sentry cli
的方式去上传 Source Maps
文件。
在上传 Source Maps
文件的过程中,有一个点要特别注意,那就是上传时的 release
必须和 Sentry.init
方法执行时传入的的 release
配置保持一致,否则上传的 Source Maps
文件将无法起作用。
如果我们的应用是一个简单的 spa
架构,那么这一点很容易做到。我们只需要将 Sentry.init
中的 release
配置项和 webpack plugin
的 release
配置项(或者是 sentry cli
的 release_name
) 保持一致就可以了。
但如果我们的应用是一个复杂的微前端架构,比如使用 Qiankun
,那要做到这一点就比较麻烦。在 使用 Sentry 做异常监控 - 如何优雅的解决 Qiankun 下 Sentry 异常上报无法自动区分项目的问题 ? 中,我们将 Sentry.init
动作放在主应用中,而上传 Source Maps
的动作放在了子应用中, 那怎样能保证这两者的 release
配置项保持一致呢?
这个问题,其实也好解决。接下来,小编就通过下面这个章节给大家梳理一下。
解决方案
其实,Sentry.init
方法执行时传入的 release
参数,最终是在通过接口上报异常时作为入参来使用的。因此我们可以在主应用对异常上报做拦截时,根据异常对应的追踪栈信息找到异常属于哪个子应用,然后重写这次异常上报的 release
参数。
为了能保证异常上报时的 release
和 Source Maps
文件上传的 release
保持一致,小编在这里提供了两种方案:固定版本号和自定义版本号。
方案一: 固定版本号
固定版本号的方案非常简单,即写死 release
配置项即可。通常我们可以使用项目在 Sentry
中的 Project ID
作为 release
。
举个 🌰,我们的某个子应用对应的 Project ID
为 by-aicc
, 那我们可以在子应用上传 Source Maps
文件时,将 release
设置为 by-aicc
。当异常上报被拦截,确认异常属于项目 by-aicc
时,我们可以将异常上报接口中的 release
参数也设置为 by-aicc
。这样,我们就可以保证两者的 release
一致。
不过这种方式有点简单粗暴。通常,我们会根据项目发布的日期、版本等信息来动态配置 release
,这样可以帮助我们快速定位问题。如果简单的设置为项目 ID
,相反会给我们排查定位问题带来负担,有点聪明反被聪明误了。
方案二: 自定义版本号
既然固定版本号的方案不可取,那我们就来尝试一下自定义版本号的方案。
自定义版本号方案的难点在于:主应用如何获取到子应用当前的自定义 release
。只要解决了这个痛点问题,那么对应的方案也就可行了。
关于这一点,Qiankun
的 html entry
给了小编灵感。
Qiankun
在首次加载子应用时,会根据路由注册表中的 entry
配置项,去读取子应用的入口文件 - index.html
,然后解析入口文件,拿到子应用的入口 js
文件,然后通过 sandbox
的方式去执行 js
文件,拿到子应用的生命周期方法。
既然这样,那我们可以将子应用的自定义 release
以内联 script
的方式添加到 index.html
中,等到 Qiankun
在处理子应用的 index.html
文件时,执行这段 script
脚本,把自定义 release
添加到 window
中。等接口被拦截需要重新设置 release
时,直接从 window
中读取就可以了。
举个 🌰,我们可以通过 html-webpack-plugin
,在 index.html
中动态添加自定义 release
,如下:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const config = {
plugins: [
new HtmlWebpackPlugin({
templateContent: `
<html>
<body>
<h1>Hello World</h1>
<script type="text/javascript">
window["by-aicc-release"] = 'xxxxx'
</script>
</body>
</html>
`
})
],
};
其他类型的构建工具,也提供了自定义 index.html 的方式。实在不行,我们写个 gulp 任务,自动给 index.html 中添加 script 脚本。
当主应用拦截异常上报,并确定这个异常属于 by-aicc
时,可以通过 window["by-aicc-release"]
的方式去获取自定义 release
,然后重新设置接口的 release
的参数,保证两者的 release
一致。
这样,整个问题就完美解决了,👍🏻。
结束语
到这里,关于如何解决 Qiankun
下 soucemap
自定义版本号问题的梳理就结束了。
简单总结一下,为了解决这个问题,小编提出了固定版本号和自定义版本号两种解决方案。其中,固定版本号方案比较简单粗暴,不是很推荐使用;自定义版本号方案相比更优秀,适用于实际项目使用。
如果有小伙伴们也遇到了同样的问题,不妨试试自定义版本号方案吧,😄。