在 iOS 开发里,实时日志几乎是每个工程师每天都会用到的东西。 但真正让人头疼的,往往不是"有没有打日志",而是当问题出现时:
- 日志是不是还在
- 日志是不是完整
- 日志能不能对应到当下的操作
- 日志是不是被别的噪声淹没了
很多线上或测试阶段的问题,其实并不复杂,但只要实时日志缺失或不连续,排查成本就会被无限放大。
实时日志的问题,通常不是没打印,而是看不到
有一次在做联调时,遇到一个看似简单的问题: 某个接口在部分设备上偶发失败,但重试又能成功。
开发第一反应是让测试把日志发过来,结果拿到的只有几行零散的 NSLog,前后上下文完全对不上。 当时才意识到一个问题:日志是有的,但没有全部读取到。
Xcode Console 的局限,很多人其实已经习惯了
大多数情况下,我们都是直接用 Xcode 的 Console 看实时日志:
- 连接设备
- Run
- 看 NSLog / os_log
在开发阶段,这确实够用。但一旦进入稍微复杂一点的场景,它的问题就会暴露出来:
- 日志量一大,很快被刷走
- 多进程(WebKit、Extension)日志混在一起
- 断开连接后日志就没了
- 无法很好地按 App、进程、关键字长期观察
当问题不是"立即复现"的时候,Xcode Console 往往就显得力不从心。
Console.app 能看到更多,但并不轻松
macOS 自带的 Console.app 能看到系统级日志,包括:
- App 日志
- WebKit 进程日志
- 系统警告
- sandbox / permission 相关信息
但它的使用体验并不友好:
- 日志量巨大
- 过滤条件复杂
- 不太适合持续盯着某一个 App
- 对非开发人员不友好
在一次需要长时间观察日志的测试中,我们试过用 Console.app,结果是: 信息很多,但真正有用的内容反而更难找。
实时日志,往往需要跟着运行走
后来在排查另一个问题时,我开始刻意调整思路: 不再把日志当成"事后分析材料",而是当成运行过程的一部分。
这时用到的是 克魔(KeyMob)。
最初并不是因为它"能看日志",而是因为它在真机环境下,可以把日志、性能、运行状态放在一个连续的时间线上。
用 KeyMob 看实时日志,关键不在"多",而在"连续"
在 KeyMob 里查看 iOS App 实时日志时,有几个细节让我印象比较深:
- 日志不会因为断开 Xcode 而消失
- 可以按 App、进程、关键字过滤
- 日志和当前操作几乎是同步的
- 在长时间运行时,日志依然是连续的
这在一些"慢性问题"上非常有用,比如:
- 某个操作偶发触发异常
- 后台切前台后逻辑不一致
- WebView 页面在某些时刻行为异常
这些问题,往往需要你盯着日志跑完整个操作流程,而不是只看某个时间点。
WebView 场景下,实时日志尤其容易断层
如果 App 里有 WebView、uni-app 或混合页面,实时日志的复杂度会明显上升。
这时,单靠 Native 日志是不够的。
我一般会同时使用:
- Safari Inspector:看 JS console、前端报错
- KeyMob:看 App 侧实时日志、系统日志
在一次白屏问题排查中,就是通过对比这两边的日志时间点,才发现:
- Native 侧并没有明显异常
- WebView 进程在某个时刻被系统重启
- 重启前有连续的内存和日志警告
如果没有连续的实时日志,很难把这些线索串起来。
网络相关问题,实时日志也很关键
还有一类问题,看起来是"接口失败",但本质并不只是网络。
在某次弱网测试中,我们发现:
- 接口请求确实发出去了
- 服务端返回也正常
- 但 App 偶发解析失败
通过 Charles 抓包,只能确认网络层没问题。 真正的线索,反而出现在实时日志里:
- 某次解析异常前,日志里已经出现警告
- 同一时间 CPU 有短暂峰值
- 后续逻辑走了异常分支
如果只是事后看零散日志,这些细节很容易被忽略。
实时日志不是"单独使用"的工具
在现在的工程实践中,我基本不会单独谈"怎么看实时日志",而是把它放进一个组合里:
- Xcode Console:开发调试、快速验证
- KeyMob:真机实时日志、长期观察
- Console.app:系统级异常补充
- Safari Inspector:Web 相关日志
- Charles:网络行为对照
实时日志的价值,往往体现在和别的信号一起看的时候。
其实看这些经历,会发现很多问题并不是"没有日志",而是:
- 日志没被连续记录
- 日志和操作脱节
- 日志和系统行为没有放在一起看
当实时日志真正和运行过程同步的时候,很多原本模糊的问题,其实就会自己出来。