腾讯Mars Xlog:移动开发者解决线上问题的秘密武器

腾讯Mars Xlog:移动开发者解决线上问题的秘密武器

对移动开发者来说,最头疼的莫过于线上出现问题,本地无法复现又没有任何日志的场景。但是考虑到应用性能和安全性,无法打印和保存过多的日志。颇有一种书到用时方恨少的感觉。

一、xlog介绍

xlog 是腾讯 Mars 终端基础组件中的通用日志模块,它有下面几个优点:

使用mmap的方案进行日志写入,mmap 是使用逻辑内存对磁盘文件进行映射,中间只是进行映射没有任何拷贝操作,避免了写文件的数据拷贝。操作内存就相当于在操作文件,避免了内核空间和用户空间的频繁切换。提升了效率同时也保证了日志的完整性。下图是官方提供的写入效率对比图 日志支持加密,提高日志信息的安全性底层使用c++实现,支持Android和iOS平台支持设置单个日志文件的保存天数和大小,基本满足日常的开发需求

二、xlog 使用

参考官方提供的 demo

2.1 引入xlog

configurations {

//定义一个新的依赖方式

cmake_depends

}

dependencies {

implementation fileTree(dir: 'libs', include: ['*.jar'])

androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {

exclude group: 'com.android.support', module: 'support-annotations'

})

implementation 'com.android.support:appcompat-v7:26.1.0'

testImplementation 'junit:junit:4.12'

implementation "com.tencent.mars:mars-xlog:${VERSION_NAME}${VERSION_NAME_SUFFIX}"

cmake_depends "com.tencent.mars:mars-xlog:${VERSION_NAME}${VERSION_NAME_SUFFIX}"

}

//获取xlog中的.so文件,用于ndk编译使用,如果项目中不包括ndk代码,可以不需要

task resolveDependencies {

project.configurations.each { configuration ->

if ("cmake_depends".equalsIgnoreCase(configuration.name)) {

def lib = configuration.resolve()[0]

copy {

from zipTree(lib)

into "${project.rootDir}/${project.name}/src/main/jniLibs/"

include "jni/**/*.so"

}

}

}

}

//build 依赖 resolveDependencies task

build.dependsOn resolveDependencies

导入xlog头文件 cmake 中 查找并链接 xlog 动态库

cmake_minimum_required(VERSION 3.4.1)

include_directories(export_include)

add_library(native-lib SHARED native-lib.cpp)

find_library(log-lib log)

set(XLOG_PATH ../jniLibs/jni/${ANDROID_ABI}/)

find_library(XLOG_LIB marsxlog PATHS ${XLOG_PATH} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)

target_link_libraries(native-lib ${log-lib} ${XLOG_LIB})

2.2 使用xlog

初始化xlog

static {

System.loadLibrary("c++_shared");

System.loadLibrary("marsxlog");

System.loadLibrary("native-lib");

}

public void initLog(boolean isDebug) {

String logPath = getExternalFilesDir(null).getPath() + "/logsample/xlog";

Xlog xlog = new Xlog();

// xlog.setMaxFileSize(0, 1024*1024);

// xlog.setMaxAliveTime(0, 1);

Log.setLogImp(xlog);

Log.setConsoleLogOpen(true);

Log.appenderOpen(isDebug ? Xlog.LEVEL_DEBUG : Xlog.LEVEL_INFO, Xlog.AppednerModeAsync, "",

logPath, "LOGSAMPLE", 0);

}

主要是appenderOpen 方法:

appenderOpen(int level, int mode, String cacheDir, String logDir, String nameprefix, int cacheDays)

level:日志等级,如果使用xlog,日志等级就比较好控制,不需要再传递给openvpn debug开关 mode: 写入的模式,支持同步和异步写入,同步写入可能会导致卡顿,release版本一定要异步写入 cacheDir:设置缓存目录 logDir:设置写入的文件目录, nameprefix:设置日志文件名的前缀, cacheDays:在多少天以后 从缓存目录移到日志目录 一般情况下填0即可

xlog 使用

直接使用xlog相关的api进行打印日志,日志会自动写入文件中。

com.tencent.mars.xlog.Log.d(TAG, "test");

com.tencent.mars.xlog.Log.e(TAG, "test");

#include "xlogger/android_xlog.h"

LOGI("test", "111111111111");

LOGD("test", "111111111111");

生成的日志文件 .xlog 文件是无法直接查看的,需要使用xlog对应的python脚本进行处理。

python decode_mars_nocrypt_log_file.py 日志文件

转换后的日志内容:

xlog加解密

生成加密秘钥,执行 python gen_key.py 命令 其中 private key 是私钥,appender_open's parameter 是公钥。

代码中设置公钥,初始化方式和上面有些差异

public void initLog(boolean isDebug) {

String logPath = getExternalFilesDir(null).getPath() + "/logsample/xlog";

Xlog xlog = new Xlog();

xlog.setMaxAliveTime(0, 24 * 60 * 60);

Xlog.open(false, isDebug ? Xlog.LEVEL_DEBUG : Xlog.LEVEL_INFO, Xlog.AppednerModeAsync, "",

logPath, "LOGSAMPLE", LOG_PUB_KEY);

xlog.setMaxFileSize(0, 1024 * 120);

xlog.setConsoleLogOpen(0, true);

Log.setLogImp(xlog);

}

Log.appenderOpen() 方法没有 pubKey 参数,需要使用 Xlog.open() 方法初始化。

修改解密脚本 decode_mars_crypt_log_file.py,替换刚才生成的私钥和公钥。

其他使用细节

由于使用异步模式,所以日志并不会实时同步到文件中,当执行日志上报操作时,需要调用 appenderFlush 方法将内存中的日志写入文件中,避免日志不完整。单条日志大小限制16kb,超过16kb会被截取,目前没有其他解决方法,需要自行判断日志大小进行拆分写入。

相关文章

养生明伤、暗伤

养生明伤、暗伤

2025-09-21 阅读 957
我想进入股票微信交流群,应该怎么做?
如何压缩PNG图片?

如何压缩PNG图片?

2025-07-31 阅读 6035