一、业务背景
用户使用客户端应用过程中,会遇到各种bug, 包括奔溃、数据显示错误、交互出现问题等等,虽然APP已经接入腾讯bugly和友盟统计,但是依然无法解决部分实际问题。
因此引入了日志的概念,为了准确的获取APP使用过程中的日志,目前采用更加成熟的组件:腾讯Mars。
二、Mars介绍
Mars 是微信官方的跨平台跨业务的终端基础组件,基于C++语言开发,可支持Android、iOS、Mac、Windows 平台。
四大模块
- comm:可以独立使用的公共库,包括 socket、线程、消息队列、协程等;
- xlog:高可靠性高性能的运行期日志组件;
- SDT: 网络诊断组件;
- STN: 信令分发网络模块,也是 Mars 最主要的部分。
xlog三大特性
- 高性能
- 准确性
- 安全性
三、Mars-iOS接入项目
1. 编译
项目在接入mars.framework之前需要先编译,在下载下来的mars文件夹下找到/mars/libraries/build_apple.py,执行
python build_apple.py
之后会生成对应的引入文件,包括mars.framework。
2. 添加相应文件和库到项目中,具体参考下图:
其中红色部分为 mars 提供的部分(可根据业务情况引入相应文件,如只使用xlog模块的话只引用log_crypt.h和log_crypt.cc即可),黄色部分是使用 mars 需要的系统库,绿色部分为需要开发者自行实现的 callback 部分。
四、xlog使用方法
1. 初始化和反初始化
需要在main.mm文件初始化
NSString *logPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingString:@"/log"];
NSLog(@"logPath: %@", logPath);
//不备份日志路径
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
setxattr([logPath UTF8String], attrName, &attrValue, sizeof(attrValue), 0, 0);
#if DEBUG
xlogger_SetLevel(kLevelDebug);
appender_set_console_log(true);
#else
xlogger_SetLevel(kLevelInfo);
appender_set_console_log(false);
#endif
/*
* 设置日志目录、日志文件前缀
* 特别强调一点pubkey,设置后才会对日志进行加密,若Debug模式下不希望加密,可以设置空"",pubkey在decode_mars_crypt_log_file.py脚本中。
*/
appender_open(kAppednerAsync, [logPath UTF8String], "fileNameprefix", "pubkey");
需要在APP终止方法applicationWillTerminate中反初始化
appender_close();
2. 打印日志
LOG_DEBUG(@"模块名称", @"日志描述:%@", 需要打印的具体信息); //开发模式
LOG_INFO(@"模块名称", @"日志描述:%@", 需要打印的具体信息); //发布模式
以上方法为打印日志的接口方法宏定义,具体实现如下:
+ (void)logWithLevel:(TLogLevel)logLevel moduleName:(const char*)moduleName fileName:(const char*)fileName lineNumber:(int)lineNumber funcName:(const char*)funcName message:(NSString *)message {
XLoggerInfo info;
info.level = logLevel;
info.tag = moduleName;
info.filename = fileName;
info.func_name = funcName;
info.line = lineNumber;
gettimeofday(&info.timeval, NULL);
info.tid = (uintptr_t)[NSThread currentThread];
info.maintid = (uintptr_t)[NSThread mainThread];
info.pid = g_processID;
xlogger_Write(&info, message.UTF8String);
}
3. 获取日志并上传到服务器
- 手动上传
- 通过日志目录目录获取日志文件,并上传服务器。
4. 解压解密日志文件
下载pyelliptic1.5.7,并解压执行:python setup.py install。
在 mars\log\crypt 下执行
python gen_key.py
如果能生成成功则表示配置成功。python gen_key.py
会生成private key 和public key,把pulic key作为appender_open 函数参数设置进去,private key务必保存在安全的位置,防止泄露。并把这两个key设置到 mars\log\crypt 中 decode_mars_crypt_log_file.py脚本中。
注意此步骤仅仅执行一次即可,团队其他小伙伴无需重复。日志解压方法:
python + python解压脚本 + .xlog文件
=>生成.log文件解压脚本:
- 解压未加密文件:decode_mars_nocrypt_log_file.py
- 解压加密文件:decode_mars_crypt_log_file.py
注意:由于解密脚本需要一些命令插件支持,若系统未安装需要,需要逐个安装,也可以通过报错来逐个安装:
import sys
import os
import glob
import zlib
import struct
import binascii
import pyelliptic
import traceback
import zstandard as zstd
- 解密报错
如果报错:ImportError: No module named pyelliptic
终端执行:
pip2 install pyelliptic==1.5.7
如果报错:Consider using the --user option or check the permissions.
终端执行:
pip2 install zstd --user
如果报错:ImportError: No module named zstandard
终端执行:
pip2 install zstandard --user
以上需要通过Python安装pip:https://pip.pypa.io/en/stable/installation/
如果报错:EnvironmentError: [Errno 13] Permission denied: '/Users/xxx/Library/Python/2.7' Check the permissions. 文件权限问题
终端获取一下文件的访问权限,或者解密前加上 sudo 命令。
五、注意事项
- 直接include xlog头文件的 oc 文件名后缀一定要是 .mm 不要使用 .m
- debug 版本下建议把控制台日志打开,日志级别设为 Debug, release 版本建议把控制台日志关闭,日志级别使用 Info.
参考: