关于android:滴滴开源的APM方案Dokit接入

6次阅读

共计 9617 个字符,预计需要花费 25 分钟才能阅读完成。

一、简介

DoKit 是一款面向泛前端产品研发全生命周期的效率平台,目前反对诸如 Android、iOS、小程序、Flutter 和 Web 等多个平台。并且,随着 dokit.cn 平台端的推出,也标记着 DoKit 曾经从单纯的效率工具正式进入了效率工具平台的阶段。与此同时,DoKit 还在一直的更新,以提供更多的实用功能。

目前,Dokit 提供的性能有:

平台工具(www.dokit.cn)

  1. 【数据 Mock】 App 接口 Mock 解决方案,提供一套基于 App 网络拦挡的接口 Mock 计划,无需批改代码即可实现对于接口数据的 Mock。
  2. 【衰弱体检】 一键式操作,整合 DoKit 多项工具,数据可视化,疾速精确定位问题,让你对 app 的性能一目了然。
  3. 【文件同步助手】 通过终端服务,让你的终端空间在平台端残缺的展示并提供弱小的文件以及数据库操作能力。
  4. 【一机多控】 主从同步,开释人力,让研发测试效率晋升看得见

常用工具

  1. 【App 信息查看】 疾速查看手机信息,App 根底信息、签名相干、权限信息的渠道,防止去手机设置查找或者查看我的项目源代码的麻烦;
  2. 【开发者选项 Android 特有】 一键跳转开发者选项,防止安卓因为平台差别导致的入口不统一
  3. 【本地语言】 一键跳转本地语言,防止安卓因为平台差别导致的入口不统一
  4. 【沙盒浏览】 App 外部文件浏览的性能,反对删除和预览, 并且能通过 AirDrop 或者其余分享形式上传到 PC 中,进行更加粗疏的操作;
  5. 【MockGPS】 App 能定位到全国各地,反对地图位置和手动输出经纬度;
  6. 【H5 任意门】 开发测试同学能够疾速输出 H5 页面地址,查看该页面成果;
  7. 【Crash 查看】 不便本地打印出呈现 Crash 的堆栈;
  8. 【子线程 UI】 疾速定位哪一些 UI 操作在非主线程中进行渲染,防止不必要的问题;(iOS 独有)
  9. 【革除本地数据】 一键删除沙盒中所有数据;
  10. 【NSLog】 把所有 NSLog 信息打印到 UI 界面,防止没有开发证书无奈调试的难堪;
  11. 【Lumberjack】 每一条 CocoaLumberjack 的日志信息,都在在 App 的界面中显示进去,再也不须要导出日志这么麻烦;(iOS 独有)
  12. 【DBView】 通过网页方便快捷的操作利用内数据库,让数据库的调试变得十分优雅;
  13. 【模仿弱网】 限度网速,模仿弱网环境下 App 的运行状况;(android 独有)
  14. 【JS 脚本】 在指定 WebView 运行 JS 脚本。(iOS 独有)

性能检测

  1. 【帧率】 App 帧率信息提供波形图查看性能,让帧率监控的趋势更加显著;
  2. 【CPU】 App CPU 使用率信息提供波形图查看性能,让 CPU 监控的趋势更加形象;
  3. 【内存】 App 内存使用量信息提供波形图查看性能,让内存监控的趋势更加显明;
  4. 【流量监控】 拦挡 App 外部流量信息,提供波形图展现、流量概要展现、流量列表展现、流量筛选、流量详情,对流量信息对立拦挡,成为咱们 App 中自带的 “Charles”;
  5. 【卡顿】 锁定 App 呈现卡顿的时刻,打印出对应的代码调用堆栈;
  6. 【大图检测】 通过流量监测,找出所有的大小超标的图片,防止下载大图造成的流量节约和渲染大图带来的 CPU 耗费。
  7. 【启动耗时】 无侵入的统计出 App 启动过程的总共耗时;
  8. 【UI 层级查看】 查看出每一个页面中层级最深的元素;
  9. 【函数耗时】 从函数级别剖析 app 性能瓶颈;
  10. 【Load】 找出所有的 Load 办法,并给出耗时剖析;(iOS 独有)
  11. 【内存透露】 找出 App 中所有的内存透露的问题。

视觉工具

  1. 【色彩吸管】 不便设计师 UI 捉虫的时候,查看每一个组件的色彩值是否设置正确;
  2. 【组件查看】 能够抓取任意一个 UI 控件,查看它们的详细信息,包含控件名称、控件地位、背景色、字体色彩、字体大小;
  3. 【对齐标尺】 参考 Android 零碎自带测试工具,可能实时捕捉屏幕坐标,并且能够查看组件是否对齐;
  4. 【元素边框线】 绘制出每一个 UI 组件的边框,对于组件布局有肯定的参考意义。

Weex 专项工具(CML 专项工具)

  1. 【console 日志查看】 不便在端上查看每一个 Weex 文件中的 console 日志,提供分级和搜寻性能;
  2. 【storage 缓存查看】 将 Weex 中的 storage 模块的本地缓存数据可视化展现;
  3. 【容器信息】 查看每一个关上的 Weex 页面的根本信息和性能数据;
  4. 【DevTool】 疾速开启 Weex DevTool 的扫码入口。

二、疾速接入

对于 Android、iOS 接入 Dokit,官网具体的接入文档。

接入步骤

1. Gradle 依赖

首先,咱们关上 app/build.gradle 文件,而后增加如下依赖:

dependencies {debugImplementation 'io.github.didi.dokit:dokitx:${lastversion}'
    releaseImplementation 'io.github.didi.dokit:dokitx-no-op:${lastversion}'
}

如果对版本不是很分明,能够关上上面的链接进行查看:Android Releases 版本

滴滴外部业务:

滴滴外部业务线接入请增加模块

// 数据 mock 外部网络库反对
debugImplementation 'io.github.didi.dokit:dokitx-rpc:${lastversion}'
// 一机多控外部网络库反对
debugImplementation 'io.github.didi.dokit:dokitx-rpc-mc:${lastversion}'

最新版本参见这里。
须要阐明的是,如果应用最新的版本,那么须要将你我的项目的 gradle 版本改为 6.8 版本以上,最好是 7.0 以上的版本。能够关上 gradle-wrapper.properties 文件进行批改。

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
2. 初始化

在 App 启动的时候进行初始化。

overide fun onCreate() {DoKit.Builder(this)
            .productId("须要应用平台性能的话,须要到 dokit.cn 平台申请 id")
            .build()} 
3. 流量监控以及其余 AOP 性能(可选)

AOP 包含以下几个性能:
1)百度、腾讯、高德地图的经纬度模仿
2)UrlConnection、Okhttp 抓包以及后续的接口 hook 性能
3)App 启动耗时统计
4) 慢函数
5) 大图

在我的项目的 build.gradle 中增加 classpath。

buildscript {
    dependencies {classpath 'io.github.didi.dokit:dokitx-plugin:${lastversion}'
    }
}

在 app 的 build.gradle 中增加 plugin。

apply plugin: 'com.didi.dokit'

插件配置选项:
增加到 app module 的 build.gradle 文件下 与 android {}处于同一级

dokitExt {
    // 通用设置
    comm {
        // 地图经纬度开关
        gpsSwitch true
        // 网络开关
        networkSwitch true
        // 大图开关
        bigImgSwitch true
        //webView js 抓包
        webViewSwitch true
    }

    slowMethod {
        // 调用栈模式配置 对应 gradle.properties 中 DOKIT_METHOD_STRATEGY=0
        stackMethod {
            // 默认值为 5ms 小于该值的函数在调用栈中不显示
            thresholdTime 10
            // 调用栈函数入口 千万不要用我默认的配置 如果有非凡需要批改成我的项目中本人的入口 如果不须要能够去掉该字段
            enterMethods = ["com.didichuxing.doraemondemo.MainDebugActivity.test1"]
            // 黑名单 粒度最小到类 暂不反对到办法  千万不要用我默认的配置 如果有非凡需要批改成我的项目中本人的入口 如果不须要能够去掉该字段
            methodBlacklist = ["com.facebook.drawee.backends.pipeline.Fresco"]
        }
        // 一般模式配置 对应 gradle.properties 中 DOKIT_METHOD_STRATEGY=1
        normalMethod {
            // 默认值为 500ms 小于该值的函数在运行时不会在控制台中被打印
            thresholdTime 500
            // 须要针对函数插装的包名 千万不要用我默认的配置 如果有非凡需要批改成我的项目中本人的我的项目包名 如果不须要能够去掉该字段
            packageNames = ["com.didichuxing.doraemondemo"]
            // 不须要针对函数插装的包名 & 类名 千万不要用我默认的配置 如果有非凡需要批改成我的项目中本人的我的项目包名 如果不须要能够去掉该字段
            methodBlacklist = ["com.didichuxing.doraemondemo.dokit"]
        }
    }
}

其中 strategymethodSwitch配置项曾经弃用。新的配置开关位于我的项目根目录下的 gradle.properties 中。

具体的配置如下所示:

// dokit 全局配置
// 插件开关
DOKIT_PLUGIN_SWITCH=true
// DOKIT 读取三方库会和 booster 抵触 如果你的我的项目中也集成了 booster 倡议将开关改成 false
DOKIT_THIRD_LIB_SWITCH=true
// 插件日志
DOKIT_LOG_SWITCH=true
// 自定义 Webview 的全限定名 次要是作用于 h5 js 抓包和数据 mock
DOKIT_WEBVIEW_CLASS_NAME=com/didichuxing/doraemonkit/widget/webview/MyWebView
// dokit 慢函数开关
DOKIT_METHOD_SWITCH=true
// dokit 函数调用栈层级
DOKIT_METHOD_STACK_LEVEL=4
// 0: 默认模式 打印函数调用栈 需增加指定入口  默认为 application onCreate 和 attachBaseContext
// 1: 一般模式 运行时打印某个函数的耗时 全局业务代码函数插入
DOKIT_METHOD_STRATEGY=0

理由 :
为了缩小我的项目的编译工夫,所以慢函数的默认开关为 false。再加上 plugin 的 transform 注册必须早于 project.afterEvaluate。所以无奈通过原先的配置项拿到配置信息,只能通过在全局的 gradle.properties 中的配置能够拿到。

tips:
当批改完 DoKit 插件的相干配置当前肯定要 clean 一下从新编译能力失效。这是 AS 的缓存增量编译导致的,临时没有其余好的解决方案。

4. 自定义性能组件(可选)

自定义组件须要实现 IKit 接口,该接口对应哆啦 A 梦性能面板中的组件。

以代驾乘客端为例,实现环境切换组件如下。

class DemoKit : AbstractKit() {
    override val category: Int
        get() = Category.BIZ
    override val name: Int
        get() = R.string.dk_kit_demo
    override val icon: Int
        get() = R.mipmap.dk_sys_info

    override fun onClickWithReturn(activity: Activity): Boolean {SimpleDoKitStarter.startFloating(DemoDokitView::class.java)
        return true
    }

    override fun onAppInit(context: Context?) {}}

在初始化的时候注册自定义组件。

override fun onCreate() {DoKit.Builder(this)
            .productId("须要应用平台性能的话,须要到 dokit.cn 平台申请 id")
        .customKits(mapKits)
            .build()}

DoKit 入口 api

public class DoKit private constructor() {
    companion object {
        


        /**
         * 主 icon 是否处于显示状态
         */
        @JvmStatic
        val isMainIconShow: Boolean
            get() = false


        /**
         * 显示主 icon
         */
        @JvmStatic
        fun show() {}

        /**
         * 间接显示工具面板页面
         */
        @JvmStatic
        fun showToolPanel() {}

        /**
         * 间接暗藏工具面板
         */
        @JvmStatic
        fun hideToolPanel() {}

        /**
         * 暗藏主 icon
         */
        @JvmStatic
        fun hide() {}

        /**
         * 启动悬浮窗
         * @JvmStatic: 容许应用 java 的静态方法的形式调用
         * @JvmOverloads : 在有默认参数值的办法中应用 @JvmOverloads 注解,则 Kotlin 就会裸露多个重载办法。*/
        @JvmStatic
        @JvmOverloads
        fun launchFloating(
            targetClass: Class<out AbsDokitView>,
            mode: DoKitViewLaunchMode = DoKitViewLaunchMode.SINGLE_INSTANCE,
            bundle: Bundle? = null
        ) { }


        /**
         * 启动悬浮窗
         * @JvmStatic: 容许应用 java 的静态方法的形式调用
         * @JvmOverloads : 在有默认参数值的办法中应用 @JvmOverloads 注解,则 Kotlin 就会裸露多个重载办法。*/
        @JvmStatic
        @JvmOverloads
        fun launchFloating(
            targetClass: KClass<out AbsDokitView>,
            mode: DoKitViewLaunchMode = DoKitViewLaunchMode.SINGLE_INSTANCE,
            bundle: Bundle? = null
        ) { }

        /**
         * 移除悬浮窗
         * @JvmStatic: 容许应用 java 的静态方法的形式调用
         * @JvmOverloads : 在有默认参数值的办法中应用 @JvmOverloads 注解,则 Kotlin 就会裸露多个重载办法。*/
        @JvmStatic
        fun removeFloating(targetClass: Class<out AbsDokitView>) { }

        /**
         * 移除悬浮窗
         * @JvmStatic: 容许应用 java 的静态方法的形式调用
         * @JvmOverloads : 在有默认参数值的办法中应用 @JvmOverloads 注解,则 Kotlin 就会裸露多个重载办法。*/
        @JvmStatic
        fun removeFloating(targetClass: KClass<out AbsDokitView>) { }

        /**
         * 移除悬浮窗
         * @JvmStatic: 容许应用 java 的静态方法的形式调用
         * @JvmOverloads : 在有默认参数值的办法中应用 @JvmOverloads 注解,则 Kotlin 就会裸露多个重载办法。*/
        @JvmStatic
        fun removeFloating(dokitView: AbsDokitView) { }


        /**
         * 启动全屏页面
         * @JvmStatic: 容许应用 java 的静态方法的形式调用
         * @JvmOverloads : 在有默认参数值的办法中应用 @JvmOverloads 注解,则 Kotlin 就会裸露多个重载办法。*/
        @JvmStatic
        @JvmOverloads
        fun launchFullScreen(
            targetClass: Class<out BaseFragment>,
            context: Context? = null,
            bundle: Bundle? = null,
            isSystemFragment: Boolean = false
        ) { }

        /**
         * 启动全屏页面
         * @JvmStatic: 容许应用 java 的静态方法的形式调用
         * @JvmOverloads : 在有默认参数值的办法中应用 @JvmOverloads 注解,则 Kotlin 就会裸露多个重载办法。*/
        @JvmStatic
        @JvmOverloads
        fun launchFullScreen(
            targetClass: KClass<out BaseFragment>,
            context: Context? = null,
            bundle: Bundle? = null,
            isSystemFragment: Boolean = false
        ) { }


        @JvmStatic
        fun <T : AbsDokitView> getDoKitView(
            activity: Activity?,
            clazz: Class<out T>
        ): T? {return null}

        @JvmStatic
        fun <T : AbsDokitView> getDoKitView(
            activity: Activity?,
            clazz: KClass<out T>
        ): T? {return null}

        /**
         * 发送自定义一机多控事件
         */
        @JvmStatic
        fun sendCustomEvent(
            eventType: String,
            view: View? = null,
            param: Map<String, String>? = null
        ) { }
        /**
         * 获取一机多控类型
         */
        @JvmStatic
        fun mcMode(): WSMode {return WSMode.UNKNOW}
    }


    class Builder(private val app: Application) {
        private var productId: String = ""
        private var mapKits: LinkedHashMap<String, List<AbstractKit>> = linkedMapOf()
        private var listKits: List<AbstractKit> = arrayListOf()

        init { }

        fun productId(productId: String): Builder {return this}

        /**
         * mapKits & listKits 二选一
         */
        fun customKits(mapKits: LinkedHashMap<String, List<AbstractKit>>): Builder {return this}

        /**
         * mapKits & listKits 二选一
         */
        fun customKits(listKits: List<AbstractKit>): Builder {return this}

        /**
         * H5 任意门全局回调
         */
        fun webDoorCallback(callback: WebDoorManager.WebDoorCallback): Builder {return this}

        /**
         * 禁用 app 信息上传开关,该上传信息只为做 DoKit 接入量的统计,如果用户须要爱护 app 隐衷,可调用该办法进行禁用
         */
        fun disableUpload(): Builder {return this}

        fun debug(debug: Boolean): Builder {return this}

        /**
         * 是否显示主入口 icon
         */
        fun alwaysShowMainIcon(alwaysShow: Boolean): Builder {return this}

        /**
         * 设置加密数据库明码
         */
        fun databasePass(map: Map<String, String>): Builder {return this}

        /**
         * 设置文件治理助手 http 端口号
         */
        fun fileManagerHttpPort(port: Int): Builder {return this}

        /**
         * 一机多控端口号
         */
        fun mcWSPort(port: Int): Builder {return this}

        /**
         * 一机多控自定义拦截器
         */
        fun mcClientProcess(interceptor: McClientProcessor): Builder {return this}

        /**
         * 设置 dokit 的性能监控全局回调
         */
        fun callBack(callback: DoKitCallBack): Builder {return this}


        /**
         * 设置扩大网络拦截器的代理对象
         */
        fun netExtInterceptor(extInterceptorProxy: DokitExtInterceptor.DokitExtInterceptorProxy): Builder {return this}


        fun build() {}
    }
}

开启插件调试的命令如下:

./gradlew :app:assembleDebug -Dorg.gradle.daemon=false -Dorg.gradle.debug=true

三、接入版本阐明

lastversion:3.5.0;kotlin 编译插件为 1.4.32;反对 Gradle 6.8 及以上
lastversion:3.5.0.1;kotlin 编译插件为 1.3.72;反对 Gradle 6.8 及以下

DoKit 最新版本 形容
3.3.5 及当前的 Androidx debugImplementation “io.github.didi.dokit:${aarName}: ${lastversion}” (1)dokitx 的 library 和 plugin 的 groupId 及版本号须要保持一致;(2)AGP 最低版本要求 3.3.0+
3.3.5 及以前的 Androidx 版本 debugImplementation “com.didichuxing.doraemonkit:${aarName}:3.3.5” (1)dokitx 的 library 和 plugin 的 groupId 及版本号须要保持一致;(2)AGP 最低版本要求 3.3.0+
反对 android support debugImplementation “com.didichuxing.doraemonkit:${aarName}:3.3.5” support 放弃更新,请大家尽快降级和适配 Androidx

${aarName}须要改为指定的名称,参考如下:

// 外围模块

debugImplementation "io.github.didi.dokit:dokitx:${lastversion}"

// 文件同步模块

debugImplementation "io.github.didi.dokit:dokitx-ft:${lastversion}"

// 一机多控模块

debugImplementation "io.github.didi.dokit:dokitx-mc:${lastversion}"

//weex 模块

debugImplementation "io.github.didi.dokit:dokitx-weex:${lastversion}"

//no-op 模块

releaseImplementation "io.github.didi.dokit:dokitx-no-op:${lastversion}"
  • debugImplementation 须要依据本人的构建改成对应的 productFlavor
  • ** 上面所有的例子均用 dokitx 举例。要应用 support 版本请将 dokitx 改为 dokit 即可。
    v3.3.5 当前的版本须要增加 mavenCentral()仓库 **

源码链接:https://github.com/didi/DoKit

正文完
 0