高性能终端实时日志收集系统
背景
在移动端的日常运营中,经常会遇到用户反馈APP出现功能性问题的情况,以往需要通过一系列询问,诸如手机型号、操作系统版本、复现的场景等信息,这一繁琐的过程不仅费时,还容易产生信息不完整或错误的问题,在尝试复现问题时也可能遇到困难,这种“盲目”排查问题的方式导致了问题解决的周期较长,也增加了沟通和理解的成本
项目目标与特点
项目目标
开发一个能提高问题解决效率的日志收集系统,包括服务端、管理端和AndroidSDK
主要特点
较高的可靠性:
日志写入缓冲区后会立即回写到磁盘并记录位置,即使APP出现Crash或被强制关闭也不会丢失数据(会影响一些性能,也可手动切换为轮询方式定时将数据回写到磁盘,但在回写之前出现Crash等情况会丢失数据)实时日志上报:
实时日志用于记录精简的日志数据,通过短轮询方式上传到后台,以便能查看到接近实时的日志,快速定位问题离线日志回捞:
较为详细的日志数据应记录到离线日志中,后台下发回捞任务后,ZLogAndroidSDK会把该任务日期区间的日志文件打包上传到后台,由后台解析完日志文件后,再去排查和定位问题加密存储和传输:
存储到本地文件、上报实时日志时数据将被压缩并加密,只有服务端和产生日志的设备能够解密日志数据
集成ZLogAndroidSDK
添加依赖
1 | implementation 'com.github.zangjy:XBase:版本号见Github' |
MMKV对armv7和x86架构的支持
ZLogAndroidSDK使用了MMKV对写入位置进行记录,在v1.3.5版本中MMKV放弃了对armv7和x86架构的支持,在不受支持的架构中使用,你需要
将SO库放到对应文件夹下
在工程根目录的build.gradle
中添加如下
1 | allprojects { |
或者在settings.gradle
中添加如下
1 | dependencyResolutionManagement { |
在程序入口初始化
写实时日志
1 | ZLog.writeOnlineLog(Log.Level.INFO, "写实时日志") |
写离线日志
1 | ZLog.writeOfflineLog(Log.Level.INFO, "写离线日志") |
ZLogAndroidSDK实现方案
在初始化之后,ZLogAndroidSDK使用mmap映射一块磁盘空间作为缓冲区,写日志时使用Protobuf将日志序列化成二进制数据、然后对数据进行压缩和加密后写入缓冲区,在缓冲区写满或需要打包日志文件时使用标准I/O将缓冲区数据追加到日志文件中
存储方式
每条数据使用8个字节来标记数据头,读取并解析数据时可以跳过损坏的数据,不会影响后面数据的读取和解析
加密方式
ZLog使用了ECDH + AES CFB-128对每条数据进行加密
客户端在本地使用ECDH生成一个密钥对
和服务端进行公钥交换
客户端使用自己的私钥和服务端的公钥计算获得加解密密钥,服务端也使用自己的私钥和客户端的公钥计算获得相同的加解密密钥
客户端使用计算的加解密密钥对一段文本进行加密后发送给服务端
服务端接收并尝试解密客户端发送的密文,然后将结果发送给客户端
客户端将原始文本和服务端解密后的文本进行比对,如果一致,则密钥协商和验证操作完成
性能
测试设备 | 40字节10w次写入耗时 |
---|---|
HUAWEI HONOR Play3 | 4252ms |
Redmi K40 Pro | 1810ms |
XIAOMI 12S Ultra | 1504ms |
VIVO iQOO 12 | 1033ms |
VIVO X100 Pro | 3600ms |
OPPO Reno11 Pro | 1631ms |
OPPO A1 Pro | 2920ms |
服务端部署
需要根据操作系统选择对应二进制文件
下载
点此下载
提取密码:ate1
配置
下载完成后进入conf
文件夹修改conf.ini
文件
启动
回到根目录,运行main
程序
管理端部署
需要根据操作系统选择对应二进制文件
下载
点此下载
提取密码:51rt
配置
下载完成后修改
conf.ini
文件进入
static\assets
目录,修改Api.8f856717.js
文件,将http://127.0.0.1:8888/api/v1
替换成服务端的地址,按照示例的配置需要改为http://127.0.0.1:20000/api/v1
第一步配置的是访问Web端的端口,第二步配置的是Web端连接服务端查询数据的端口
启动
回到根目录,运行main
程序,按照示例的配置,浏览器访问http://127.0.0.1:80
即可打开Web管理端
APP管理
实时日志
回捞任务
注意事项
- 线上服务端及Web端必须配置SSL,否则Web端无法使用!!
- 如果使用Nginx,则必须进行以下配置
在
http
块里增加underscores_in_headers on;
属性,允许Header中存在下划线的项
在
server
块的location
配置中增加proxy_set_header Request-Headers $http_all;
属性,转发所有请求头