Electron-开发实践:crash上报及解析
【前言】
electron开发实践中,crash的上报不可避免,
electron中可以通过crashReporter来上报crash,
https://www.electronjs.org/docs/latest/api/crash-reporter ,
而处理crash使用的是crashpad,有兴趣的可以继续研究下,
https://chromium.googlesource.com/crashpad/crashpad/+/refs/heads/main/README.md
【crashReporter】
通过start方法启动上报,
start需要尽早的调用,
例如在app.on(‘ready’)前
// crash reporter
const { crashReporter } = require("electron");
/**
* start方法
*/
crashReporter.start({
// 要上报的服务器地址
submitURL: "https://your-domain.com/url-to-submit",
// 产品名称
productName: "x",
// 是否压缩,默认true,如果开启会上传gzip,服务器要处理一下
compress: false,
// 是否限制频次,默认为false,如果开启每小时上传1次
rateLimit: false,
// 是否上传到服务器,默认为true,如果关闭只在本地生成crash文件
uploadToServer: true,
// 是否禁止系统crash处理,默认为false
ignoreSystemCrashHandler: false,
// 携带的参数,extra中的参数只有主进程崩溃会携带
extra: {
userId: "xxx",
},
// 携带的参数,globalExtra中的参数所有进程崩溃都会携带
globalExtra: {
userId: "xxx",
},
});
通过addExtraParameter来添加携带的参数
crashReporter.addExtraParameter(key, value);
通过crash方法来产生crash,进行测试
process.crash();
如果需要子进程单独上报,可以使用如下方法
process.crashReporter.start(options);
【服务端处理上报】
这里服务端使用qiao-z这个框架来演示,
文档: https://qiao-z.vincentqiao.com/#/
服务端:安装依赖
npm i qiao-z qiao-z-upload
服务端:app.js
// qz
const qz = require("qiao-z");
// app
const app = qz({
upload: require("qiao-z-upload"),
});
// listen
app.listen(9001);
服务端:CrashController.js,qiao-z会自动扫描Controller.js结尾的文件,并注册路由
// fs
const { renameSync } = require("fs");
// path
const { resolve } = require("path");
/**
* crash controller
*/
module.exports = (app) => {
// crash
app.post("/crash", async (req, res) => {
try {
// fields
const fields = req.body.fields;
console.log("fields: ", fields);
// file info
const fileInfo = req.body.files.upload_file_minidump;
const tmpPath = fileInfo.filepath;
const destPath = resolve(__dirname, fileInfo.originalFilename);
renameSync(tmpPath, destPath);
// return
res.send("crash success");
} catch (e) {
console.log(e);
res.send("crash failed");
}
});
};
服务端:启动服务
node app.js
electron:设置crashReporter的submitURL
submitURL: 'http://localhost:9001/crash',
electron:crashReporter启动后设置4s后的crash
// report
crashReporter.start(options);
// crash
setTimeout(() => {
process.crash();
}, 4000);
服务端:查看效果
1.dmp文件

2.获取到的上报信息
这里可以看到,处理一些基础信息,已经上报了globalExtra中的userId信息

【解析dmp文件】
如上,已经获取到electron应用crash的dmp文件了,
那么,如何解析dmp文件呢,稍微比较复杂
安装depot_tools
breakpad依赖于depot_tools
|— 首先clone项目
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
|— 然后设置path
export PATH=/path/to/depot_tools:$PATH
安装breakpad
|— 创建文件夹
mkdir breakpad && cd breakpad
|— 下载breakpad
fetch breakpad
cd src
|— 构建breakpad
./configure && make
|— 安装命令
make install
下载electron symbols文件
|— 下载地址: https://github.com/electron/electron/releases
|— 找到对应操作系统和electron版本的symbols.zip文件并下载,例如我本地是22.0.0版本

使用breakpad解析dmp文件
|— 使用breakpad的minidump_stackwalk命令解析dmp文件
minidump_stackwalk -s PATH_TO_DUMP PATH_TO_electron.breakpad.sym
上面两个路径,
第一个是dmp路径,例如:
dmp/e66fdb11-043e-4f4f-ac24-8a473d54e0b3.dmp
第二个是sym路径,例如:
electron-v22.0.0-darwin-arm64-symbols/breakpad_symbols/chrome_crashpad_handler/chrome_crashpad_handler.sym
执行命令后解析效果如下

【electron-minidump】
上面解析完后的文件基本没有可读性,
是因为只使用的chrome对应的符号文件进行解析,
如果把一个dmp文件比喻为一个构建后的js文件,
如果想解析js文件所有的源码,
需要知道这个js引用的所有npm包的源码。
依次类推,解析一个dmp文件需要用到很多符号表,
比如electron的,electron渲染进程的,chrome的等等,
这里推荐一个工具进行解析: https://www.npmjs.com/package/electron-minidump
简单总结这个工具的解析方法
1.下载dmp文件对应的所有需要的sym文件
2.使用这些sym文件解析dmp文件
使用方式如下:
npx electron-minidump -f /path/to/your/dmp/file
效果如下
下载sym文件:

可以看到解析一个dmp文件,
需要下载对应的607个sym文件,
解析后内容如下:

可以看到这次解析后已经可以看到具体的异常堆栈了
【第三方方案】
上述本地解析dmp文件比较麻烦,
是否有比较方便的方案,
确实有,但是大部分收费,
例如: https://sentry.io/welcome/
【总结】
1. electron crashReporter如何使用
2. 服务端如何接收crash上报
3. 本地如何解析接收到的dmp文件
4. 其他解析方案
相关推荐
Electron-开发实践:注册苹果开发者账号
【前言】 当使用electron开发完一个mac应用后, 如果想正常在mac电脑上使用, 还需要对你的应用进行签名和公证, 而签名和公证都需要一个苹果开发者账号, 这个过程中有一些坑,记录一下。 【注册】 注册地址: https://developer.apple.com/cn/programs/e
Electron-开发实践:clipboard剪切板
【前言】 Electron提供获取和写入系统剪切板的操作, 详见:https://www.electronjs.org/docs/latest/api/clipboard 【进程】 clipboard支持主进程使用,支持没有开启sandbox的渲染进程使用 【系统】 大部分clipboard的api
Electron-开发实践:DMG安装包定制
【前言】 dmg文件是mac端常见的安装包格式, 前面几篇文章已经使用electron开发并打包好一个应用了, 本文主要讲下定制dmg安装包, 前面几篇文章: 一篇文章学会Electron Electron开发实践:本地数据库SQLite Electron开发实践:使用Monorepo管理Elect
Electron-开发实践:包体积精简
【前言】 前面几篇文章讲了从开发electron应用到mac打包, 相关文章: 一篇文章学会Electron Electron开发实践:本地数据库SQLite Electron开发实践:使用Monorepo管理Electron项目 Electron开发实践:Mac打包 Electron开发实践:注册
Electron-开发实践:制作icns图标
【省流】 封装了一个mac上将png转为icns的应用, 欢迎大家使用: https://electronicns.com/ 【前言】 将Electron应用打包为Mac应用包的时候, 这里以electronpackager打包为例, 默认打包运行后的应用图标是这样, 【icns】 按electro
Electron-开发实践:本地日志
【前言】 使用electron开发好本地应用后, 本地日志记录必不可少, 这样可以通过日志获取用户操作信息以及定位bug等, 本地日志与实时性的埋点上报稍微有不同, 本地日志量更大,信息更全,且不是所有信息都时候上报。 【与nodejs本地日志的异同】 electron写本地日志和nodejs写本地
Electron-开发实践:定制Mac菜单
【前言】 前面几篇文章讲了从开发electron应用到mac打包, 相关文章: 一篇文章学会Electron Electron开发实践:本地数据库SQLite Electron开发实践:使用Monorepo管理Electron项目 Electron开发实践:Mac打包 Electron开发实践:注册
Electron-开发实践:Mac应用包签名和公证
【前言】 一篇文章学会Electron Electron开发实践:本地数据库SQLite Electron开发实践:使用Monorepo管理Electron项目 当你通过上面这些文章使用Electron开发好一个桌面应用, Electron开发实践:Mac打包 并通过这个文章在本地打包好了mac的应
Electron-开发实践:Mac打包
【前言】 当本地开发好一个 electron 应用后, 最想做的事情就是打包然后分享出去。 如何用 monorepo 管理一个 electron 项目, 可以看这里: Electron开发实践:使用Monorepo管理Electron项目 【构建】 接上一篇,打包是在 packages/dishie
Electron-开发实践:使用Monorepo管理Electron项目
【前言】 本文讲如何用 monorepo 来管理一个 electron 项目 代码地址: https://github.com/uikoo9/dishimonorepo/tree/electronmonorepo 【初始化】 首先需要初始化一个 monorepo 前端项目, 具体步骤可以看这里: 初
Electron-开发实践:注册快捷键
【前言】 本文介绍一下electron应用中如何注册快捷键 【主进程】 主进程注册快捷键比较简单,需要注意的是在app ready后使用, 常见键盘映射: https://www.electronjs.org/docs/latest/api/accelerator 另外在推出app时需要将所有注册的
Electron-开发实践:几种更新方式
【前言】 Electron开发桌面APP后, 接着涉及一个问题就是如何更新后续的版本, 本文介绍几种更新的方式。 【Electron架构】 用Electron开发的桌面APP, 其实包含几个部分: 1\. Electron本身的环境 2\. 主进程,主进程中又分为Nodejs部分,和非Nodejs部
Electron-开发实践:创建Window
【前言】 Electron入门就需要创建一个window, window是用来展示ui的, window是在渲染进程。 【创建window】 新建一个前端项目, package.json内容如下, 可以看到安装了Electron的开发依赖, 即执行过下面的命令, 且有一个start命令用来本地启动E
一篇文章学会Electron
【前言】 javascript语言的强大生命力,为前端开发拓展了很多业务 网页端业务:基于js,html,css开发网页相关业务 服务端业务:基于nodejs开发服务端业务 桌面端业务:基于chromium和nodejs开发桌面业务 移动端业务:基于webview开发移动端业务 【electron简
Electron-开发实践:本地数据库SQLite
【前言】 本地存取数据的一些常见的手段:Cookie,LocalStorage,IndexedDB,SQLite等, 这里做下简单的对比 Cookie 存储大小:4k 设置有效期:可以 服务端获取:可以 特点:简单数据存取 LocalStorage 存储大小:5M 设置有效期:不行 服务端获取:不行