日志采集准备:四大工具链配置与选型
ANR 问题排查的起点是完整、准确的现场数据。不同工具采集的数据维度不同,采集窗口稍纵即逝。本章聚焦四种核心日志工具的配置方法与选型策略,确保你在下次 ANR 出现时能一次性拿到足够的信息,避免反复复现。
核心原则:先采集、后分析;多工具互补,单工具不追责。adb logcat 记录应用层事件,ANR trace 冻结系统线程状态,systrace / perfetto 追踪时间片与调度过程。四者组合才能还原完整的 ANR 成因链。
现象识别:哪些信号表明需要采集日志?
ANR 发生时系统会产生明确的日志写入行为。识别以下现象即可触发自动化采集流程:
- Logcat 出现 "ANR in" 关键字 —— 应用主线程超时,系统弹出 ANR 对话框。
- 系统生成
/data/anr/traces.txt—— 内核 dump 所有线程堆栈到该文件。 - Event log 输出
am_anr事件 —— 记录 ANR 发生时间、进程名、CPU 负载。 - 用户反馈界面卡死 > 5 秒 —— 即使 logcat 未及时打印,也应主动拉取 trace 和 perfetto 缓冲区。
| 现象 | 日志来源 | 采集优先级 |
|---|---|---|
| logcat 出现 "ANR in" | adb logcat | 最高,立即保存 |
| /data/anr/traces.txt 更新 | ANR trace 文件 | 最高,第一时间 pull |
| am_anr 事件出现 | logcat -b events | 高,辅助确认时间点 |
| UI 线程卡顿无响应 | systrace / perfetto | 中,需提前配置守护采集 |
数据采集:四种工具配置详解
1. adb logcat —— 应用层日志即时采集
最直接的日志通道,用于记录 ANR 发生前后的应用行为、系统广播、Service 超时信息。
# 清空缓冲区并持续输出,按标签过滤
adb logcat -c
adb logcat -s ActivityManager:I WindowManager:I *:S -v threadtime > anr_app.log
# 同时捕获 main、system、events 三个缓冲区
adb logcat -b main -b system -b events -v threadtime | tee anr_full.log
# ANR 发生后立即 dump 历史缓冲区(无等待)
adb logcat -d -b main -b system -b events | grep -E "ANR|am_anr|CPU"
避坑:线上环境建议在应用启动时通过
ProcessBuilder 启动独立进程持续采集 circular buffer(大小 2 MB),避免 ANR 发生时 logcat 缓冲区已被滚动覆盖。
2. 系统 ANR trace 文件 —— 线程堆栈的冻结快照
ANR 发生时系统自动 dump 所有线程堆栈到 /data/anr/traces.txt(Android 10+ 可能分片为 traces_*)。这是定位阻塞线程最直接的数据源。
# 拉取 trace 文件(需要 root 或 debuggable 应用)
adb root
adb wait-for-device
adb pull /data/anr/traces.txt ./anr_traces_$(date +%Y%m%d_%H%M%S).txt
# 若设备无 root,使用 run-as 抓取本应用堆栈
adb shell run-as com.your.package cat /data/anr/traces.txt > app_trace.txt
| 字段 | 含义 | 关注点 |
|---|---|---|
| "main" prio=5 tid=1 | 主线程标识 | tid=1 表示主线程,观察其状态:RUNNABLE / BLOCKED / WAITING |
| at com.xxx.xxx.method | 当前执行栈帧 | 最上层为阻塞点,检查锁对象、IPC 调用 |
| Locked ownable synchronizers | 持有的锁 | 与其它线程的锁等待形成死锁链 |
| CPU usage | 进程 CPU 占用 | 过高表示计算密集,过低表示等待 I/O 或锁 |
3. systrace —— 轻量级 UI / 调度追踪
systrace 基于 ftrace,适合追踪 UI 渲染、View 绘制、消息分发等短时间(5~10 秒)场景。Android 10 以下默认使用,以上推荐迁移至 perfetto。
# 通过 Python 脚本启动(需 Android SDK tools 目录)
python systrace.py -t 8 -o anr_trace.html \
--categories=view,am,rs,hal,app,sched,freq
# 使用 atrace 命令直接输出
adb shell atrace --async_start -c -b 4096 view am app sched
# ... 复现 ANR 操作 ...
adb shell atrace --async_dump > anr_systrace.txt
adb shell atrace --async_stop
适用场景:UI 线程卡顿、布局过度绘制、Binder 调用超时。输出为 HTML,可在 Chrome 中可视化分析。单次采集时长建议 ≤ 10 秒,否则缓冲区溢出。
4. perfetto —— 下一代全平台追踪方案
Perfetto 是 Android 11+ 的官方追踪引擎,支持更长的采集窗口、更丰富的数据源(CPU、GPU、内存、I/O、调度器)。通过 protobuf 配置灵活控制探针。
# 1. 创建采集配置 config.pbtx
duration_ms: 30000
buffers: {
size_kb: 65536
fill_policy: RING_BUFFER
}
data_sources: {
config {
name: "android.logcat"
target_buffer: 0
android_logcat_config {
log_ids: LOG_ID_MAIN
log_ids: LOG_ID_SYSTEM
log_ids: LOG_ID_EVENTS
}
}
}
data_sources: {
config {
name: "linux.ftrace"
ftrace_config {
ftrace_events: "sched/sched_switch"
ftrace_events: "power/cpu_frequency"
ftrace_events: "binder/*"
}
}
}
# 2. 推送配置并启动采集
adb push config.pbtx /data/local/tmp/
adb shell perfetto -c /data/local/tmp/config.pbtx \
-o /data/local/tmp/trace.perfetto-trace --txt
# 3. 复现 ANR 后停止并拉取
adb pull /data/local/tmp/trace.perfetto-trace ./anr_perfetto.pb
| 维度 | systrace | perfetto |
|---|---|---|
| 数据源丰富度 | 仅 ftrace 事件 | ftrace + logcat + heap + 自定义探针 |
| 最大采集时长 | ~10 秒 | ~60 秒(环形缓冲区可更长) |
| 配置灵活性 | 命令行参数固定 | protobuf 灵活编排 |
| 可视化方式 | Chrome trace viewer | ui.perfetto.dev 或 Chrome |
| 推荐场景 | 快速验证 UI 问题 | 深度 ANR / 性能回归分析 |
原因定位:工具选型决策树
面对一次 ANR,不应盲目启动所有工具。根据已有线索选择最小采集集合,既能降低性能开销,又能提高数据信噪比。下图展示了从 ANR 问题到具体工具的选型路径:
判断规则:若 trace 中主线程状态为
BLOCKED 且持有锁,优先分析锁竞争链,此时 perfetto 的 lock_contention 事件能精确显示等待时长;若主线程为 RUNNABLE 且持续执行 CPU 密集型操作,systrace 的 CPU slice 视图可快速定位热点函数。
修复动作:常见配置问题与解决
| 问题现象 | 根因 | 解决方案 |
|---|---|---|
| logcat 缓冲区被覆盖,ANR 日志丢失 | 默认缓冲区仅 64 KB | 使用 adb logcat -G 2M 扩大缓冲区,或在应用内实现环形日志文件 |
| pull /data/anr/traces.txt 权限拒绝 | 非 root 设备,应用不可调试 | 在 AndroidManifest 中设置 android:debuggable="true",或使用 run-as 抓取本应用堆栈 |
| systrace 采集时提示 "no atrace" | 设备 Android 版本过低或系统镜像裁剪 | 改用 adb shell perfetto 命令,或升级设备至 Android 11+ |
| perfetto 配置不生效,无数据输出 | protobuf 字段遗漏或缓冲区大小不足 | 在 ui.perfetto.dev 上使用可视化配置器导出 config,验证 buffers.size_kb ≥ 32768 |
复测:验证采集配置有效性
完成工具配置后,执行以下验证脚本确保每一条采集链路畅通:
# 验证 logcat 环形缓冲区已扩大
adb logcat -g | grep -E "ring buffer"
# 验证 trace 文件可正常拉取(不依赖 ANR 触发)
adb shell "echo 'test' > /data/anr/traces.txt" 2>/dev/null && echo "trace 写入权限 OK"
# 验证 systrace 能启动并输出 HTML
python systrace.py -t 2 -o /dev/null --categories=view,sched
# 验证 perfetto 采集端到端
adb shell perfetto -c - --txt -o /data/local/tmp/verify.pb <<EOF
duration_ms: 3000
buffers: { size_kb: 1024 }
data_sources: { config { name: "linux.ftrace" } }
EOF
adb pull /data/local/tmp/verify.pb /dev/null && echo "perfetto 采集 OK"
复测通过标准:四条命令全部返回 OK 或非空输出。任何一条失败都表示对应工具在目标设备上不可用,需回退到替代方案或修复权限配置。
预防:标准化采集规范
- 建立采集 checklist:每次 ANR 事件触发后,按 "logcat → trace → perfetto" 顺序自动执行采集脚本,避免人工遗漏。
- 统一配置模板:将 perfetto config 和 systrace 参数写入项目版本库,随应用版本迭代同步更新探针集合。
- 预置守护进程:在应用启动时启动一个低优先级服务,循环记录 logcat events 和 CPU 负载,ANR 发生时保留最后 30 秒数据。
- 定期演练:每周在 CI 中触发一次模拟 ANR(通过主线程 sleep 10 秒),验证采集链路完整性。