羽毛

V1

2022/04/14阅读:17主题:默认主题

北斗平台日志回捞

背景

客户端偶尔会发生某个页面打不开、Web或者RN白屏、分享失败等现象,由于Android碎片化、网络环境、机型ROM、操作系统版本、本地环境复杂多样,很难在本地复现这些场景,加上问题反馈的时候描述都比较模糊,很难快速定位并解决问题。

因此,我们开发了Tracker。我们希望能缩小业务问题的定位范围,如下图。帮我们抽丝剥茧,找到bug的蛛丝马迹,最终解决问题。

Tracker是一个自动采集日志库,帮助开发者自动采集日志,并赋能业务追踪问题,也可主动记录日志。通过主动上传、标记用户app启动上传回捞日志,在北斗平台展示并分析日志。

Tracker功能简介

日志采集流程

用户流程

日志上传方式有两种

  • 用户主动上传

上传日志页面SDK已经提供,接入方唤起即可使用。

  • 北斗平台标记用户

北斗平台标记,标记用户成功后,在应用重启时上传日志。

日志可视化分析

北斗平台

平台提供了筛选功能,方便你快速找到日志。

Tracker可解决的问题和诉求

如何快速辅助解决疑难问题,我们目前有一些方法,但是存在一些缺陷,也产生了强烈的诉求。

现有实现方案及弊端

  • 发临时包用户安装。弊端:用户配合过程繁琐,而且解决问题时间很长
  • QA尝试去复现问题。弊端:尝试已有机型发现个性化场景很难复现
  • 预先手动埋点回捞。弊端:覆盖范围有限,无法提前预知

诉求

  • 快速拿到线上日志
  • 不需要大量埋点甚至不埋点
  • 精准的问题现场日志

Tracker已有的能力

架构图

基于以上诉求,产生了Tracker,架构如如下:

我们借助wlog存储日志,在此基础自动采集多项日志,通过北斗平台回捞、分析展示日志。

自动采集日志

现在自动采集了10项日志,如下

Web深度定制化

  • 采集web加载过程的完成流程,包含WebView加载执行的各个函数回调;
  • 采集Web加载时的cookie及header;
  • 采集Web和Native相互间的通信(action的调用);
  • 采集webview的异常信息;
  • 采集webview的console输出;

web出问题一般较难排查,因为他是混合框架。问题可能在native,也可能在前端,希望通过以上日志,助你解决web相关问题。

RN深度定制化

  • 采集RN加载过程的完成流程,统计RN加载的各个关键路径;
  • 采集RN和Native相互间的通信(Module调用流程);
  • 采集RN的异常信息;

RN出问题跟web一样,因为他是混合框架,也很难排查。通过以上日志,可以助你发现RN相关问题。

运行环境采集

采集是否是双开运行app及设备相关信息(磁盘大小、可用空间、设备品牌等消息)。

页面跳转参数采集

监听Activty生命周期回调,采集页面的bundle参数,包括跳转协议。

原生界面生命周期

对activity和fragment的生命周期进行记录,默认记录全部(通过配置可关闭)。除了全局配置之外,可以对一些特定的activity或fragment进行重点观察,被重点观察的对象会进行全生命周期记录,设置方法为api参考接入流程。

原生View点击交互

目前只记录用户点击行为,无需特殊配置。当用户点击了这些view的时候,被记录的是这些字符串,具体如下:

View 记录信息
TextView 类全名、id、屏幕坐标、文字内容
ViewGroup 类全名、id、文字内容(递归寻找其子View中TextView的文字内容)
View 类全名、id、屏幕坐标

sdk中提供了一些默认的转换器将不同类型的view转换为可辨识的字符串,如需扩展,可以参考接入流程。

接口请求参数及返回的采集

现在大部分客户端网络请求都使用okhttp,我们也基于okhttp添加了拦截器,记录网络请求的request及response,使用者需要在代码主动添加拦截器。由于网络日志数量较多,如果全部监控会对日志体积影响较大,记录网络日志还需要主动开启网络日志记录开关。

客户端crash

自动捕捉异常并记录到日志,无需特殊配置,异常捕捉基于UncaughtExceptionHandler实现,内部使用代理模式,不会导致其他基于这种原理实现的功能模块失效,也不会导致互相引用造成的无限循环调用。

方法执行日志

对方法进行了插桩来记录方法执行路径,在方法的开头插入一段桩代码。由于日志量较多,只针对配置的包名进行插桩埋日志。

安全模式

安全模式是为了解决app在启动过程中崩溃导致无法上传日志而设计的,tracker SDK提供了Tracker.launchSuccess()方法标记本次启动成功,此方法如果不调用,会在3分钟后清理过期日志时自动被调用,如果app在标识启动成功之前崩溃,安全模式模块会在进程回收前捕捉异常,如果两次启动异常相同则认定为无法启动,再次启动会触发安全模式。

接入流程

  1. 在主项目的build.gradle中指定maven仓库地址
 allprojects {
     repositories {
         //指定maven仓库地址
         maven{
             url 'http://artifactory.58corp.com:8081/artifactory/android-local/'
         }
     }
 }
  1. 在app(需要引入的module)的build.gradle的dependencies中添加入依赖
 implementation "com.wuba.wuxian.sdk:tracker:$TrackerVersion"
  1. 代码中初始化,一般是在Application中初始化
   //初始化Tracker
   Tracker.init(context);
   
   //绑定用户,在北斗平台上标记该用户,app重启上传日志。
    Tracker.setIdentifyGetter(new Tracker.IStringGetter() {
            @Override
            public String[] getValue() {
                ArrayList<String> bindInfo =new ArrayList<>();
                String imei = TownDeviceInfoUtils.getImei(context);//用户imei
                bindInfo.add(imei);
                if(LoginClient.isLogin()){
                    bindInfo.add(LoginClient.getUserID());//用户id
                }
                return (String[]) bindInfo.toArray();
            }
        });
    //存储绑定信息,可以在用户登录、登出、用户隐私协议授权时机调用下,绑定用户信息。
    Tracker.refreshIdValue();

至此tracker已经接入完成,可以使用Tracker记录日志。并自动采集运行环境、页面跳转参数、原生界面生命周期、原生View点击交互、客户端crash。需要统计更详细的数据,请按一下步骤继续接入。

  1. 网络、RN、Web日志采集
//自动采集网络日志
OKHttpClientBuilder okHttpClientBuilder = xxx;
okHttpClientBuilder.setInterceptor(new TrackerNetInterceptor());

//自动采集RN相关日志
WubaRNManager.Initiater init = xxx;
init.setWubaRNConfig(new WubaRNConfig() {
    @Override
    protected IWubaRNLogHandler createWubaRNLogHandler() {
        return new IWubaRNLogHandler() {
            @Override
            public void writeLog(Class<?> clazz, Object... join) {
                TrackerWriteLogUtil.writeLog(com.wuba.tracker.Constant.RN_MODULE_NAME,clazz,join);
            }
        };
}}

//自动采集WEB相关日志
//Hybrid.Config的实现类中重写writeLog方法
override 
fun writeLog(clazz: Class<*>, vararg join: Any) {
    // 埋点日志
     TrackerWriteLogUtil.writeLog(Constant.WEB_MODULE_NAME,clazz,join)
}

  1. 方法执行日志接入
//在主项目的build.gradle,加入插件
dependencies {
  classpath 'com.wuba.wuxian.sdk:tracker-plugin:$TrackerVersion'
}
//在module的build.gradle,引入插件
apply plugin: 'om.wuba.wuxian.sdk.tracker.plugin'
  1. 日志开关控制

TrackerSwitch,它的值即控制tracker功能的开关。目前包含以下可选项,默认值只记录生命周期、点击事件、页面bundle参数。

  public static final int FLAG_NO_COMMON_LOG = -1;
  public static final int FLAG_LIFECYCLE = 1;//生命周期及页面bundle参数日志
  public static final int FLAG_EVENT = 1 << 1;//viw点击日志
  public static final int FLAG_NETWORK = 1 << 2;//网络日志
  public static final int FLAG_WEB = 1 << 3;//Web日志
  public static final int FLAG_RN = 1 << 4;//RN日志
  public static final int FLAG_EXCEPTION_HANDLER = 1 << 5;//crash日志
  public static final int FLAG_AUTO_METHOD = 1 << 6;//方法执行日志
  public static final int FLAG_ALL = FLAG_LIFECYCLE | FLAG_EVENT | FLAG_NETWORK | FLAG_WEB | FLAG_RN | FLAG_EXCEPTION_HANDLER | FLAG_AUTO_METHOD;//全日制标记
  public static final int FLAG_DEFAULT =  FLAG_LIFECYCLE | FLAG_EVENT;//默认记录日志标记
  

控制日志开关

//设置记录日志flag
TrackerSwitch.setFlag(int flag)
//也可以调用api控制记录各类日志
TrackerSwitch.openLifecycleLog()
TrackerSwitch.closeLifecycleLog()
TrackerSwitch.openEventLog()
TrackerSwitch.closeEventLog()
  1. 记录日志
 TrackerLogBuilder.create().setMsg().setCls().setMethod().setModule().setTag().openStackTrace().setLevel().setThrowable().log();
          

其中setMsg必填,其余选填。

为了增加日志的阅读性,通用日志我们使用以下日志格式: 【MSG、TAG、模块(RN/WEB/Tracker/)、类名、方法名、Throwable、方法堆栈】

已接入方

后续规划

明镜项目接入,对接各种性能指标。

分类:

前端

标签:

前端

作者介绍

羽毛
V1