本文档描述 CatScope 的技术架构、模块边界和关键实现策略。
首选方案:
桌面框架:Wails v2
后端语言:Go
前端框架:Vue 3 + TypeScript
构建工具:Vite
ADB 调用:Go exec.Command 调用本地 adb
构建调用:Go exec.Command 调用 gradlew / gradlew.bat
本地存储:JSON 配置文件和 `.catscope-session` 文件(SQLite 为后续可选方向)
日志渲染:虚拟滚动列表
┌─────────────────────────────┐
│ Frontend │
│ Vue 3 + TypeScript + Vite │
│ │
│ - 日志主界面 │
│ - 过滤器面板 │
│ - 设备选择器 │
│ - 构建安装面板 │
│ - 崩溃分析面板 │
│ - AI 上下文生成面板 │
└──────────────┬──────────────┘
│ Wails Bridge
┌──────────────▼──────────────┐
│ Go Core │
│ │
│ - ADB Manager │
│ - Logcat Stream Manager │
│ - Log Parser │
│ - Filter Engine │
│ - Build Runner │
│ - Install Runner │
│ - Launch Runner │
│ - Session Storage │
│ - Exporter │
│ - Analyzer │
└──────────────┬──────────────┘
│ exec.Command
┌──────────────▼──────────────┐
│ Android Toolchain │
│ │
│ - adb │
│ - gradlew / gradlew.bat │
│ - Android SDK │
└─────────────────────────────┘
CatScope 前端使用 Vue 3 生态。建议组合如下:
Vue 3:主前端框架
TypeScript:类型约束
Vite:开发和构建
Pinia:全局状态管理
Naive UI:主 UI 组件库
VueUse:常用组合式工具函数
@vicons/ionicons5:图标方案
@tanstack/vue-virtual:日志虚拟滚动
选择 Naive UI 的原因:
- Vue 3 原生支持较好。
- 暗色主题和桌面工具风格适配较好。
- 表格、表单、弹窗、抽屉、标签页、下拉选择、通知组件比较完整。
- 适合快速实现设备选择、过滤器面板、日志详情面板、错误提示等界面。
日志主表格不要完全依赖普通 DataTable 渲染海量日志。大量日志场景下,应优先使用专门的虚拟滚动列表实现行渲染,再组合 Naive UI 的按钮、选择器、输入框、弹窗、通知等组件。
职责:
- 查找 adb 路径
- 执行 adb 命令
- 获取设备列表
- 获取设备基础信息
- 管理多设备 serial
常用命令:
adb devices -l
adb -s <serial> get-state
adb -s <serial> shell getprop ro.product.model
adb -s <serial> shell getprop ro.build.version.release
adb -s <serial> shell getprop ro.build.version.sdk
adb -s <serial> shell getprop ro.product.cpu.abi
adb -s <serial> shell pm list packages
adb -s <serial> shell pidof <package>设备结构:
type AndroidDevice = {
serial: string
state: "device" | "offline" | "unauthorized" | "unknown"
model?: string
brand?: string
androidVersion?: string
sdkVersion?: string
abi?: string
isEmulator?: boolean
}职责:
- 启动 Logcat 流
- 停止 Logcat 流
- 重启 Logcat 流
- 捕获 stdout / stderr
- 处理 ADB 断开
- 自动重连
- 支持 buffer 选择
推荐命令:
adb -s <serial> logcat -v threadtime -b main,system,crash支持 buffer:
main
system
crash
events
radio
all
职责:
- 解析 threadtime 格式
- 解析失败时保留 raw
- 多行日志合并
- Java stacktrace 合并
- Native crash 合并
- JSON 日志格式化
- 厂商 ROM 特殊格式兼容
日志结构:
type LogEntry = {
id: number
timestamp: string
pid: number
tid: number
level: "V" | "D" | "I" | "W" | "E" | "F"
tag: string
message: string
packageName?: string
raw: string
multiline?: string[]
}多行归并策略:
如果当前行符合标准 Logcat 头部,则创建新的 LogEntry。
如果当前行不符合标准头部,则追加到上一条 LogEntry 的 multiline 字段。
过滤分三层:
- 采集层过滤:减少 ADB 输出量。
- 解析层过滤:Go 后端按字段过滤。
- UI 层过滤:前端临时搜索和高亮。
过滤器结构:
{
"name": "Native Crash",
"levels": ["E", "F"],
"tags": ["AndroidRuntime", "DEBUG", "libc"],
"messageRegex": "SIGSEGV|SIGABRT|tombstone|backtrace|JNI DETECTED ERROR",
"packageName": "com.example.app",
"excludeRegex": "Choreographer|OpenGLRenderer"
}职责:
- 限制内存占用
- 保留最近 N 行日志
- 支持丢弃旧日志计数
- 支持前端增量拉取
建议默认:
maxLogLines = 100000
内置分析器:
- Java Crash Analyzer
- Native Crash Analyzer
- ANR Analyzer
- Install Error Analyzer
Java Crash 关键词:
FATAL EXCEPTION
AndroidRuntime
Caused by:
NullPointerException
ClassNotFoundException
NoClassDefFoundError
SecurityException
UnsatisfiedLinkError
Native Crash 关键词:
signal 11
SIGSEGV
SIGABRT
backtrace:
tombstone
libxxx.so
JNI DETECTED ERROR
ANR 关键词:
ANR in
Input dispatching timed out
BroadcastQueue
executing service
Application Not Responding
职责:
- 选择项目根目录
- 检测 Gradle Wrapper
- 执行 assembleDebug
- 捕获构建输出
- 定位 APK 文件
Windows 命令:
gradlew.bat assembleDebugUnix 命令:
./gradlew assembleDebug职责:
- 安装 APK
- 捕获安装输出
- 识别安装错误
基础命令:
adb -s <serial> install -r <apk-path>常见错误:
INSTALL_FAILED_VERSION_DOWNGRADE
INSTALL_FAILED_UPDATE_INCOMPATIBLE
INSTALL_FAILED_NO_MATCHING_ABIS
INSTALL_FAILED_INVALID_APK
INSTALL_PARSE_FAILED_NO_CERTIFICATES
INSTALL_PARSE_FAILED_MANIFEST_MALFORMED
MVP 阶段优先使用 monkey 启动:
adb -s <serial> shell monkey -p <package> 1后续支持解析 launcher activity:
adb -s <serial> shell cmd package resolve-activity --brief <package>职责:
- 提取选中日志
- 提取错误前后上下文
- 提取设备信息
- 提取 App 信息
- 提取 Build / Install 输出
- 生成 Markdown 分析材料
internal/update 负责读取 GitHub Releases、按正式版或 Preview 通道比较语义版本,并选择当前平台对应的发布资产。Windows 自动安装流程只接受 GitHub HTTPS 下载地址,下载 EXE 后必须通过同名 .sha256 文件校验。
Windows 不能覆盖运行中的 EXE,因此主程序会把自身复制到系统临时目录并以 updater 模式启动。updater 等待主程序退出后,先保留旧 EXE、替换新 EXE、重新启动 CatScope,再由新进程清理临时目录。发布物仍然是单个 EXE。macOS 当前只提供更新检测和 Release 页面入口。
顶部工具栏:设备选择 | 包名选择 | Level | 搜索 | 开始/暂停 | 清屏 | 导出 | 构建安装
左侧面板:过滤器列表 | 已安装应用 | 历史会话
中间区域:日志表格
右侧面板:日志详情 | 崩溃分析 | AI 上下文
底部状态栏:设备状态 | 日志数量 | 丢弃数量 | ADB 状态 | 内存占用
时间 | Level | PID | TID | Package | Tag | Message
Ctrl + F:搜索
Ctrl + L:清屏
Ctrl + P:暂停 / 恢复
Ctrl + S:保存当前日志
Ctrl + E:导出日志
Ctrl + R:刷新设备
Ctrl + B:Build
Ctrl + I:Install
Ctrl + Enter:Build + Install + Launch
Esc:关闭当前详情面板或搜索框
- 后端持续读取 adb stdout。
- 后端解析 LogEntry。
- 后端写入 Ring Buffer。
- 前端每 100ms - 300ms 拉取新增批次。
- 前端使用虚拟滚动渲染。
- 超出上限时丢弃旧日志并显示丢弃数量。
- 用户主动保存时再落盘。
{
"adbPath": "",
"androidSdkPath": "",
"theme": "system",
"defaultBuffer": ["main", "system", "crash"],
"defaultLogFormat": "threadtime",
"maxLogLines": 100000,
"autoReconnect": true
}{
"projectName": "ExampleApp",
"projectPath": "D:/workstation/android/ExampleApp",
"packageName": "com.example.app",
"gradleCommand": "gradlew.bat",
"defaultTask": "assembleDebug",
"defaultModule": "app",
"defaultVariant": "debug",
"lastDeviceSerial": "",
"filters": []
}App 重启后 PID 会变化。需要通过 packageName 定期刷新 pidof,发现 PID 变化后自动更新过滤条件。
Java stacktrace、Native crash、ANR 日志通常是多行。非标准头部日志必须追加到上一条 LogEntry。
必须使用 Ring Buffer、批量刷新和虚拟滚动。
MVP 阶段只支持 assembleDebug,不做完整 Gradle Project Sync。
查找顺序:
用户配置 adbPath
ANDROID_HOME / ANDROID_SDK_ROOT
PATH
用户手动选择