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平台核心架构。你看一眼,基本就明白整体流程了。

APM平台核心架构 SDK采集层 FPS / 内存 / CPU / 线程 本地缓存层 内存缓存 → 磁盘分片 数据上报层 Gzip压缩 / 批量 / 触发 后端服务层 数据清洗 / 聚合 / 去重 / 存储 时序数据库 InfluxDB / TimescaleDB 关系型数据库 MySQL / PostgreSQL 实时告警引擎 可视化看板

五、一些实战经验

最后,分享几个我踩过的坑:

  • 数据采样率:别想着100%采集。对于大DAU的App,1%的采样率就足够发现问题了。全量采集,成本太高,收益有限。
  • 版本兼容:Android版本碎片化严重。有些API在低版本上不支持,一定要做好兼容。比如,获取CPU使用率,Android 8.0以上和以下,方法完全不同。
  • 隐私合规:采集用户数据,一定要符合GDPR和国内隐私法规。不要采集IMEI、MAC地址等敏感信息。用UUID代替设备ID。

注意:SDK的初始化,一定要放在Application的attachBaseContext里,而不是onCreate。因为有些性能问题,在onCreate之前就发生了。早一步初始化,就能早一步发现问题。

嗯,关于性能监控平台,我能想到的核心要点就这些。从SDK采集,到数据上报,再到告警和可视化,每一步都有细节。你如果正在搭建APM平台,建议先从最核心的FPS和内存监控开始,慢慢再扩展。别想一口吃成胖子。


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