概述
对于任何的客户端应用,开发者都希望能够在用户上的手上记录下相关信息以便了解真实的使用情况。
一般情况下,分为以下两种信息:
在不涉及隐私的情况下,让开发者了解用户使用客户端的详细情况,从这些情况中提炼的信息能够让开发者根据用户的使用情况更好地优化产品
用户的使用环境千差万别,有时候可能会让客户端崩溃。崩溃日志的收集,有利于让开发人员更好地定位,解决问题
对于日志的处理,一般分为 收集 、上报、分析等多个步骤,本文主要细分讲述 Electron 客户端应用的崩溃日志收集步骤, 官方参考: 将崩溃日志提交给远程服务器
大致流程如下:
开启 Electron Crash Reporter
开起后,可以收集 Electron 应用的奔溃堆栈,Electron Crash Reporter 支持将奔溃堆栈上传到在线的第三方服务平台,用户也可以通过配置上传自己的服务器(服务端需要自己开发),也可以只生成奔溃堆栈文件在本地,用于排查奔溃问题。下面将只介绍如何生成奔溃堆栈文件到本地。
开启奔溃堆栈文件生成,并获取奔溃文件存放路径
需要在 main 进程的 JavaScript 代码中,在一开始的位置添加如下代码,开启 Electron Crash Reporter 捕获功能。
const { app, BrowserWindow, crashReporter, ipcMain, systemPreferences } = require('electron');
const path = require('path');
// 获取奔溃堆栈文件存放路径
let crashFilePath = '';
let crashDumpsDir = '';
try {
// electron 低版本
crashFilePath = path.join(app.getPath('temp'), app.getName() + ' Crashes');
console.log('————————crash path:', crashFilePath);
// electron 高版本
crashDumpsDir = app.getPath('crashDumps');
console.log('————————crashDumpsDir:', crashDumpsDir);
} catch (e) {
console.error('获取奔溃文件路径失败', e);
}
// 开启crash捕获 官方建议写在app.on('ready')前
crashReporter.start({
productName: 'Your-Application-Name',
companyName: 'Your-Company-Name',
submitURL: 'https://www.xxx.com', // 上传到服务器的地址
uploadToServer: false, // 不上传服务器
ignoreSystemCrashHandler: false, // 不忽略系统自带的奔溃处理,为 true 时表示忽略,奔溃时不会生成奔溃堆栈文件
});
以上代码不能保证每次奔溃,都收集到奔溃堆栈,但如果奔溃较频繁,很可能在某次奔溃时生成,如果发现生成了奔溃堆栈,一定不要视而不见,对于偶现的奔溃问题,奔溃堆栈文件对定位排查问题很有帮助。
将奔溃堆栈文件存放目录写到渲染进程日志
通过安装包执行的应用,Electron 主进程的日志通常看不到或者不好查阅(可借助 Node.js 文件 API 写本地日志文件),可以将奔溃堆栈文件的存放路径打印到渲染进程的控制台,方便查询。实现方式参阅下方代码。
mainWindow.webContents.on('did-finish-load', function(event){
mainWindow.webContents.send('crash-file-path', `${crashFilePath} or ${crashDumpsDir}`);
});
mainWindow.webContents.on('did-finish-load', function(event){
mainWindow.webContents.send('crash-file-path', `${crashFilePath} or ${crashDumpsDir}`);
});
监听 Electron 渲染进程和 GPU 进程奔溃事件
Electron 提供了监听渲染进程和 GPU 进程奔溃的事件接口,监听这些事件,可以知道何时发生了奔溃,但奔溃的具体原因一般看不出来,需要获取奔溃堆栈的 dump 文件。
在 Electron main 进程的启动脚本,增加如下代码,监听奔溃事件,可以把这些日志写入本地文件。
注意:此时渲染进程可能已经奔溃,不能发送给渲染进程打印到窗口的控制台,奔溃事件的日志最好写到本地文件或者发送个服务端。
app.on('gpu-process-crashed', (event, kill) => {
console.warn('app:gpu-process-crashed', event, kill);
});
app.on('renderer-process-crashed', (event, webContents, kill) => {
console.warn('app:renderer-process-crashed', event, webContents, kill);
});
app.on('render-process-gone', (event, webContents, details) => {
console.warn('app:render-process-gone', event, webContents, details);
});
app.on('child-process-gone', (event, details) => {
console.warn('app:child-process-gone', event, details);
});
注意:event 和 webContents 对象直接写文件,可以 JSON.stringify() 后写入。
测试崩溃报告
直接在主进程写入该代码, 就会直接崩溃, 生成崩溃本地文件
// 测试崩溃报告日志
process.crash()
奔溃堆栈文件分析
奔溃堆栈文件的分析,需要 Node.js C++ add-on 程序编译时的符号文件,WIndows下为 dmp 文件,Mac 下为 dSYM 文件,
获取到对应的崩溃文件后,需要对 dump 文件进行分析,推荐工具为 google 的 breakpad。关于 breakpad,不同平台有不同的安装方法,需要各位看官通过官方文档仔细安装(mac 要用 xcode 进行编译,windows需要额外安装 gcc)
假设已经安装好了 breakpad,那么我们会有两个工具:dump_syms 和 minidump_stackwalk,在这里,我们关键会用到 minidump_stackwalk这个工具
通过如下命令行,把 minidump 文件解析并存储结果到 output.txt 中
minidump_stackwalk 15dcad6faa9e9914ae9016d794c391a8 > ./output.txt
可使用VS打开查看崩溃日志