Glog 是货拉拉移动端监控体系中的日志存储组件,Glog 意即 General log – 通用日志。为了满意咱们对日志格局的多种需求,咱们在存储方法、归档方法上做了一些探索和实践,使得 Glog 的通用性和功能优于常见的日志计划。Glog 现已在货拉拉全线 App 中安稳运行了 1 年多,现在将其开源,咱们期望 Glog 的开源可以为移动开发者供给一种更加通用的日志计划,同时期望 Glog 可以从社区中汲取营养,不断得到优化和完善。GitHub 地址:https://github.com/huolalatech/hll-wp-glog
布景简介
移动端日志体系一般来说,首要的目标是辅佐开发同学排查线上问题,这些问题包含但不限于
- 客诉渠道反应的 App 运用问题;
- Crash 体系上报的崩溃问题;
- 其他线上冒烟问题。
为了可以赶快定位问题,咱们期望可以快速、详细的复原问题现场,这就需求在代码中 App 运行的关键节点埋入日志,将呈现问题时的运行状态快速上报。这对日志体系提出了两个关键的要求,信息完好性以及实时性。 在移动端,公司之前存在一套简略的日志体系,搜集的日志信息比较有限,咱们经过 App 的常见运用流程来看其覆盖的关键节点
另外,之前的日志体系只能经过下发使命回捞,实时性较差,还存在 I/O 功能等问题。
为了解决这些问题,咱们开发了新的移动端日志体系,覆盖了上面 App 运用流程的全节点信息
另一方面,为了提高日志的实时性,咱们增加了实时日志,经过短轮询来进行定时上报,此外还补充了监控日志来支撑 App 的横向数据比照、评价 App 的功能指标,终究的计划如下
体系首要组成包含
- Android/iOS 上层日志收集 SDK
- 跨渠道的储存组件 Glog
- 担任日志存储过滤的日志后端
- 担任日志展现的日志前端
新的监控体系包含实时性要求较高的实时日志,信息较完好的离线日志以及为大盘数据服务的监控日志
- 实时日志,快速上传,信息精简,可以接近实时的查看,快速定位、排查用户反应的问题;
- 离线日志,经过后台使命触发上传,按天归档,作为实时日志的兜底,要求信息完好详尽;
- 监控日志,支撑采样,作为监控大盘的信息源,实时性要求最高,日志只包含监控信息。
为了适配不同日志的存储格局,咱们期望存储组件可以在格局上尽量通用,最好做到格局无关;另一方面咱们也期望其功能、牢靠和安全方面可以对齐一线水平,在调研了市面上盛行的日志组件后,咱们发现并没有现成计划满意咱们的需求,因而咱们自研了自己的日志存储组件 Glog。
计划概览
运用上层对不同类型的日志序列化(推荐 Protobuf)之后,将二进制数据存储到 Glog,关于上传频次较高的实时日志和监控日志,选用重命名缓存的方法快速归档;关于信息较全而上传频次不高的离线日志,咱们选用 mmap 偏移映射的方法归档,相较规范 I/O 仿制归档的方法,提高了功能。在牢靠性和安全性方面咱们也学习了当时的盛行计划,例如 mmap I/O 提高功能和牢靠性、流式的加密和紧缩避免 CPU 突发峰值,另外咱们在日志中参加了同步符号支撑读取容错。
存储方法
为了适应不同的日志格局,Glog 存储二进制数据,上层根据自己的需求,将数据序列化后交给 Glog
详细的文件格局:运用 2 个字节描绘每条日志长度,在每条日志结尾参加一个同步标志,用于文件损坏时的读取容错。
归档方法
回忆一下常见的日志组件中 mmap 的运用方法,首要 mmap I/O 需求映射一片巨细为 page size (一般为 4KB) 整数倍巨细的缓存,跟着数据的写入将这片空间耗尽后,咱们无法继续扩展这片空间的巨细(因为它占用的是 App 的运行内存空间),因而需求将其间的数据归档,常见的方法是将其间内容 flush 追加到另一个归档文件当中,之后再清空 mmap 缓存,这个 flush 的进程一般运用规范 I/O
而咱们的实时、监控日志为了快速上传确保数据实时性,选用距离较短的轮询来触发 flush 并上传,这将导致 flush 频率变得很高;而一般的 flush 方法选用规范 I/O 来仿制数据,功能相对较低,后续的日志写入需求等待 flush 完结,这将影响咱们的写入功能,因而咱们考虑两种计划来提高 flush 速度以优化写入功能
- mmap 偏移映射,经过 mmap 映射归档文件的结尾,之后经过内存仿制将 mmap 缓存追加到归档文件结尾。这种方法将文件仿制变成内存仿制,功能较好。
- 文件重命名,关于可以快速上传并删去的日志,咱们可以在需求时将 mmap 缓存重命名成归档文件,之后重建缓存。这种方法直接去除了仿制的环节,但是在日志量较大时,或许产生很多琐细的归档文件。
这两种计划可以在咱们的不同日志场景运用,关于实时、监控日志来说,对功能要求最高,选用第 2 种计划,这个计划带来的琐细归档文件问题,因为上传和删去较快,在这里并不会堆积,另一方面,考虑到实时、监控日志上传周期较短,琐细的归档文件也便于操控上传的数据量;而离线日志选用第 1 种计划,可以将每天的日志归档在一个文件中,相对常见的规范 I/O 也有功能上的优势。
加密方法
Glog 运用了 ECDH + AES CFB-128,对每条日志进行单独加密。详细来说经过 ECDH 洽谈加密秘钥,之后 AES CFB-128 进行对称加密。
选择 CFB-128 是因为 AES 通用性和安全性较好,加解密只需执行相同块加密算法,对 IV 随机性要求低,ECC 相对 RSA 在加密强度相同的前提下,秘钥更短。
Security(In Bits) | RSA Key Length Required(In Bits) | ECC Key Length Required(In Bits) |
---|---|---|
80 | 1024 | 160-223 |
112 | 2048 | 224-255 |
128 | 3072 | 256-383 |
192 | 7680 | 384-511 |
256 | 15360 | 512+ |
紧缩方法
考虑到解紧缩的快捷性和通用性,Glog 运用了常见的 Deflate 无损紧缩算法,对日志进行流式紧缩,即以每条日志为紧缩单元,在每次写入时进行同步紧缩。这样避免了归档时对整个 mmap 缓存做紧缩带来的 CPU 波峰,详细的原理下面做一些解说。
Deflate 算法是 LZ77 与哈夫曼编码的组合
LZ77
LZ77 将数据(短语)经过前向缓冲区,然后移动到滑动窗口中成为字典的一部分,之后从字典中查找能与前向缓冲区匹配的最长短语,假如可以射中,则成为短语符号作为成果保存起来,不能射中则作为字符符号保存。 解压时,假如是字符符号则直接仿制到滑动窗口中,假如是短语符号则在滑动窗口中查找相应的偏移量,之后将滑动窗口中相应长度的短语仿制到成果中。
短语符号包含了
- 滑动窗口中的偏移量
- 匹配射中的字符长度
- 匹配完毕后前向缓冲区的第一个字符
下面展现了对字符 LABLALALABLA 进行 LZ77 紧缩和解紧缩的进程,
接下来霍夫曼编码对 LZ77 的处理成果(包含前面说到的偏移量、长度、字符),依照呈现频率越高,占用空间越少的方法进行编码存储。 在扼要阐明原理之后,咱们知道影响紧缩率的几个因素:滑动窗口(字典)巨细,输入的数据(短语)长度、以及短语中字符的重复率。字典越大、短语越长,越容易从字典中找到匹配短语从而变成短语符号,那么流式紧缩以每条日志作为紧缩单元,输入数据长度变短,咱们怎么确保紧缩率呢? 这里咱们能做的是尽量确保字典的巨细,不频频重置字典,详细做法是只在 mmap 缓存归档时重置字典,关于归档前 mmap 缓存的数据,复用字典来确保紧缩率。
音讯行列
mmap 相对规范 I/O 在功能上有较大优势,首要是因为其减少了内核空间与用户空间的仿制、以及 write lseek 体系调用带来的上下文切换开支
但在体系资源不足时 mmap 仍有或许呈现功能问题,举个例子,咱们知道 mmap 与规范 I/O 相同也需求经过 Page Cache 回写到磁盘
Page Cache 的生命周期: 当用户经过规范 I/O 从用户缓冲区向内核空间仿制数据时,假如内核缓冲区中没有这个 Page,将发生缺页中止分配一个 Page,之后仿制数据,完毕后这个 Page Cache 变成一个脏页,然后该脏页同步到磁盘中,同步完毕后,这个 Page Cache 变成 Clean Page 保存在体系中。
Android 中可以经过 showmap
指令调查 mmap 写入了 Page Cache
当体系内存不足时,体系将收回 Page Cache 来开释内存,引起频频的磁盘回写,mmap 功能也会受到影响。 另一方面因为实时日志、监控日志需求高频归档,而归档会堵塞后续的写入。因而咱们在 Glog 底层参加了音讯行列来处理写入和归档等操作,进一步提高功能,避免卡顿。
功能比照
手机类型 | 日志 SDK | 1w 条日志耗时 | 10w 条日志耗时 |
---|---|---|---|
Samsung Galaxy S10+ Android 11 | glog | 21 ms | 182 ms |
glog+pb | 54 ms | 335 ms | |
xlog | 207 ms | 1961 ms | |
logan | 250 ms | 6469 ms | |
Huawei Honor Magic 2 Android 10 | glog | 38 ms | 286 ms |
glog+pb | 84 ms | 505 ms | |
xlog | 263 ms | 2165 ms | |
logan | 242 ms | 3643 ms | |
Xiaomi 10 Android 11 | glog | 27 ms | 244 ms |
xlog | 198 ms | 1863 ms | |
logan | 210 ms | 4238 ms | |
Huawei Mate 40 pro HarmonyOS 2.0.0 | glog | 30 ms | 257 ms |
xlog | 275 ms | 2484 ms | |
logan | 260 ms | 4020 ms | |
OPPO R11 Android 8.1.0 | glog | 63 ms | 324 ms |
glog+pb | 234 ms | 1611 ms | |
xlog | 464 ms | 3625 ms | |
logan | 430 ms | 5355 ms | |
iPhone 12 128G iOS 14.8 | glog | 7 ms | 29 ms |
xlog | 152 ms | 1079 ms | |
logan | 162 ms | 12821 ms | |
iPhone 8 64G iOS 13.7 | glog | 12 ms | 50 ms |
xlog | 242 ms | 2106 ms | |
logan | 251 ms | 38312 ms |
Glog 运用异步形式、按天归档
经过比照数据来看,Glog 异步形式因为运用了音讯行列,即便累加上 Protobuf 的序列化时间,写入功能相对来说依然有较大优势。
遇到的问题
- 运用 mmap 偏移映射方法仿制数据时,需求经过 mmap 映射文件结尾,其偏移量也需求是 page size 的整数倍,而归档文件和仿制数据巨细一般情况下都不是 page size 的整数倍,需求做额定的计算;
- 假如只对归档文件总体积作为阈值来清理,在重命名归档这种情况下琐细文件较多,或许在搜集文件列表的进程中导致 JNI 本地引用超限,需求约束文件总个数、及时收回 JNI 本地引用;
- 在跨天写入日志的情况下,mmap 缓存中的数据或许无法及时归档,形成部分日志误写入次日的归档文件当中,需求在归档轮询中增加时间窗口的判定;
- 为了便于上层上传日志,在底层需求增加日志解析模块。
总结
经过上面的介绍,可以看到 Glog 相较其他盛行计划的首要区别是:
- 存储的是格局无关的二进制数据,具有更好的定制性;
- 底层完成的音讯行列,功能更优运用也更方便;
- 新的归档方法一方面提高功能,另一方面也便于高频读取。
当然这些手段也带来了一些妥协,比方因为存储的是二进制数据,运用 Glog 需求额定增加序列化代码;异步形式下,音讯行列中的使命在 Crash 或断电时或许丢失,这些问题在咱们的运用场景根本可以疏忽。 为了完成货拉拉的事务需求,咱们参考盛行的日志计划,站在伟人的膀子上,在移动端存储组件高功能、牢靠、安全的根本要求之外,供给了更多的特性和额定的优化。在开源之后,也期望可以反哺社区,为移动开发者供给一种更为通用的日志计划。
以 Glog 为存储模块的日志体系,现在现已接入了公司的全线 app,实时日志的单日日志量达到数十亿条,安稳运行在百万等级的 App 上。为线上用户反应问题解决、App 崩溃排查供给了有力的帮助,除此之外,还为风控体系、监控大盘供给了数据支撑。