谭倚靖 谭智文 张亮 韦通明 苏万德
【摘 要】本文研究一种Android客户端日志采集系统的整体解决方案,实现终端日志的“全量滚动缓存+动态配置上报”,保证日志信息的完整存储,并减少无用日志上报。
【关键词】日志系统;客户端;Android系统;日志采集
中图分类号:U463.6 文献标志码:A 文章编号:1003-8639( 2023 )08-0040-03
Research on Log Collection System of Android Client
TAN Yi-jing,TAN Zhi-wen,ZHANG Liang,WEI Tong-ming,SU Wan-de
(SAIC GM Wuling Automobile Co.,Ltd.,Guangxi Laboratory of New Energy Automobile,
Guangxi Key Laboratory of Automobile Four New Features,Liuzhou 545007,China)
【Abstract】This paper studies an overall solution of Android client log collection system to achieve the“full rolling cache+dynamic configuration reporting”of terminal logs,ensure the complete storage of log information,and reduce the reporting of useless logs.
【Key words】log system;client;Android system;log collection
日志是操作系统或应用程序在运行时的事件记录,为开发人员提供程序运行过程中的状态变化信息,用于处理和观察分析系统或程序的运行是否符合预期的结果。
1 客户端系统的多样性问题
服务端的日志系统较为成熟,目前主流的日志系统使用ELK作为日志的分布式存储,使用skywalking作为微服务架构中的分布式链路解决方案,使得开发者能够便捷地收集和查询日志,协助处理系统问题。而客户端与服务端不同,相较于服务端稳定的网络架构,客户端需要面对更多的多样性问题。
1)客户端平台的多样性。云平台上的服务器、每个人手里的手机以及物联网设备等终端都可以作为客户端,不同的客户端通常使用不同的操作系统,这就要求客户端的日志系统需要在多平台实现,或者具备跨平台的能力。
2)客户端场景的多样性。客户端为用户所有,用户在客户端进行业务交互时,其是否同意采集并上传日志、产品应用是否希望用户感知到日志的采集与回传操作、流量的消耗是否合理……这些问题都需要基于具体的应用场景来设计,场景需求的多样性则要求客户端日志系统需要具备较高的可配置能力,同时,日志采集需要尽量低消耗与无感知。
3)客户端网络环境的多样性。互联网有多种接入方式,常见的有:WIFI接入、移动蜂窝网络接入、有线宽带接入、USB桥接网络接入……多种网络可能随时切换,也随时可能出现网络不稳定、短时离网等异常情况。为保证日志数据不因为网络问题而丢失,要求客户端的日志系统需要具备数据缓存、数据压缩、断点续传、超时重连等机制,以保证日志系统在复杂网络条件下能够正常运作。
2 Android客户端的日志采集系统现状
客户端系统种类甚多,对于实现复杂业务场景的客户端系统,在出现系统异常时,常常难以为每个问题提供场景复现与复测条件,因此需要日志收集系统的支持。当前,在复杂业务客户端系统中,开源的Android应用最为广泛,故本文主要探讨Android客户端的日志采集系统如何实现,并解决客户端日志系统面临的主要难点问题。
在Android系统的应用中,日志级别分为错误日志(Error)、警告日志(Warn)、信息日志(Info)、调试日志(Debug)、详细日志(Verbose)。日志级别用于筛选日志内容时,使用者可根据实际需要来选择查看不同级别的日志。
目前,常见的Android日志收集方式主要有以下3种。
1)日志仅本地存储,用户主动回传。在客户端出现严重问题时,引导用户主动操作上报日志压缩文件。通常作为操作系统方的实现方式,例如:手机系统、车机系统,采集的日志类型包含系统日志、应用日志、内核日志、外部设备日志等,日志内容全,覆盖范围广。由于操作系统的重要性,在发布正式版本前大多经过了一层层的严格测试,线上问题较少。采用這种日志收集形式,便于更针对性地解决特定用户的特定问题,并最大程度减少对于网络资源以及服务端资源的消耗。
2)监听系统应用程序异常,上传错误日志。通常面向应用层的软件,主要由第三方提供服务,在捕获到App发生异常时,自动采集错误日志到第三方后台,主要用于解决应用程序崩溃问题以及应用无响应问题。这种方式接入简单高效,能够快速、便捷地为App开发者提供错误统计以及日志数据。缺点则是日志内容有限,且只能在严重错误发生时获取日志信息,而业务功能错误无法收集。
3)实时回传核心业务功能的相关日志。在指定的业务代码位置直接定义日志上传规则及内容,每当产生新日志时即刻上报,信息冗余量较大,一般仅用于特定核心业务功能的状态上报。
3 研究目标
基于Android客户端的日志采集系统现状分析可知,前端日志采集的难点主要在于如何解决日志数据量大、价值密度低的问题。若全量日志数据尽数存储并回传,会显著地占用客户端设备的I/O性能、CPU计算性能、存储容量以及网络流量,且其中能够直接发挥作用的有效日志却可能不足总量的万分之一,服务端接收到的数据量更与用户数量直接相关,这大量的冗余数据对用户和服务端的资源都造成了浪费。所以,主流的解决方案都会考虑解决或回避这些问题,例如:仅在发生程序崩溃时上传错误日志,尽量提高上传日志数据的价值密度,仅上传特定用户的日志数据,降低服务端资源消耗,更针对性地处理用户问题。
本文研究一种“全量滚动缓存+动态配置上报”的Android客户端日志采集系统解决方案。①全量滚动缓存是指对系统中所有的日志进行本地持久化存储,并加入数据队列的处理模式,当日志内容超出存储池大小的时候,依次存储新的日志和删除最旧的日志内容,以保证存储完整的日志信息,但不会超出预设的存储池大小;②动态配置上报是指通过后台动态配置的方式,控制日志数据是否上报、上报的内容、上报的频率等信息,依据需求来确定需要上报的内容和方式,减少无用日志上报。
根据Android客户端日志采集系统解决方案的主要思想,可以将设计目标拆分为以下4个方面。
1)配置功能:日志采集需要具备动态配置功能,可以通过服务端配置文件控制日志存储池大小、日志内容上报的过滤条件、上报频率等配置参数。
2)性能要求:日志采集模块需要接入方便,稳定高效,对项目的入侵度低,对目标设备性能影响小。
3)日志存储:日志采集内容可以进行本地持久化,不挤兑应用的存储空间,日志内容滚动更新,应用意外停止时具备防止日志内容丢失的机制。
4)数据安全性:日志采集内容需要保证安全性,对内容进行加密,防止信息泄露。
本文设计的日志采集系统在适用范围方面,只要是具备数据存储能力和网络传输能力的设备,都符合本文设计的系统要求,而市面上运行Android系统的主要设备有智能手机、平板电脑、汽车的车载车机模块、智能电视或机顶盒等,都具备存储与网络传输的基础能力。
4 数据模型定义
数据模型中的数据结构采用JSON格式,主要原因是Android依赖库自带JSON库,无需增加其他第三方依赖,且性能稳定,并提供了很好的可读性。主要的数据模型有“日志数据模型”和“配置文件数据模型”。日志数据模型示例见表1,配置文件数据模型示例见表2。
5 系统架构详细设计
系统的架构设计分为日志管理控制模块、本地存储模块、加密模块、网络请求模块、自动化日志插桩模块、Crash与ANR日志收集模块,整体架构设计如图1所示。
1)日志管理控制模块:整个日志采集系统的主要业务逻辑模块。用于管理日志系统的整体调度,控制是否开始日志收集、日志文件的缓存大小、缓存时间、日志上报时间间隔等信息。配置信息的获取时机是在系统的初始化过程中,即在系统每次启动时请求最新的配置信息。为了进一步保证配置信息的及时更新,对需要更新的配置信息,将会在每次上报日志的响应体中进行跟随返回指向性配置。日志管理配置信息获取流程如图2所示。
若使用长链接或消息推送协议的方式来更新配置信息,会更高效与及时,但这样无疑会增加整个系统的复杂度,也需要付出更多的性能代价,故本文建议的配置更新方式为请求伴随的方式。
2)本地存储模块:日志系统的核心模块。日志信息通常数据量庞大,读写I/O本就是比较消耗性能的操作,如果调度写入日志信息存储到本地,会太过消耗系统的I/O资源,若日志采集系统会从性能上影响到业务功能的流畅性,则是得不偿失的。因为存储部分是整个系统中的主要性能模块,所以需要尽可能地对其进行性能优化。Android系统的应用运行采用的是java虚拟机的执行机制,内存的分配与回收由虚拟机自行调度,面对大量的日志数据持续处理的条件下,硬件配置较低的宿主设备会频繁触发GC,而表现到顶层应用的现象就是卡顿,可通过Android的NDK工具集,使用C++的原生代码实现整个日志的存储调度。同时还可以利用linux的mmap内存映射方法,省去写入存储前需经过buffer内存空间的过程,直接映射内存地址,当发生应用意外中断和I/O资源满载等异常情况时,能够大大降低数据丢失风险。
3)加密模块:日志内容反映了系统或软件的运行状态,输出的参数甚至可能包含一些关键涉密信息,需要对日志内容进行加密,保证信息安全。对日志的内容进行加密时,由于日志数据量庞大,需要使用高效的数据加密方式,并保证日志内容不被破解。加密方案主要参考https协议的数据传输加密模式,对日志内容使用对称加密方式进行加密,同时对密钥文件使用非对称加密方式进行加密。日志信息加密存储流程如图3所示。
4)网络请求模块:用于与服务端的网络数据传输,包含日志系统的控制信息获取,以及日志文件上报。客户端采用队列形式的单一请求,使用Android系统自带的HttpURLConnection请求类,HttpURLConnection是对于http协议的封装,底层通过Socket通信实现。其优点是作为系统库类较为稳定,也不需要增加其他的网络封装库,使得日志采集系统盡量轻量化,同时可以避免对于外部库的依赖而产生的冲突与版本兼容问题。
5)自动化日志插桩模块:辅助功能之一,以可选插件的形式添加到系统中,对于一些无输出日志的功能模块,可为其增加日志。
6)Crash与ANR日志收集模块:辅助功能之一,以可选插件的形式添加到系统中,监听系统是否出现Crash与ANR,自动获取系统内的Crash堆栈日志和ANR线程日志文件上报。
6 数据安全与用户隐私
日志输出的内容可能是业务应用中的各项数据,数据内容甚至可能包含用户行为数据和隐私数据。因此,对于日志采集系统来说,一方面需要符合隐私协议与用户手册的内容,是否开启日志采集,采集哪些内容需要完全可控,这一点可以通过日志采集系统中的日志管理控制模块实现;另一方面需要保证传输的数据安全,不能被黑客入侵手机获取应用内的核心信息,也不能被抓包或中间人攻击的方式获取到日志数据信息,这一方面则通过日志采集系统的加密模块来实现对数据的保护。
7 应用与拓展
本文所论述的是如何在Android客户端实现一个高效、稳定、可控的日志采集系统,虽然未对后端服务设计进行详细说明,但其后端服务对于前端的Android日志采集系统的功能有着重要的关联与影响。一方面,其能够控制日志配置的管理下发,另一方面,后端服务保存所有上传的日志数据。
现阶段后端的日志系统较为成熟,一般使用skywalking管理微服务请求调用链,记录整条链路的调用详情;通过trackID贯穿整条链路;使用logstash来过滤有效的日志信息;使用elasticsearch来存储logstash过滤后的日志信息和skywalking的链路数据;使用kibana来读取日志并展示统计信息页面。在存储和管理Android前端时的日志信息时,只要对日志的数据模型进行设计整合,即可对前后端的日志数据进行统一管理,降低后端服务资源消耗。此外,对于应用程序中的异步方法和多线程方法来说,日志信息的记录会呈现为乱序,不便于将同一调用链下的日志进行整合排查,而通过在前端请求中也加入trackID,打通前后端日志的调用链关系,可以实现更高效的全链路日志排查。
8 总结
本文从控制能力、终端性能、数据安全性以及前后端整合的角度,论述了在Android平台下对于客户端日志采集系统的整体设计。在实际应用场景中,可以结合业务需求,对日志的配置文件和日志模型进行调整,也可以根据現有的后端日志系统进行适配性调整。
参考文献:
[1] 赵书慧. Android日志过滤器中正则表达式的应用[J]. 电子测试,2021(2):84-85.
[2] Meng Zhaoyi,Xiong Yan,Huang Wenchao,etc. AppAngio:Revealing Contextual Information of Android App Behaviors by API-Level Audit Logs[J]. IEEE TRANSACTIONS ON INFORMATION FORENSICS AND SECURITY,2021(16):1912-1927.
[3] 徐永新. 高性能分布式日志系统研究与设计[J]. 工业控制计算机,2020,33(12):44-46.
[4] 郑仕元,刘军. 不可信环境下的客户端日志保护机制[J]. 计算机工程,2011,37(23):138-140.
[5] 王祥雒,李毅. Linux中基于mmap()的共享存储实现研究[J]. 计算机应用,2006(S2):307-309,320.
[6] 吴云周,程鹏,林飞. JSON在Android客户端和网页客户端的应用研究[J]. 电脑编程技巧与维护,2017(18):40-43.
(编辑 凌 波)
作者简介
谭倚靖(1994—),女,工程师,主要从事大数据应用相关工作。