使用XLog、Spring-Boot、And-Design-Pro搭建日志系统

栏目: Java · 发布时间: 6年前

内容简介:日志系统用于记录用户行为和数据以及崩溃时的线程调用栈,以帮助程序员解决问题,优化用户体验。iOS系统就有自带Crash收集应用程序“ReportCrash”来收集App Crash信息,我也深入了解过iOS收集Crash 信息的过程并记录在此“譬如用户反馈,拍照偏黄,中间经过了十几个渲染管线,没有log真呵呵,你又不可能让用户再拍一次”

日志系统用于记录用户行为和数据以及崩溃时的线程调用栈,以帮助 程序员 解决问题,优化用户体验。

iOS系统就有自带Crash收集应用程序“ReportCrash”来收集App Crash信息,我也深入了解过iOS收集Crash 信息的过程并记录在此 CPU发生异常到生成Crash Log的过程 , 但用户遇到的很多问题不仅仅是Crash,更何况有些情况仅靠Crash Log并不能定位Crash,而且ReportCrash 收集的Crash信息还需要用户同意才可以和开发者共享。为了说明用户日志的重要性,这里引入一个faceu 团队-轻颜相机-Tom哥的调侃

“譬如用户反馈,拍照偏黄,中间经过了十几个渲染管线,没有log真呵呵,你又不可能让用户再拍一次”

因此大多数App 都带有Crash收集框架和日志收集框架,而Crash信息也是日志信息的一种,为什么要分成两个框架去收集呢?因为信息采集方式不一样,Crash收集框架通过捕获系统发送来的 Mach 异常和 Unix 信号进行信息采集、而日志收集框架是程序员主动代码触发的信息采集,信息采集部分共用代码很少,所以分成两个框架也更易于维护。

这里介绍的日志系统是收集非Crash 信息的日志系统。该系统分为三部分:

  • 采集部分:使用微信开源的日志采集组件XLog,该组件具有 安全性流畅性完整性容错性 的优点。
  • 传输部分:使用Spring Boot 开发Web服务器,Web服务器提供简单的文件上传和下载、文件上传白名单获取和设置的功能。
  • 管理部分:使用Ant Design Pro 框架来开发后台管理系统,在管理系统中提供页面进行设置日志上传白名单,及日志下载。

下面和大家聊一聊我技术选型的过程

二、技术选型:本日志系统的技术栈

都说技术服务业务,考虑技术选型当然离不开业务需求。

其实团队项目之前就有日志系统,没有使用三方框架,而是自己写了一些简单的策略,如按优先级写文件或上报服务器。但仍满足不了客户端开发的需求

  • 有个致命的缺点是:找日志看的话没有可视化平台,日志上报的接口对应的服务端同学早就离职了,而找别的服务端同学帮捞日志比较费时费力。
  • 其次,日志明文写文件保证不了 安全性 、闪退时无法保证Log的 完整性 、本地日志管理策略也没有对文件数量、单个文件大小做限制
  • 再者,日志只输出到console和文件,想要数据通过web socket实时输出到web页面展示的话,代码层面不易于扩展,这个功能可以帮助在真机调试push、测试同学实时查看埋点信息。

开发有时间限制,需求也就有优先级之分

2.1 最高优先级需求:稳定的日志传输服务和可视化的日志管理

服务端和前端同学人力紧张,而且这个不是挣钱的产品需求,不一定能争取到排期让服务端和前端同学支持“稳定的日志传输服务和可视化的日志管理”这个需求,而且我们的Crash 收集和查看 工具 都是用的腾讯的,不是同一个公司同一个部门,更别指望他们来支持了,只能网上寻找解决方案。

2.1.1 Seafile 个人网盘 + CocoaLumberjack 日志采集

本人服务端开发经验匮乏,只搞过vps搭建vpn和博客,并没有玩过web服务器,找到一个不需要搭建web服务器的方案。服务器搭建Seafile 个人网盘服务

Seafile,是一套中国国产的开源、专业、可靠的云存储项目管理软件,解决文件集中存储、共享和跨平台访问等问题。正式发布于2012年10月。除了一般网盘所提供的云存储以及共享功能外,Seafile还提供消息通信、群组讨论等辅助功能,帮助员工更好的围绕文件展开协同工作,已有10多万用户使用。

Seafile 是比较成熟的方案了,还提供接口来上传、下载文件,赶紧买个10块/月的腾讯云学生机搭个Seafile 个人网盘验证一下。

使用XLog、Spring-Boot、And-Design-Pro搭建日志系统

半天业余时间就解决了“稳定的日志传输服务和可视化的日志管理“,接着又调研了下客户端日志采集框架,发现 CocoaLumberjack start数量很多,最近还有提交记录,而且框架设计得易于扩展,已经有基于CocoaLumberjack 去解决“有通过web socket实时输出log到web页面”问题的方案,另外,CocoaLumberjack 还支持对文件数量、单个文件大小的设置。CocoaLumberjack 这个方案看着挺好,马上又撸了个Demo去验证。

拿着Demo去和同事讨论,总结了几个问题:

  • Seafile,高定制化牺牲了可扩展性

    • 除了文件上传下载外,无法自定义接口来进行更多的C/S交互,比如客户端询问服务端日志上传类型,是上传用户日志还是上传数据库文件,是发送到微信好友还是上传到服务器。
    • 数据存储孤独,无法和其他数据进行联动展示,还是可扩展性不好。比如用户反馈的问题的日志文件应该和Crash收集文件放到同一个地方才合理,虽然Crash 收集用的是第三方框架,无法自己去改代码做扩展,万一以后不跟那个三方框架合作了呢,或者用户日志的数据需要和其他数据进行联动呢。
  • CocoaLumberjack 仍无法百分百保证Log的 完整性 ,在App Crash时无法保证Log 已经写到文件。因为CocoaLumberjack是通过 -[NSFileHandle writeData:] 来进行写文件的,此方式除了无法保证Log完整性外,相对mmap中使用内存映射文件来执行写操作的方案也较慢

2.2 方案优化

既然找不到服务端和前端同学来帮忙,那就硬着头皮自己上吧。分解任务,逐个击破!将日志系统分成相对独立的三部分 采集部分、传输部分、管理部分

  • 采集部分:使用微信开源的日志采集组件XLog,该组件具有 安全性流畅性完整性容错性 的优点。
  • 传输部分:使用Spring Boot 开发Web服务器,Web服务器提供简单的文件上传和下载、文件上传白名单获取和设置的功能。
  • 管理部分:使用Ant Design Pro 框架来开发后台管理系统,在管理系统中提供页面进行设置日志上传白名单,及日志下载。

2.2.1 采集部分:高性能日志采集组件 XLog

流畅性是首要考虑

在采集部分,之前一直没有提到 流畅性 的重要程度,其实这个才是日志采集组件的最高优先级需求,不能因为日志频繁写文件导致应用程序卡顿或耗电量增加。因为项目中之前没有高频高密度地使用日志,没能及早意识到 流畅性 的重要程度。频繁写文件为什么会卡顿?

当写文件的时候,并不是把数据直接写入了磁盘,而是先把数据写入到系统的缓存(dirty page)中,系统一般会在下面几种情况把 dirty page 写入到磁盘:

  • 通过页的 flag 标记为有改动,操作系统定时将这种 dirty page 写回到磁盘上,时机不可控。
  • 调用用户态的写接口->触发内核态的sys_write->文件系统将数据写回磁盘。而文件系统回写磁盘的时机也是不可控的,发现 dirty page 占用内存超过系统内存一定比例后回写。

而且数据从程序写入到磁盘的过程中,牵涉到两次数据拷贝:一次是用户空间内存拷贝到内核空间的缓存,一次是回写时内核空间的缓存到硬盘的拷贝。其中内核空间和用户空间频繁切换的话也带来性能损耗。

保证流畅性无法兼顾完整性

避免频繁写文件,先在内存中创建buffer,合适时在进行写文件。这个方式虽然保证了流畅性,缺无法保证完整性,而且集中压缩日志会导致 CPU 短时间飙高。程序发生Crash的话内存中的数据还没有持久化,实时写文件的话又无法保证流畅性,该如何是好?

mmap 保证流畅性和完整性

mmap 是使用逻辑内存对磁盘文件进行映射,中间只是进行映射没有任何拷贝操作,避免了写文件的数据拷贝。操作内存就相当于在操作文件,避免了内核空间和用户空间的频繁切换。

为了验证 mmap 是否真的有直接写内存的效率,微信团队写了一个简单的测试用例:把512 Byte的数据分别写入150 kb大小的内存和 mmap,以及磁盘文件100w次并统计耗时

使用XLog、Spring-Boot、And-Design-Pro搭建日志系统

mmap 除了能保证 流畅性 ,还能兼顾日志的 完整性 ,下面这些情况回自动回写磁盘

  • 内存不足
  • 进程退出
  • 调用这两个函数
    msync(mmap_ptr, mmap_size, MS_ASYNC)
    munmap(mmap_ptr, mmap_size)
    
  • 不设置 MAP_NOSYNC 情况下 30s-60s(仅限FreeBSD)

xlog 还保证了安全性和容错性

通过压缩和加密可以保证日志信息非明文写入磁盘,同时减少所占用的 mmap 的大小。策略是

在写进逻辑内存之前就把日志先进行压缩,再进行加密,最后再写入到逻辑内存中

微信选择的具体压缩方案可以参考文章 cloud.tencent.com/developer/a… ,简单来说就是 能够保证日志 容错性 的流式压缩,

即使压缩单位中有部分数据损坏,因为是流式压缩,并不影响这个单位中损坏数据之前的日志的解压,只会影响这个单位中这个损坏数据之后的日志。

所以一句话总结xlog 为什么具有 安全性流畅性完整性容错性 的优点

使用流式压缩方式对单行日志进行压缩,压缩加密后写进作为 log 中间 buffer的 mmap 中,当 mmap 中的数据到达一定大小后再写进磁盘文件中

另外mmap 相关的API 如下,参考开源的XLog,你也可以给团队定制基于mmap的日志采集组件

FILE *fp = fopen(file_path, "wb+");
file_num = fileno(fp);
ftruncate(file_num, size);      // 调整size
char *mmap_ptr = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, file_num, 0);

// 然后就可以对 mmap_ptr 进行读写了

munmap(mmap_ptr, mmap_size);    // 解除一个map,内容会写回磁盘
msync(mmap_ptr, mmap_size, MS_ASYNC);  // 同步,异步写回磁盘

扩容办法:先解除munmap,调大文件大小,重新调 mmap 映射即可

复制代码

手淘的SatanWoo 五子棋大佬在解析xlog源码的时候给出了两点使用mmap时需要额外注意的点,文章在此

  • 注意点1: 如果我们尝试打开mmap成功了,但是mmap对应的数据地址是NULL,那我们必须停止映射。因为NULL所代表的地址处于内核态,一旦映射了,势必造成Crash。
  • 注意点2:使用mmap的情况下,如果上次应用断电了、Crash,日志的信息还是存在的,但是并不一定能及时的转换成我们想要的日志文件。因此我们首先检查下mmap文件里面有没有数据,有的话先把这部分转换成日志。

2.2.2 传输部分:使用Spring Boot 快速开发Web服务器

在网上有很多介绍Spring Boot的文章,蚂蚁金服的一位前辈写了篇 Spring Boot快速开始指南 我看还不错,介绍了Spring-Boot的知识点线路图和基本概念,还有如何快速创建一个Spring Boot 应用。

我在自己的学生机开发完,用postman 调试完接口再去找公司运维要机器资源,部署到了公司机器上。由于我也是照葫芦画瓢,只是使用Spring Boot提供了简单的文件上传和下载功能,暂时无法在这一块深入介绍自己的经验,不过日志系统对应的Spring Boot部分我已经放到了github,感兴趣可以clone 下来跑跑看 github.com/HonchWong/H…

项目名字是RDA,也就是研发助手的英文,意味着这个Spring-Boot应用不会止步于此。因为平时iOS业务开发中会经常遇到些阻碍效率的问题,会想出很多“牛逼”的技术方案去解决,但仅仅熟悉Cocoa 框架是实现不了的,少不了服务端的支持,比如最近业余在做的三个需求,【客户端可视化Mock数据:提供可视化的界面去设置Mock网络数据,无需硬编码Mock和减少编译时间】、【客户端可视化一键生成bug单:提供可视化的界面去输入bug描述,并生成bug单,提高研发效率】、【客户端埋点管理平台:提供平台去管理埋点需求、验证埋点、埋点信息自定义展示】,这也是立个flag,技术服务业务,业务必将反哺于技术,19年好好学习服务端知识,再来完善这篇文章 :)

2.2.3 管理部分:直接fork "Ant Design Pro"进行改装

Ant Design Pro 是蚂蚁金服团队在 Ant Design 的设计规范与组件库基础上推出的一套 React 实现的企业级中后台前端/设计解决方案。基于这个框架可以快速开发后台管理系统,如果你有React Native的开发经验,那么对基于React开发的Ant Design Pro 肯定也是上手很快。本日志系统使用到的 Ant Design Pro 放到了github github.com/HonchWong/H…

三、本日志系统如何使用

除了服务端和前端的Demo,iOS端的Demo我已经提交到github。需要从github下载两个工程 web服务器工程 github.com/HonchWong/H… 、 iOS端工程 github.com/HonchWong/H…

  • 本地运行web服务器
    • 环境搭建,安装JDK、Maven
    • HCRDA-SpringBoot/src/main/resources/application.properties 修改配置文件中的用户日志文件夹位置,比如,这个是我本地存放的位置 userlog.dir.path=/Users/huanghongchang/Desktop/userLog
    • 在HCRDA-SpringBoot 目录下执行 mvn spring-boot:run
    • 访问 http://localhost:9080
  • 运行iOS工程
    • pod install 安装依赖
    • 修改 HCLogFileUploadManager.m 中的 static NSString *_hostURL 为 localhost的ip

3.1 XLog使用

  • 初始化xlog。 涉及四个API,具体调用可以参考Demo工程中的 XLogHelper.m +setupXlog

    setxattr([[self xlogFileDirPath] UTF8String], attrName, &attrValue, sizeof(attrValue), 0, 0);
    xlogger_SetLevel(kLevelDebug);
    appender_set_console_log(true);
    appender_open(kAppednerAsync, [logPath UTF8String], "Test");
    
  • 打log, xlogger_Write(&info, message.UTF8String) ,Demo用宏定义封装了该API

  • 需要在APP终止方法applicationWillTerminate中反初始化 appender_close()

以上只是Demo中的使用方式,更多详细API 可以参考xlog的wiki Mars iOS/OS X 接口详细说明 ,Demo中对log日志进行加密,appender_open 提供了参数传入公钥,xlog的加密使用可以参考文档 Xlog 加密使用指引

使用XLog、Spring-Boot、And-Design-Pro搭建日志系统

3.2 日志上传和下载

本日志系统日志上传的策略采用白名单的方式,在后台管理系统设置白名单,白名单包含用户唯一标识符uin及对应的上传的日志类型(如数据库or日志log),用户输入白名单中的uin,获取需要上传的日志类型进行日志上传。

在HCRDA-SpringBoot 目录下执行 mvn spring-boot:run 后,在浏览器中访问 http://localhost:9080 , 输入账户admin 密码 123,在用户日志-指定用户中可以看到有白名单中已经有八个,目前Demo 中只实现了【选择日志上传单个文件】和【上传全部日志】

使用XLog、Spring-Boot、And-Design-Pro搭建日志系统

设置白名单后便可在Demo 中走上传流程,操作步骤如下

使用XLog、Spring-Boot、And-Design-Pro搭建日志系统

在后台管理系统中可以查看和下载上传的日志

使用XLog、Spring-Boot、And-Design-Pro搭建日志系统

3.3 查看日志

我这里并没有对xlog文件进行加密,而是对zip文件进行了加密,而密码用了xor的方式对字符串进行混淆避免用hopper等反汇编工具直接查看,当然这个还不是绝对安全,还是可以通过逆向App,动态调试,获取zip文件的密码,只不过也加大了破解的难度。虽然没有加密,但单行log还是进行了流压缩,需要用这个脚本进行解压 decode_mars_nocrypt_log_file

执行脚本 python decode_mars_nocrypt_log_file.py xxx.xlog

使用XLog、Spring-Boot、And-Design-Pro搭建日志系统

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

PHP Cookbook

PHP Cookbook

Adam Trachtenberg、David Sklar / O'Reilly Media / 2006-08-01 / USD 44.99

When it comes to creating dynamic web sites, the open source PHP language is red-hot property: used on more than 20 million web sites today, PHP is now more popular than Microsoft's ASP.NET technology......一起来看看 《PHP Cookbook》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具