27、Logcat 在 CI/CD 中的应用:自动化日志收集与问题预警

说实话,很多团队做 CI/CD,跑完自动化测试就算完事了。日志呢?要么没人看,要么等用户反馈了才去翻。这其实挺可惜的。我个人习惯是把 Logcat 当成一个「哨兵」,让它自动盯着流水线里的每一个构建和测试环节。

今天我们就聊聊,怎么把 Logcat 塞进 CI/CD 流程里,让它自动收集日志,还能在出问题的时候提前报警。

为什么要在 CI/CD 里用 Logcat?

你想想看,本地开发的时候,Logcat 就在 Android Studio 底下滚着,出问题一眼就能看到。但到了 CI 环境,没有屏幕,没有鼠标,Logcat 默认是关掉的。很多隐蔽的运行时异常、ANR 前兆、内存泄漏的蛛丝马迹,就这么被忽略了。

我在项目中遇到过好几次:本地测试全绿,CI 也全绿,结果灰度一上,用户疯狂崩溃。后来一查,是某个低端机在 CI 上跑的时候 Logcat 里早就打印了 OutOfMemoryError 的堆栈,但没人去看。从那以后,我就把「自动收集 Logcat」写进了每个项目的 CI 脚本里。

自动化收集:从命令行开始

CI 环境里没有 Android Studio,但我们有 adb logcat。核心思路很简单:在测试执行的同时,启动一个后台进程抓取日志,测试结束后保存成文件。

下面是我常用的一个脚本片段,放在 Jenkins 或 GitLab CI 的 before_script 里:

#!/bin/bash
# 启动 logcat 后台抓取
adb logcat -v threadtime -b all > build_${BUILD_NUMBER}.log &
LOGCAT_PID=$!
echo "Logcat PID: $LOGCAT_PID"

# 运行测试(示例)
./gradlew connectedDebugAndroidTest

# 测试结束后,等待 2 秒确保日志刷完
sleep 2
kill $LOGCAT_PID
echo "日志已保存到 build_${BUILD_NUMBER}.log"
小提示: 我建议加上 -b all 参数,把 main、system、events、crash 四个缓冲区都抓下来。有些 ANR 信息只在 events 缓冲区里出现,只抓 main 会漏掉关键线索。

问题预警:从日志里挖出「地雷」

光收集还不够,得让机器帮我们看。说白了,就是在日志里搜索那些「不该出现」的关键词。

我总结了一个高频预警关键词表,你可以直接拿来用:

关键词 含义 预警级别
FATAL EXCEPTION 未捕获的崩溃 严重
ANR in 应用无响应 严重
OutOfMemoryError 内存溢出 严重
NullPointerException 空指针异常
ClassNotFoundException 类找不到(常见于混淆问题)
Could not read input channel 输入通道异常(可能卡顿)
BufferOverflowException 缓冲区溢出

在 CI 脚本里,我们可以用 grep 配合退出码来做预警:

#!/bin/bash
LOG_FILE="build_${BUILD_NUMBER}.log"

# 检查严重错误
if grep -q "FATAL EXCEPTION\|ANR in\|OutOfMemoryError" "$LOG_FILE"; then
  echo "❌ 检测到严重错误!请立即查看日志。"
  # 这里可以触发钉钉/飞书/邮件通知
  exit 1
fi

# 检查高优先级警告
if grep -q "NullPointerException\|ClassNotFoundException" "$LOG_FILE"; then
  echo "⚠️ 发现高优先级异常,建议人工审查。"
  # 可以标记构建为 unstable,但不阻断
fi

echo "✅ 日志检查通过,未发现严重问题。"
注意: 不要把所有 Exception 都当成错误。有些第三方库会在 Logcat 里打印自己的异常堆栈,但实际上已经内部处理了。我曾经因为没做白名单过滤,导致 CI 天天误报,团队都麻木了。建议先跑一个基线版本,把「已知无害」的异常加进忽略列表。

知识体系:Logcat 在 CI/CD 中的完整链路

下面这张图,是我自己画的一个流程框架。它把日志收集、解析、预警、归档串在了一起。你可以直接照着这个结构去搭建你的 CI 流水线。

Logcat 在 CI/CD 中的自动化链路 CI 构建 / 测试触发 后台启动 adb logcat -b all 抓取 自动化测试运行 保存日志文件 + 停止抓取 grep 关键词预警 归档到 CI 产物 触发报警通知 并行 并行 并行

实战中的几个坑

嗯,这里我要多说几句。自动化日志收集看着简单,但实际落地的时候,有几个地方特别容易翻车。

  • 日志文件太大:一个完整的 UI 自动化测试跑下来,Logcat 可能生成几百 MB 的文本。我建议在抓取时加上 -G 20M 限制缓冲区大小,或者用 grep 实时过滤,只保留 Warning 及以上级别的日志。
  • adb 连接不稳定:CI 机器上如果同时跑多个模拟器,adb 可能会掉线。我习惯在脚本里加一个重试逻辑:如果 adb logcat 命令失败,等 3 秒再试一次。
  • 时间戳对齐:Logcat 的时间戳是设备本地时间,CI 服务器可能是 UTC。如果你需要把日志和测试用例的执行时间对应起来,建议在测试开始和结束时各打一条标记日志,比如 Log.d("CI_MARKER", "TEST_START")
核心思路总结: 把 Logcat 当成 CI 流水线里的一个「传感器」。它不贵(几乎零成本),但能帮你捕捉到那些测试用例覆盖不到的运行时异常。说白了,就是让机器替你做 24 小时不间断的日志巡检。

我个人觉得,这套方案最大的价值不是「收集」,而是「预警」。当你的 CI 脚本能在凌晨三点自动发出一条「检测到 ANR 趋势上升」的消息时,你就知道,之前花在搭建上的时间,全都值回来了。

公众号:蓝海资料掘金营,微信deep3321