我用Flutter Deskstop做了一个Mars Xlog日志解析工具
时间:2023-02-03 12:00:00
前言
我的最后一篇文章 2022腾讯Mars Xlog日志系统集成指南-iOS篇 详细的介绍iOS下接入Xlog日志系统指南。 Xlog日志接入了之后,我们要对它进行解析,如果不解析那就是一堆加密的二进制数据。常规的分析方案是使用Mars官方的python文件 修改一下private key可以直接分析,但因为是用的python2且需要pip安装一堆库,很多人用起来很痛苦,所以我是基于Flutter Deskstop 做的Mars Xlog日志分析工具XlogDecoder就这样诞生了。此工具采用Flutter目前只支持编写Mac,不需要内置解码库python环境。
代码过程
一、编译Python文件成可执行文件
Mars解析Xlog这三个日志主要由官方源码组成Python文件构成,一个是加密分析脚本,一个是不加密分析脚本,另一个是提供生成RSA Key脚本。如果我们想做桌面GUI如果工具不依赖机器环境,我们只能使用这三个py将文件编译成可执行文件供应直接运行。
编译python文件成为可执行文件,我们使用著名的文件pyinstaller制作。
- 安装方式
pip3 install pyinstaller
由于Mars的脚本都是python2.我们需要这个,而且版本很低。我花了很长时间才确认版本可以支持编译。我们需要这样安装 (注意Mac 12.3 之后会移除自带python2.如果需要自己安装python2)
python -m pip install PyInstaller==3.3.1
- 开始编译可执行文件
decode_mars_crypt_log_file.py
因为默认是写死的private_key, 我们需要修改脚本,让脚本支持输入参数private key
//decode_mars_crypt_log_file.py 修改 PRIV_KEY=sys.argv[1] # PRIV_KEY = "145aa7717bf9745b91e9569b80bbf1eedaa6cc6cd0e26317d810e35710f44cf8" //main 函数转换为接收参数2 main(sys.argv[2:]) 然后执行编译命令: python -m PyInstaller ./decode_mars_crypt_log_file.py
新添加的编译产品disk在目录下,会有一个人和你在一起py同名文件夹,剩下两个py我们可以用同样的方式编译文件。
二、导入编译产品到flutter项目
我们将导入三个可执行文件flutter image目录,
pubspec.yaml 指定目录
三、应用内获取assets目录
Flutter编译包装后,所有资源都放在一起flutter_assets在目录中,我强行找到它。
static final String _assetsPath = Platform.isWindows ? '../data/flutter_assets/images' : '../../Frameworks/App.framework/Resources/flutter_assets/images'; static File mainFile = File(Platform.resolvedExecutable); static Directory _assetsDir = Directory(path.normalize(path.join(mainFile.path, _assetsPath)));
四、通过相关UI事件以及Flutter 自带 Process类运行执行文件
- 例如,生成一个新的RSA
//操作方法 Future genKey() async { var pyPath = path.joinAll([ _assetsDir.path, "gen_key", "gen_key" ]); var process = await Process.run(pyPath, []); print("result:\n"); print("${process.stdout}"); return process.stdout; } //按钮事件 PushButton( buttonSize: ButtonSize.large, child: Text('生成 RSA Key'), onPressed: () async { var result = await controller.genKey(); showMacosAlertDialog( barrierDismissible: true, useRootNavigator: false, context: context, builder: (context) => MacosAlertDialog( appIcon: Image.asset( "images/app_icon.png", width: 64, height: 64, ), title: Text( '请记住你生成的RSA Key', style: TextStyle( fontWeight: FontWeight.w500, fontSize: 16), ), message: Text( result, ), horizontalActions: false, primaryButton: PushButton( buttonSize: ButtonSize.large, child: const Text(复制), onPressed: () { ClipboardData data = ClipboardData(text: result); Clipboard.setData(data); showToast("粘贴板已复制", textPadding: EdgeInsets.all(15)); Navigator.of(context).pop(); }, ),
secondaryButton: PushButton(
buttonSize: ButtonSize.large,
child: const Text('取消'),
onPressed: Navigator.of(context).pop,
),
),
);
},
),
- 解析日志
解析日志我们可以选择直接拖动xlog日志文件过来,也可以选择点击按钮选择。如果是文件夹拖过来我也会遍历目录符合xlog后缀的我全都是添加进去队列解析。
核心解析日志方法:
void beginCompressTask({required XlogInfoItemViewModel vm}) async {
if (savePath.value.length == 0) {
print("save path no define");
vm.updateStatus(XlogInfoStatus.fail);
taskList.refresh();
return;
}
if (this.isEnableCrypt.value == true && (this.cryptMd5.value.isEmpty || this.cryptMd5.value.length != 64)) {
print("private key is empty");
showToast("Private Key 为空或长度不对(64位)", textPadding: EdgeInsets.all(15));
vm.updateStatus(XlogInfoStatus.fail);
taskList.refresh();
return;
}
print("save path : $savePath");
var dir = await createDirectory(savePath.value);
if (dir == null) {
vm.updateStatus(XlogInfoStatus.fail);
taskList.refresh();
return;
}
var pyPath = path.joinAll([
_assetsDir.path,
"decode_mars_crypt_log_file",
"decode_mars_crypt_log_file"
]);
if (this.isEnableCrypt.value == false) {
pyPath = path.joinAll([
_assetsDir.path,
"decode_mars_nocrypt_log_file",
"decode_mars_nocrypt_log_file"
]);
}
List args = [vm.file.path];
if (this.isEnableCrypt.value == true) {
args.insert(0, this.cryptMd5.value);
}
var process = await Process.run(pyPath, args);
if (process.exitCode != 0) {
showToast("Xlog解析失败,请检查你的Private Key是否正确", textPadding: EdgeInsets.all(15));
vm.updateStatus(XlogInfoStatus.fail);
taskList.refresh();
return;
}
var file = File(vm.file.path + ".log");
var isExist = await file.exists();
if (isExist) {
await Process.run("mv", [
"-f",
file.path,
savePath.value,
]);
vm.saveFile = File(path.joinAll([savePath.value, file.fileName]));
vm.updateStatus(XlogInfoStatus.success);
taskList.refresh();
} else {
vm.updateStatus(XlogInfoStatus.fail);
taskList.refresh();
}
}
末尾
本次开源的工具暂时只支持Mac。 pyinstaller输出的也是mac才支持的可执行文件,由于pyinstaller也是跨平台的,理论上在windows机器安装 pyinstaller 直接输出适配windows的可执行文件,不同平台则替换一下相应文件,就可以适配windows。如果本次开源了反响比较大,后续我也会支持windows。否则本篇文章则可以给大家供学习,理论上Flutter的很多工具类软件都可以基于此方法编写。
附件
iOS接入xlog的Demo参考:
- xlog_ios_demo
本篇文章开源地址:
- xlog_decoder