App技术选型--日志框架

title: App技术选型--日志框架

版 本 历 史

版本 责任人 日期 备注
V1.0 曾维铭 2017-04-12 创建文档。

日志对于开发来说是非常重要的,不管是调试数据查看、bug问题追踪定位、数据信息收集统计,日常工作运行维护等等,都大量的使用到。

功能需求

  • 线程的信息
  • 类的信息
  • 方法的信息
  • 格式打印JSON、XML等
  • 点击链接跳转到源码打印处
  • 拥有默认TAG和自定义TAG
  • release包中不能泄漏Log
  • 使用友好,使用高效
  • 日志持久化到本地
  • 日志框架的扩展性

Xlog

mars 是微信官方的终端基础组件,是一个使用C编写的业务性无关,平台性无关的基础组件。Xlog是mars中可以独立使用的日志模块。

优势:

  • 性能好:使用了中间层,减少了读写磁盘的次数。使用mmap进行逻辑内存对磁盘文件进行映射,中间只是进行映射没有任何拷贝操作,避免了写文件的数据拷贝,操作内存就相当于在操作文件,避免了内核空间和用户空间的频繁切换。占用内存CPU资源少。
  • 功能丰富:与原生Log使用几乎一致,但增加了写入文件功能,同时自带加密
  • 稳定:腾讯微信团队正在使用,久经考验。

面临的问题:

  • Xlog是用C写的,出问题调试起来不太友好。
  • so库比较大,导入后APK增大1.5M。

解决方案:

  • 只能通过 xlog 输出的信息进行排查。不过日志作为辅助系统,出问题可能性低,而且问题影响不大。
  • 如果很在乎APK包大小的话,可以只集成armeabi的so包。

持久化的实现

为了提高日志的性能,Xlog引入了 mmap作为中间buff层,当buff层满足一定条件时,才将日志写到存储空间。

日志存储位置

初始化时,写在logPath中。
logPath = Environment.getExternalStorageDirectory().getAbsolutePath()/sdcard/PhiComm/app name/logs

日志文件命名

APP名_日期

日志格式

一般内容:[日志级别][日期][PID][TAG(类名)][线程---日志内容]
方法栈:[日志级别][日期][PID][TAG(类名)][线程---方法栈]

日志使用策略

每次启动时会删除过期文件,只保留十天内的日志文件(该值定义在appender.cc中的 kMaxLogAliveTime ),所以给 Xlog 的目录请使用单独目录,防止误删其他文件。目前不会根据文件大小进行清理。如若想自定义清理逻辑请自行更改appender.cc中的 __del_timeout_file 函数。

日志使用级别

<table><tr><th></th><th colspan="2">debug</th><th colspan="2">release</th></tr><tr><td></td><td>控制台</td><td>持久化</td><td>控制台</td><td>持久化</td></tr><tr><td>v</td><td>程序说明</td><td>null</td><td>null</td><td>程序说明</td></tr><tr><td>d</td><td>需要调试的代码</td><td>null</td><td>null</td><td>null</td></tr><tr><td>i</td><td>程序正常运行时日志</td><td>程序正常运行时日志</td><td>null</td><td>程序正常运行时日志</td></tr><tr><td>w</td><td>会出现潜在错误的情形</td><td>会出现潜在错误的情形</td><td>null</td><td>会出现潜在错误的情形</td></tr><tr><td>e</td><td>catch块中,程序状态检查语句</td><td>catch块中,程序状态检查语句</td><td>null</td><td>catch块中,程序状态检查语句</td></tr></table>

日志混淆问题

类名,方法名等参数使用的是Java lang包下的StackTraceElement和Throwable获得。具体混淆策略需要在原型中测试后才能确定。

LogUtils

由于Xlog提供的功能有限,为了满足使用需求,这里对Xlog进行了封装。

实现的功能:

  • 支持打印字符串,集合,JSON,日志级别,日期,线程ID,线程名,异常信息,堆栈信息,源代码跳转。
  • 日志持久化到外部存储,自动清理过期日志,保存最近十天的日志文件。

使用指南

1.添加读写权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

2.在Application的onCreate中初始化

初始化:

LogUtils.init();

注:

  1. 为了不造成混乱,这里初始化时不提供自定义配置。如日志默认TAG,保存路径,日志方法栈打印数量等在代码中写死。
  2. 根据BuildConfig.DEBUG参数,debug下会打印到控制台,release下控制台输出关闭。

3.打印日志

    public static void d(Object message) 
    public static void d(Object message, boolean isPrStack) 
    public static void d(String tag, Object message, boolean isPrStack) {
    public static void d(String tag,final String message, boolean isPrStack, final Object... args)
    public static void json(String json, boolean isPrStack) 
    public static void log(int priority, String tag, Object message, boolean isPrStack, @Nullable Throwable throwable, Object...args)


注:

  1. message为打印内容,可接收任意参数。
  2. isPrStack控制是否打印堆栈信息。
  3. 支持对日志字符串格式化,args为参数。内部会调用String.format(String format, Object args)。
  4. JSON输出的缩进默认为2,可自行修改。
  5. 打印异常信息可调用log,传入Throwable。
  6. 堆栈打印的方法数通过METHOD_CCOUNT控制,默认为8。可以自行修改(可能要考虑线程安全问题,不过影响也不大)。

打印JSON结果

[I][2017-04-20 +8.0 15:52:40.412][12502, 1*][PhiComm][, , 0][Thread:main---{
  "name": "BeJson",
  "url": "http:\/\/www.bejson.com",
  "page": 88,
  "isNonProfit": true,
  "address": {
    "street": "科技园路.",
    "city": "江苏苏州",
    "country": "中国"
  },
  "links": [
    {
      "name": "Google",
      "url": "http:\/\/www.google.com"
    },
    {
      "name": "Baidu",
      "url": "http:\/\/www.baidu.com"
    },
    {
      "name": "SoSo",
      "url": "http:\/\/www.SoSo.com"
    }
  ]
}

字符串,堆栈,Throwable打印结果

[D][2017-04-20 +8.0 15:52:40.411][12502, 1*][Throw][, , 0][Thread:main---{i=zwm, love=joyce}
VMStack.java/dalvik.system.VMStack/getThreadStackTrace/-2
Thread.java/java.lang.Thread/getStackTrace/580
LogUtils.java/com.example.weimingzeng.myapplication.LogUtils/getThreadStack/206
LogUtils.java/com.example.weimingzeng.myapplication.LogUtils/log/232
MainActivity.java/com.example.weimingzeng.myapplication.MainActivity/onCreate/31
Activity.java/android.app.Activity/performCreate/6323
Instrumentation.java/android.app.Instrumentation/callActivityOnCreate/1108
ActivityThread.java/android.app.ActivityThread/performLaunchActivity/2385:java.lang.Throwable
    at com.example.weimingzeng.myapplication.MainActivity.onCreate(MainActivity.java:31)
    at android.app.Activity.performCreate(Activity.java:6323)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2385)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2492)
    at android.app.ActivityThread.access$900(ActivityThread.java:153)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1358)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5458)

在程序退出时反初始化:

LogUtils.unLoad();

4.解析Log

Log生成完毕后,会在指定的路径下生成相应的日志文件:

shell@R7:/sdcard/marssample/log $ ll
-rw-rw---- root     sdcard_r   153600 2016-12-30 17:06 MarsSample.mmap2
-rw-rw---- root     sdcard_r    29633 2016-12-30 17:06 MarsSample_20161230.xlog

由于使用缓存,日志只有在应用退出时才会将日志写入外部存储。其中MarsSample.mmap2是缓存文件,不用关心,我们需要的是.xlog文件,我们把这个文件pull出来,使用Mars提供的Python脚本进行解密。

找到Mars源码log/crypt/decode_mars_log_file.py下的这个文件,用python执行,生成log文件:

mars_xlog_sdk python decode_mars_log_file.py ~/Downloads/log/MarsSample_20161230.xlog

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容