我用Flutter Deskstop做了一个Mars Xlog日志解析工具

2,026 阅读3分钟

前言

我的上篇文章 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<String> 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<String> args = <String>[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参考:

本篇文章开源地址: