背景
音视频SDK(实时音视频TRTC/移动直播MLVB)、即时通信SDK都有默认把sdk运行的log输出到本地文件。本地文件详细记录了SDK各模块的操作和质量信息,在遇到问题需要分析,很多时候需要获取本地日志文件配合问题定位。但是,往往位于用户手机本地的文件,受限于用户的it知识,很难从手机里取出来并发送给运营人员。因此本文提供一种参考方案,供用户方便上传日志文件。
本文档分两部分,PART1描述log文件本地位置及日志解压办法,PART2描述安卓&IOS端日志文件上传cos的方案。
本文仅作为参考,补充在某些特殊情况下,需要获取管理用户本地日志文件,来分析某些问题时使用。
PART1:本地log路径
默认输出文件的路径如下表格。可修改输出文件路径、可过滤日志等级、可关闭日志输出。
表格引用自音视频专家团队成员 腾讯云-chaoli 文章:https://cloud.tencent.com/developer/article/1502366 。更多详细内容可跳转查看。
sdk | 产品线 | 平台 | 日志路径 |
---|---|---|---|
LiteAVSDK | UGC | iOS&安卓 | iOS&Mac: sandbox的Documents/log Android: /sdcard/log/tencent/liteav (6.7以前的版本);/sdcard/Android/data/(your app package name)/files/log/tencent/liteav/LiteAV_日期.xlog(6.8版本修改成这个新路径了) Windows: %appdata%/tencent/liteav/log Web: 打开浏览器控制台,或使用vConsole记录 SDK 打印信息 小程序: 启用<live-pusher>和<live-player>标签的debug属性,使用vConsole记录打印信息 |
Player | iOS&安卓&web | ||
Smart | iOS&安卓&小程序 | ||
TRTC | iOS&Mac&安卓&小程序&Windows&Web | ||
Professional | iOS&安卓 | ||
Enterprise | iOS&安卓 | ||
IMSDK | IM | iOS&Mac&安卓&小程序&Windows&Web | iOS&Mac:日志默认路径在 App 目录下:Library/Caches/imsdk_YYYYMMDD.log 安卓:默认日志存储路径为:SD 卡下,/tencent/imsdklogs/(your app package name)/;/sdcard/Android/data/(your app package name)/files/log/tencent/imsdk/imsdk_日期.xlog(4.6.1版本修改成这个新路径了) Windows:.exe文件的同级目录 Web: 打开浏览器控制台,或使用vConsole记录 SDK 打印信息 小程序: 使用vConsole记录打印信息 |
修改log路径
sdk | 产品线 | 平台 | 修改 |
---|---|---|---|
LiteAVSDK | Smart UGC Player Professional Enterprise | iOS&Mac | //设置日志输出等级,最高级可关闭 [TXLiveBase setLogLevel:LOGLEVEL_DEBUG]; |
安卓 | //设置日志输出等级,,最高级可关闭 TXLiveBase.setLogLevel(TXLiveConstants.LOG_LEVEL_DEBUG); | ||
TRTC Professional Enterprise | iOS&Mac | //设置输出 Log 级别,最高级可关闭 [TRTCCloud setLogLevel:TRTCLogLevelDebug] //修改日志路径 [TRTCCloud setLogDirPath:(NSString *)path] | |
安卓 | //设置输出 Log 级别,最高级可关闭 trtcCloud.setLogLevel(TRTCCloudDef.TRTC_LOG_LEVEL_DEBUG); //修改日志路径 trtcCloud.setLogDirPath(string); | ||
Windows | //设置输出 Log 级别,最高级可关闭 getTRTCCloud()->setLogLevel(TRTC_LOG_LEVEL_DEBUG); //修改日志路径 getTRTCCloud()->setLogDirPath(const char * path); | ||
IMSDK | IM | iOS&Mac | @interface TIMSdkConfig : NSObject //本地写 log 文件的等级,最高级可关闭 @property(nonatomic,assign) TIMLogLevel logLevel; //log 文件路径,不设置时为默认路径 @property(nonatomic,retain) NSString * logPath; |
安卓 | //设置写日志等级,最高级可关闭 TIMSdkConfig setLogLevel(@NonNull TIMLogLevel logLevel) //设置日志路径,不设置时为默认路径 TIMSdkConfig setLogPath(@NonNull String logPath) | ||
Windows | static const char* kTIMSdkConfigConfigFilePath ="sdk_config_log_file_path" std::string json_init_cfg; Json::Value json_value_init; json_value_init[kTIMSdkConfigConfigFilePath] = path; TIMInit(sdk_app_id, json_value_init.toStyledString().c_str()); |
查看log文件
LiteAVSDK 为了减少 log 的存储体积,对本地存储的 log 文件做了加密,并且限制了 log 数量的大小,所以要查看 log 的文本内容,。
了解了日志文件的位置,下一步就是文件的打开。可以看到,直接在客户端提取的日志文件是.xlog后缀结尾的文件(文件名举例:LiteAV_20201008.xlog),直接用记事本打开是“乱码”,原因在于文件经过了加密,,下面简单讲解什么是xlog,为什么xlog不能直接阅读,以及如何解压xlog。
(1)什么是xlog
说起xlog文件,需要从mars看起,mars 是微信官方的终端基础组件,是一个使用 C 编写的业务性无关,平台性无关的基础组件。目前已接入微信 Android、iOS、Mac、Windows、WP 等客户端。现正在筹备开源中,它主要包括以下几个部分:
comm:可以独立使用的公共库,包括 socket、线程、消息队列等
xlog:可以独立使用的日志模块
sdt:可以独立使用的网络诊断模块
stn:可以独立使用的信令分发网路模块
跳过技术部分的balabala,之所以用xlog,是为了在兼顾流畅性 完整性 容错性的同时,达到极好的压缩率
(2)为什么xlog不能直接打开
原因当然是加密了,本文中不展开将加密算法,之所以用户发过来的xlog能打开,是因为加密“参数”是带的空参数,所以可以不带参解密
(3)如何打开xlog
解密xlog需要运行mars的解码程序,需要使用 log 解压缩工具,运行解压工具,需要在python2的环境中运行。
附解压脚本的使用命令:
python decode_mars_nocrypt_log_file.py LiteAV_20201008.xlog即可将xlog文件解码,生成一个后缀为.xlog.log的文件。
导出来就可以用记事本等文本编辑工具查看了。
PART2:日志文件上传腾讯云COS的一种实现方案
文章背景中有描述,一般情况向用户取日志往往比较难,建议开发过程中,将手机本地日志上传到自己的业务服务器活腾讯云cos存储等云存储。整体上传实现方案也很直接,将本地的日志文件,由客户主动或者被动触发,以文件的形式上传即可。
上传cos方式方法说明:
安卓端参考文档:https://cloud.tencent.com/document/product/436/46415
上传对象
COS的高级接口封装了简单上传、分块上传接口,根据文件大小智能的选择上传方式,同时支持续传功能。
示例代码一: 上传本地文件
代码语言:javascript复制// 初始化 TransferConfig,这里使用默认配置,如果需要定制,请参考 SDK 接口文档
TransferConfig transferConfig = new TransferConfig.Builder().build();
// 初始化 TransferManager
TransferManager transferManager = new TransferManager(cosXmlService,
transferConfig);
String bucket = "examplebucket-1250000000"; //存储桶,格式:BucketName-APPID
String cosPath = "exampleobject"; //对象在存储桶中的位置标识符,即称对象键
String srcPath = new File(context.getCacheDir(), "exampleobject")
.toString(); //本地文件的绝对路径
//若存在初始化分块上传的 UploadId,则赋值对应的 uploadId 值用于续传;否则,赋值 null
String uploadId = null;
// 上传文件
COSXMLUploadTask cosxmlUploadTask = transferManager.upload(bucket, cosPath,
srcPath, uploadId);
//设置上传进度回调
cosxmlUploadTask.setCosXmlProgressListener(new CosXmlProgressListener() {
@Override
public void onProgress(long complete, long target) {
// todo Do something to update progress...
}
});
//设置返回结果回调
cosxmlUploadTask.setCosXmlResultListener(new CosXmlResultListener() {
@Override
public void onSuccess(CosXmlRequest request, CosXmlResult result) {
COSXMLUploadTask.COSXMLUploadTaskResult cOSXMLUploadTaskResult =
(COSXMLUploadTask.COSXMLUploadTaskResult) result;
}
@Override
public void onFail(CosXmlRequest request,
CosXmlClientException clientException,
CosXmlServiceException serviceException) {
if (clientException != null) {
clientException.printStackTrace();
} else {
serviceException.printStackTrace();
}
}
});
//设置任务状态回调, 可以查看任务过程
cosxmlUploadTask.setTransferStateListener(new TransferStateListener() {
@Override
public void onStateChanged(TransferState state) {
// todo notify transfer state
}
});
说明:
·更多完整示例,请前往GitHub查看。
IOS端参考文档:https://cloud.tencent.com/document/product/436/46381
上传对象
腾讯云COS高级接口封装了简单上传、分块上传接口,根据文件大小智能的选择上传方式,同时支持续传功能。
示例代码一: 上传本地文件
Objective-C
代码语言:javascript复制QCloudCOSXMLUploadObjectRequest* put = [QCloudCOSXMLUploadObjectRequest new];
// 本地文件路径
NSURL* url = [NSURL fileURLWithPath:@"文件的URL"];
// 存储桶名称,格式为 BucketName-APPID
put.bucket = @"examplebucket-1250000000";
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "dir1/object1"
put.object = @"exampleobject";
// 需要上传的对象内容。可以传入NSData*或者NSURL*类型的变量
put.body = url;
// 监听上传进度
[put setSendProcessBlock:^(int64_t bytesSent,
int64_t totalBytesSent,
int64_t totalBytesExpectedToSend) {
// bytesSent 新增字节数
// totalBytesSent 本次上传的总字节数
// totalBytesExpectedToSend 本地上传的目标字节数
}];
// 监听上传结果
[put setFinishBlock:^(id outputObject, NSError *error) {
// 可以从 outputObject 中获取 response 中 etag 或者自定义头部等信息
NSDictionary * result = (NSDictionary *)outputObject;
}];
[put setInitMultipleUploadFinishBlock:^(QCloudInitiateMultipartUploadResult *
multipleUploadInitResult,
QCloudCOSXMLUploadObjectResumeData resumeData) {
// 在初始化分块上传完成以后会回调该 block,在这里可以获取 resumeData,uploadid
NSString* uploadId = multipleUploadInitResult.uploadId;
}];
[[QCloudCOSTransferMangerService defaultCOSTransferManager] UploadObject:put];
说明:
·更多完整示例,请前往GitHub查看。
·上传之后,您可以用同样的 Key 生成文件下载链接,具体使用方法见生成预签名链接文档。但注意如果您的文件是私有读权限,那么下载链接只有一定的有效期。
Swift
代码语言:javascript复制let put:QCloudCOSXMLUploadObjectRequest = QCloudCOSXMLUploadObjectRequest<AnyObject>();
// 存储桶名称,格式为 BucketName-APPID
put.bucket = "examplebucket-1250000000";
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "dir1/object1"
put.object = "exampleobject";
// 需要上传的对象内容。可以传入NSData*或者NSURL*类型的变量
put.body = NSURL.fileURL(withPath: "Local File Path") as AnyObject;
// 监听上传结果
put.setFinish { (result, error) in
// 获取上传结果
if let result = result {
// 文件的 etag
let eTag = result.eTag
} else {
print(error!);
}
}
// 监听上传进度
put.sendProcessBlock = { (bytesSent, totalBytesSent,
totalBytesExpectedToSend) in
// bytesSent 新增字节数
// totalBytesSent 本次上传的总字节数
// totalBytesExpectedToSend 本地上传的目标字节数
};
// 设置上传参数
put.initMultipleUploadFinishBlock = {(multipleUploadInitResult, resumeData) in
// 在初始化分块上传完成以后会回调该 block,在这里可以获取 resumeData,以及 uploadId
if let multipleUploadInitResult = multipleUploadInitResult {
let uploadId = multipleUploadInitResult.uploadId
}
}
QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(put);
说明:
·更多完整示例,请前往GitHub查看。
·上传之后,您可以用同样的 Key 生成文件下载链接,具体使用方法见生成预签名链接 文档。但注意如果您的文件是私有读权限,那么下载链接只有一定的有效期。