399 lines
9.4 KiB
Markdown
399 lines
9.4 KiB
Markdown
# Android 应用调试日志抓取指南
|
||
|
||
## 当前日志配置分析
|
||
|
||
### ✅ 已有日志点
|
||
|
||
应用在关键位置使用 `android.util.Log` 记录日志:
|
||
|
||
| 日志标签 | 位置 | 日志内容 |
|
||
|---------|------|---------|
|
||
| `MainViewModel` | 所有 ViewModel 操作 | 会话创建、参与者加入、TSS进度、异常 |
|
||
| `TssRepository` | 所有 Repository 操作 | gRPC调用、TSS native调用、数据库操作 |
|
||
| `GrpcClient` | 网络通信 | gRPC连接、请求/响应、错误 |
|
||
| `TssNativeBridge` | TSS原生库 | 密钥生成、签名、错误 |
|
||
|
||
### 📋 关键日志内容
|
||
|
||
#### 1. 会话创建(创建2-of-3钱包)
|
||
```
|
||
MainViewModel: Creating new session: walletName=xxx, t=2, n=3
|
||
MainViewModel: Session created: sessionId=xxx, inviteCode=xxx
|
||
MainViewModel: Session status fetched: X participants already joined
|
||
MainViewModel: Participants: [partyId1, partyId2, ...]
|
||
```
|
||
|
||
#### 2. 密钥生成触发
|
||
```
|
||
MainViewModel: Session started event for keygen initiator, triggering keygen
|
||
MainViewModel: Starting keygen as initiator: sessionId=xxx, t=2, n=3
|
||
TssRepository: Starting keygen as initiator
|
||
TssNativeBridge: keygenAsInitiator called
|
||
```
|
||
|
||
#### 3. 异常捕获(safeLaunch)
|
||
```
|
||
MainViewModel: Caught exception in safeLaunch
|
||
[Stack trace...]
|
||
```
|
||
|
||
---
|
||
|
||
## 🔍 日志抓取命令
|
||
|
||
### 方案 1: 实时日志(推荐用于复现问题)
|
||
|
||
```bash
|
||
# 清除旧日志
|
||
adb logcat -c
|
||
|
||
# 实时查看所有应用日志(带时间戳)
|
||
adb logcat -v time | grep -E "MainViewModel|TssRepository|GrpcClient|TssNativeBridge|AndroidRuntime"
|
||
```
|
||
|
||
### 方案 2: 过滤关键标签(快速定位)
|
||
|
||
```bash
|
||
# 只看应用相关日志
|
||
adb logcat MainViewModel:D TssRepository:D GrpcClient:D TssNativeBridge:D AndroidRuntime:E *:S
|
||
```
|
||
|
||
### 方案 3: 保存完整日志到文件
|
||
|
||
```bash
|
||
# 清除旧日志
|
||
adb logcat -c
|
||
|
||
# 重现问题(创建2-of-3钱包)
|
||
|
||
# 保存日志到文件
|
||
adb logcat -d -v time > android_debug.log
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 重点关注的日志
|
||
|
||
### 创建 2-of-3 钱包失败时需要看到:
|
||
|
||
#### ✅ 必须有的日志(正常流程)
|
||
1. **会话创建请求**:
|
||
```
|
||
MainViewModel: Creating new session: walletName=测试钱包, t=2, n=3, participantName=xxx
|
||
```
|
||
|
||
2. **会话创建成功**:
|
||
```
|
||
MainViewModel: Session created successfully
|
||
MainViewModel: sessionId: xxxxxxxx
|
||
MainViewModel: inviteCode: ABCD1234
|
||
```
|
||
|
||
3. **获取会话状态**:
|
||
```
|
||
MainViewModel: Session status fetched: 2 participants already joined
|
||
MainViewModel: Participants: [party-id-1, party-id-2]
|
||
```
|
||
|
||
4. **收到 session_started 事件**:
|
||
```
|
||
MainViewModel: === MainViewModel received session event ===
|
||
MainViewModel: eventType: session_started
|
||
MainViewModel: sessionId: xxxxxxxx
|
||
```
|
||
|
||
5. **触发密钥生成**:
|
||
```
|
||
MainViewModel: Session started event for keygen initiator, triggering keygen
|
||
MainViewModel: Starting keygen as initiator: sessionId=xxx, t=2, n=3
|
||
```
|
||
|
||
6. **TSS 原生库调用**:
|
||
```
|
||
TssNativeBridge: keygenAsInitiator called with sessionId=xxx
|
||
TssNativeBridge: Keygen completed successfully
|
||
```
|
||
|
||
7. **进度更新**:
|
||
```
|
||
MainViewModel: Progress update: 1 / 9
|
||
MainViewModel: Progress update: 2 / 9
|
||
...
|
||
MainViewModel: Progress update: 9 / 9
|
||
```
|
||
|
||
#### ❌ 可能出现的错误日志
|
||
|
||
1. **safeLaunch 捕获的异常**:
|
||
```
|
||
MainViewModel: Caught exception in safeLaunch
|
||
java.net.SocketTimeoutException: timeout
|
||
at ...
|
||
```
|
||
|
||
2. **gRPC 连接失败**:
|
||
```
|
||
GrpcClient: Failed to connect to server
|
||
GrpcClient: Error: UNAVAILABLE: io exception
|
||
```
|
||
|
||
3. **TSS 原生库错误**:
|
||
```
|
||
TssNativeBridge: keygenAsInitiator failed: [error message]
|
||
```
|
||
|
||
4. **会话创建失败**:
|
||
```
|
||
MainViewModel: Service check failed
|
||
TssRepository: Failed to create session: [error message]
|
||
```
|
||
|
||
---
|
||
|
||
## 🚨 关键问题检查点
|
||
|
||
### 1. 检查 safeLaunch 是否吞掉了异常
|
||
|
||
搜索日志中的:
|
||
```
|
||
"Caught exception in safeLaunch"
|
||
```
|
||
|
||
如果有这行,说明异常被捕获了,查看后续的堆栈跟踪。
|
||
|
||
### 2. 检查是否有 Result.failure 未处理
|
||
|
||
搜索:
|
||
```
|
||
"onFailure"
|
||
"Failed to"
|
||
"Error:"
|
||
```
|
||
|
||
### 3. 检查 session_started 事件是否触发
|
||
|
||
搜索:
|
||
```
|
||
"Session started event for keygen initiator"
|
||
```
|
||
|
||
如果**没有这行**,说明事件回调没有触发,密钥生成没有启动。
|
||
|
||
### 4. 检查参与者计数
|
||
|
||
搜索:
|
||
```
|
||
"Session status fetched: X participants"
|
||
```
|
||
|
||
如果参与者数量 < thresholdT(例如 2-of-3 需要至少2个参与者),会话不会启动。
|
||
|
||
---
|
||
|
||
## 📊 日志分析流程图
|
||
|
||
```
|
||
启动应用
|
||
↓
|
||
[搜索] "Service check"
|
||
├─ 成功 → 继续
|
||
└─ 失败 → 检查数据库/网络/原生库错误
|
||
↓
|
||
点击"创建钱包"
|
||
↓
|
||
[搜索] "Creating new session"
|
||
├─ 有 → 继续
|
||
└─ 无 → UI事件未触发(前端问题)
|
||
↓
|
||
[搜索] "Session created successfully"
|
||
├─ 有 → 继续
|
||
└─ 无 → 检查 gRPC 错误或 "onFailure"
|
||
↓
|
||
[搜索] "Session status fetched: X participants"
|
||
├─ 有 → 检查参与者数量是否 >= thresholdT
|
||
└─ 无 → getSessionStatus 调用失败
|
||
↓
|
||
[搜索] "Session started event"
|
||
├─ 有 → 继续
|
||
└─ 无 → WebSocket 事件未收到(服务器问题)
|
||
↓
|
||
[搜索] "Starting keygen as initiator"
|
||
├─ 有 → 继续
|
||
└─ 无 → safeLaunch 内部异常(搜索 "Caught exception")
|
||
↓
|
||
[搜索] "keygenAsInitiator called"
|
||
├─ 有 → 检查 "Keygen completed" 或 TSS错误
|
||
└─ 无 → 原生库调用未执行
|
||
↓
|
||
[搜索] "Progress update"
|
||
├─ 有 → TSS 正在进行,检查是否完成
|
||
└─ 无 → TSS 未启动或卡住
|
||
↓
|
||
[搜索] "Keygen completed successfully"
|
||
├─ 有 → 成功!
|
||
└─ 无 → 检查 TSS 错误日志
|
||
```
|
||
|
||
---
|
||
|
||
## 🛠️ 调试建议
|
||
|
||
### 如果看到 "Caught exception in safeLaunch"
|
||
|
||
**原因**: safeLaunch 捕获了异常但可能没有正确显示给用户
|
||
|
||
**临时解决方案**: 查看异常堆栈,找到根本原因
|
||
|
||
**示例**:
|
||
```
|
||
MainViewModel: Caught exception in safeLaunch
|
||
java.net.SocketTimeoutException: timeout
|
||
at okhttp3.internal.connection.RealCall.execute
|
||
at ...
|
||
```
|
||
→ 说明 gRPC 连接超时
|
||
|
||
### 如果没有 "Session started event"
|
||
|
||
**原因**: WebSocket 事件回调未触发
|
||
|
||
**可能问题**:
|
||
1. service-party 服务器未运行
|
||
2. WebSocket 连接断开
|
||
3. 服务器未广播 session_started 事件
|
||
4. 参与者数量不足(< thresholdT)
|
||
|
||
**检查**:
|
||
```bash
|
||
# 检查服务器日志
|
||
tail -f /path/to/service-party/logs/server.log
|
||
```
|
||
|
||
### 如果有 "Session started event" 但没有 "Starting keygen"
|
||
|
||
**原因**: safeLaunch 内部的 startKeygenAsInitiator 调用失败
|
||
|
||
**检查**:
|
||
- 搜索 "Caught exception in safeLaunch"
|
||
- 查看异常类型和堆栈
|
||
|
||
---
|
||
|
||
## 📝 日志模板(复制给我)
|
||
|
||
抓取日志后,请提供以下信息:
|
||
|
||
```
|
||
### 1. 操作步骤
|
||
- [ ] 启动应用
|
||
- [ ] 点击"创建钱包"
|
||
- [ ] 输入钱包名称: ___
|
||
- [ ] 选择 2-of-3
|
||
- [ ] 输入参与者名称: ___
|
||
- [ ] 点击"创建"
|
||
- [ ] 【描述具体现象】: ___
|
||
|
||
### 2. 关键日志片段
|
||
|
||
#### 会话创建
|
||
```
|
||
[粘贴包含 "Creating new session" 的日志]
|
||
```
|
||
|
||
#### 会话状态
|
||
```
|
||
[粘贴包含 "Session status fetched" 的日志]
|
||
```
|
||
|
||
#### 事件触发
|
||
```
|
||
[粘贴包含 "Session started event" 的日志]
|
||
```
|
||
|
||
#### 异常(如果有)
|
||
```
|
||
[粘贴包含 "Caught exception" 的日志]
|
||
```
|
||
|
||
### 3. 完整日志文件
|
||
[附件: android_debug.log]
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 临时调试增强(如需更详细日志)
|
||
|
||
如果标准日志不够详细,可以临时添加更多日志:
|
||
|
||
### 在 MainViewModel.kt 的 safeLaunch 中:
|
||
|
||
```kotlin
|
||
private fun safeLaunch(
|
||
onError: ((Exception) -> Unit)? = null,
|
||
block: suspend CoroutineScope.() -> Unit
|
||
) = viewModelScope.launch {
|
||
try {
|
||
android.util.Log.d("MainViewModel", "safeLaunch: Starting block") // 添加这行
|
||
block()
|
||
android.util.Log.d("MainViewModel", "safeLaunch: Block completed successfully") // 添加这行
|
||
} catch (e: CancellationException) {
|
||
android.util.Log.d("MainViewModel", "safeLaunch: CancellationException caught") // 添加这行
|
||
throw e
|
||
} catch (e: Exception) {
|
||
android.util.Log.e("MainViewModel", "safeLaunch: Caught exception: ${e.javaClass.simpleName}", e)
|
||
// ... 现有代码 ...
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## ⚠️ 常见陷阱
|
||
|
||
### 1. 异常被吞掉但 UI 不显示错误
|
||
|
||
**症状**: 操作无反应,没有错误提示
|
||
|
||
**原因**: safeLaunch 更新了 _uiState.error 但 UI 没有订阅
|
||
|
||
**检查**: 搜索日志中的 "Caught exception",看是否有异常但 UI 没反应
|
||
|
||
### 2. Result.failure 未正确处理
|
||
|
||
**症状**: repository 返回 failure 但 ViewModel 没有处理
|
||
|
||
**检查**: 搜索 "onFailure" 和 "result.fold"
|
||
|
||
### 3. 协程被取消
|
||
|
||
**症状**: 操作执行到一半停止
|
||
|
||
**检查**: 搜索 "CancellationException"
|
||
|
||
---
|
||
|
||
## 📱 完整抓取命令(复制粘贴)
|
||
|
||
```bash
|
||
# 1. 清除旧日志
|
||
adb logcat -c
|
||
|
||
# 2. 开始记录(在另一个终端)
|
||
adb logcat -v time > ~/Desktop/android_debug_$(date +%Y%m%d_%H%M%S).log
|
||
|
||
# 3. 操作应用(重现问题)
|
||
|
||
# 4. 停止记录(Ctrl+C)
|
||
|
||
# 5. 发送日志文件给我
|
||
```
|
||
|
||
或者一步到位(操作完后手动停止):
|
||
```bash
|
||
adb logcat -c && adb logcat -v time | tee android_debug.log | grep --color -E "MainViewModel|TssRepository|GrpcClient|TssNativeBridge|Exception|Error"
|
||
```
|
||
|
||
---
|
||
|
||
**准备好后,请执行上述命令,重现创建2-of-3失败的问题,然后把日志发给我!**
|