36、性能监控平台:自定义性能监控SDK、数据上报策略、实时告警、APM平台搭建
性能监控这件事,说白了就是给App装个“黑匣子”。
我早年做项目时,最怕的就是线上出问题。用户反馈卡顿、闪退,但本地死活复现不了。那时候我就想,要是能有个东西,把App运行时的各种指标都记录下来,那该多好。后来,我们团队就自己动手,从零搭了一套APM平台。
今天我就把这里面的门道,跟你好好聊聊。
一、自定义性能监控SDK:从零开始搭积木
一个成熟的APM平台,核心在于SDK。它不能太胖,也不能太瘦。太胖了影响App性能,太瘦了数据不够用。
1.1 核心指标采集
我个人习惯,把监控指标分成三大类:
- 帧率(FPS):用Choreographer.FrameCallback来监听。注意,不要只算平均值,要关注掉帧的分布。比如,连续3帧超过16ms,就算一次“卡顿”。
- 内存(Memory):通过Runtime.getRuntime()获取Java堆内存,通过Debug.MemoryInfo获取Native内存。我建议每5秒采样一次,太频繁了反而耗电。
- CPU & 线程:读取/proc/stat和/proc/[pid]/stat。这里有个坑,不同厂商的Android系统,文件格式可能有细微差别。我曾经在某个定制ROM上,就因为解析格式不对,导致CPU数据全是0。
核心原则:采集逻辑必须轻量,不能在主线程做任何I/O操作。所有采集任务,都扔到子线程去。
1.2 数据聚合与缓存
采集到的原始数据,不能直接上报。你想想看,每秒几十条数据,网络压力太大了。
我一般会做两级缓存:
- 内存缓存:用LruCache或环形缓冲区,暂存最近1分钟的数据。
- 磁盘缓存:当内存满了,或者App进入后台,就把数据序列化到本地SQLite或文件里。
这里有个技巧:磁盘缓存用“分片”策略。比如,每5分钟生成一个文件,文件名带上时间戳。这样即使App崩溃,也能保证之前的数据不丢。
二、数据上报策略:别把服务器打崩了
数据怎么上报,是个大学问。我见过不少团队,一上来就实时上报,结果服务器直接被打趴下。
2.1 上报时机
我建议采用“懒上报”策略:
- 定时上报:每5分钟或10分钟,批量上报一次。
- 触发上报:当发生严重卡顿、ANR、OOM时,立即上报。这种数据最宝贵,不能等。
- 空闲上报:利用IdleHandler,在App空闲时偷偷上报。
2.2 数据压缩与去重
上报的数据,一定要压缩。我习惯用Gzip,压缩率能达到70%以上。
另外,重复数据要过滤。比如,连续两次采集的CPU使用率完全一样,那就只保留一条。这个逻辑虽然简单,但能省不少流量。
避坑指南:我曾经遇到过一个问题:上报的数据里,时间戳全是1970年。查了半天,发现是某个低端机型的系统时间没同步。所以,上报前一定要校验时间戳的合法性。
三、实时告警:别等用户骂了才修
告警不是越多越好。告警太多,运维人员会麻木,最后变成“狼来了”。
3.1 告警分级
我一般把告警分成三级:
| 级别 | 触发条件 | 通知方式 |
|---|---|---|
| P0(致命) | ANR率 > 1%,或Crash率 > 0.5% | 电话 + 短信 + 钉钉/飞书 |
| P1(严重) | FPS < 20持续10秒,或内存泄漏 | 钉钉/飞书 + 邮件 |
| P2(警告) | CPU使用率 > 80%持续1分钟 | 邮件 |
3.2 告警去抖
一个很常见的场景:某个用户网络差,导致数据上报延迟,触发了告警。但过了一分钟,数据又正常了。这种“抖动”告警,最烦人。
我的做法是:加一个“静默期”。比如,同一个告警规则,5分钟内只触发一次。这样能过滤掉90%的无效告警。
四、APM平台搭建:从数据到决策
APM平台的后端,我建议用“时序数据库”来存指标数据,比如InfluxDB或TimescaleDB。关系型数据库存元数据,比如App版本、设备信息。
4.1 数据可视化
前端展示,核心就三个字:快、准、全。
- 快:查询响应时间不能超过3秒。用预聚合+缓存来解决。
- 准:数据不能丢,不能错。用双写校验来保证。
- 全:支持按版本、按机型、按渠道、按时间维度下钻。
4.2 核心架构图
下面这张图,是我自己总结的APM平台核心架构。你看一眼,基本就明白整体流程了。
五、一些实战经验
最后,分享几个我踩过的坑:
- 数据采样率:别想着100%采集。对于大DAU的App,1%的采样率就足够发现问题了。全量采集,成本太高,收益有限。
- 版本兼容:Android版本碎片化严重。有些API在低版本上不支持,一定要做好兼容。比如,获取CPU使用率,Android 8.0以上和以下,方法完全不同。
- 隐私合规:采集用户数据,一定要符合GDPR和国内隐私法规。不要采集IMEI、MAC地址等敏感信息。用UUID代替设备ID。
注意:SDK的初始化,一定要放在Application的attachBaseContext里,而不是onCreate。因为有些性能问题,在onCreate之前就发生了。早一步初始化,就能早一步发现问题。
嗯,关于性能监控平台,我能想到的核心要点就这些。从SDK采集,到数据上报,再到告警和可视化,每一步都有细节。你如果正在搭建APM平台,建议先从最核心的FPS和内存监控开始,慢慢再扩展。别想一口吃成胖子。
公众号:蓝海资料掘金营,微信deep3321