电一闪的博客

平凡亦有极致体现

App日志查看器

| Comments

背景

  实际开发中,有在生产环境里碰到诸多疑难杂症的棘手问题。对于问题,最佳解决手法之一是坏点检测,一层一层诊断,抽丝剥茧。那么诊断依据——日志,就是一种强大的执行手段。

最终效果

日志按时间戳倒序展示,提供关键字搜索

日志文件选取

日志文件选取器

日志文件选取

设计思想

一、文件结构:

  1、第一次构思的文件结构,就是简单的顺序写入文本文件,每一条记录加入一些格式化符号,增加辨识度。比如:

2015-06-01 21:35:03 应用特征名 日志级别【日志内容】\r\n  
2015-06-01 21:36:03 应用特征名 日志级别【日志内容】\r\n  
2015-06-01 21:37:03 应用特征名 日志级别【日志内容】\r\n  
2015-06-01 21:38:03 应用特征名 日志级别【日志内容】\r\n  
2015-06-01 21:39:03 应用特征名 日志级别【日志内容】\r\n  
2015-06-01 21:39:07 应用特征名 日志级别【日志内容】\r\n  

  那么问题来了,作为文件,只有两种写方式:覆盖写 or 尾部添加。覆盖写不适用于保存日志,而尾部添加如上所示效果,较新的日志,排在底部。疯狂滚动是一种不可理喻的交互行为(开发人员要懂得节约用户的时间,无论用户是谁)。那有什么方法可以改进?
  2、第二次构思的文件结构,便是数据库建表。用数据库存储日志,可以顺序存储,倒序取出,最终展示很容易做到最近写入的展示在顶部。

2015-06-01 21:39:03 应用特征名 日志级别【日志内容】\r\n  
2015-06-01 21:38:03 应用特征名 日志级别【日志内容】\r\n  
2015-06-01 21:37:03 应用特征名 日志级别【日志内容】\r\n  
2015-06-01 21:36:03 应用特征名 日志级别【日志内容】\r\n  
2015-06-01 21:35:03 应用特征名 日志级别【日志内容】\r\n  
2015-06-01 21:34:07 应用特征名 日志级别【日志内容】\r\n  

  表结构为:

CREATE TABLE IF NOT EXISTS 'log' ("  
"[rowid] integer PRIMARY KEY ASC AUTOINCREMENT DEFAULT 1,"  
"[dateTimeString] char(30),"//日期字符串  
"[logLevelString] char(30),"//日志等级字符串  
"[appName] varchar(50),"//消息动向类型:接受或者发送  
"[logContent] text,"//日志内容,AES128加密字符串  
"[logLevel] integer,"//日志级别  
"[timestamp] double"//时间戳,用于倒序查询  
")"  

  此外,为了避免日志内容被不法用户导出获取秘钥及服务器接口地址,对每一条日志内容做AES128加密保存

二、日志查看体验

  1、第一次构思,确定搜索是必不可少的。例如,以前碰到一个”登录奖励”提示框偶尔不弹出的问题。该功能根据接收到的消息内容,弹框展示。离线时走APNS通道,在线时用实时消息承载。偏偏debug模式下的实时消息承载100%正常,发布模式下的APNS偶尔异常,但又不是每次必现,这种情况只能打印日志进文件,记录接收到的消息内容。到这里,就出现了体验痛点。从一堆log里,挑出某“关键字”的消息内容,如大海捞针,只能copy到电脑的文本编辑器中全文搜索。
  2、第二次构思,需要将搜索到的关键字高亮。在第一次构思方案下,搜索的体验仍然不尽如意,在UITextView大篇幅的文本中搜索,滚屏频繁根本不知道当前匹配到的关键字在哪个位置。因此,高亮可有效解决此问题,将UITextView中的文本全部改为NSAttributedString。
  3、第三次构思,关键字匹配忽略大小写。手机上查看日志,区分大小写的输入十分繁琐,且查看日志一般没有将关键字精确到大小写的场景,因此忽略大小写的搜索,可以减少输入代价。
  4、第四次构思,搜索完毕,停留并提示一次“已经到末尾”,然后将搜索起始位置设置到开头。在不知情的场景下,搜索下一个匹配对象,是无法获知前方有多少匹配数的,因此在没有可匹配对象后,提示,并在末尾停留一次,可以很友好的展示搜索结果。

三、日志文件管理

  1、首先,日志文件数量和体积必须要做限制。规则如下:日志文件以日期命名,内容以天为单位存储在一个文件里;文件数大于某个指定值,比如10,删除当前日志文件数一半的较旧日志文件;单个日志文件大小不作限制;每次写日志前,确保写入时的日期的对应文件存在。
  2、其次,日志查看页面支持在app内直接切换日志文件,并动态加载。使用之前写好的,给社交分享使用的IconSheet控件,方便展示文件图标和文件名。如下图:
  日志文件选取
  3、最后,支持日志内容热加载。每次点击一个日志文件,首先关闭文件选取器,主界面开启进度指示,启动子线程,并在子线程池中将数据库读取任务放入FMDatabaseQueue,读取完成解密日志内容,还原为一个完整的NSAttributedString对象,在主线程中把得到的数据填入UITextView,同时关闭进度指示器,提示“新的内容已加载完成”(日志文件一多,解密耗费时间越多)。

至此,一个自行设计的日志查看器,开发完毕。

Comments