360 Argus APM 源码分析(4)—— argus-apm-okhttp源码分析

Android代码-ArgusAPM 360开源又一力作——ArgusAPM移动性能监控平台 项目背景 ArgusAPM是360手机卫士客户端团队继RePlugin之后开源的又一个重量级开源项目。ArgusAPM是360移动端产品使用的可视化性能监控平台,为移动端APP提供性能监控与管理,可以迅速发现和定位各类APP性能和使用问题,帮助APP不断的提升用户体验。 产品价值 实时掌控应用性能 降低性能定位成本 有效提升用户体验 监控模块 ArgusAPM目前支持如下性能指标: 交互分析:分析Activity生命周期耗时,帮助提升页面打开速度,优化用户UI体验 网络请求分析:监控流量使用情况,发现并定位各种网络问题 内存分析:全面监控内存使用情况,降低内存占用 进程监控:针对多进程应用,统计进程启动情况,发现启动异常(耗电、存活率等) 文件监控:监控APP私有文件大小/变化,避免私有文件过大导致的卡顿、存储空间占用等问题 卡顿分析:监控并发现卡顿原因,代码堆栈精准定位问题,解决明显的卡顿体验 ANR分析:捕获ANR异常,解决APP的“未响应”问题 ArgusAPM特性 非侵入式 ​ 无需修改原有工程结构,无侵入 立即下载

argus-apm-okhttp源码分析

  • OkHttp3Aspect类
    OkHttp3Aspect类是OKHTTP3的切面文件。
@Aspect
public class OkHttp3Aspect {

    @Pointcut("call(public okhttp3.OkHttpClient build())")
    public void build() {

    }

    @Around("build()")
    public Object aroundBuild(ProceedingJoinPoint joinPoint) throws Throwable {
        Object target = joinPoint.getTarget();

        if (target instanceof OkHttpClient.Builder && Client.isTaskRunning(ApmTask.TASK_NET)) {
            OkHttpClient.Builder builder = (OkHttpClient.Builder) target;
            builder.addInterceptor(new NetWorkInterceptor());
        }

        return joinPoint.proceed();
    }
}

相对于TraceNetTrafficMonitor,OkHttp3Aspect的代码明显要简单很多。这是否从另一方面印证了框架的强大?要对它做些手脚都这么方便。后边还会看到,对OKHttp还能收集到比HttpClient和HttpURLconnection更多的数据。

build()定义了切点,很简单,就是okhttp3.OkHttpClient的build方法被调用的点。
aroundBuild上的注解是Around,意味着要在切点前后都织入代码。首先获得切点的target,如果target是OkHttpClient.Builde类型,并且ApmTask.TASK_NET类型的任务正在运行,要给target添加一个NetWorkInterceptor的拦截器。当然,不要忘了joinPoint.proceed()执行原始代码。发现只有切点前需要织入代码,貌似应该用before就够了呀?但是我们这里需要ProceedingJoinPoint参数来获取target。
NetWorkInterceptor类都做了些什么事呢?

public class NetWorkInterceptor implements Interceptor {

    private static final String TAG = Env.TAG;

    private OkHttpData mOkHttpData;

    public NetWorkInterceptor() {
    }

    @Override
    public Response intercept(Chain chain) throws IOException {

        long startNs = System.currentTimeMillis();

        mOkHttpData = new OkHttpData();
        mOkHttpData.startTime = startNs;

        if (Env.DEBUG) {
            Log.d(TAG, "okhttp request 开始时间:" + mOkHttpData.startTime);
        }

        Request request = chain.request();

        recordRequest(request);

        Response response;

        try {
            response = chain.proceed(request);
        } catch (IOException e) {
            if (Env.DEBUG) {
                e.printStackTrace();
                Log.e(TAG, "HTTP FAILED: " + e);
            }
            throw e;
        }

        mOkHttpData.costTime = System.currentTimeMillis() - startNs;

        if (Env.DEBUG) {
            Log.d(TAG, "okhttp chain.proceed 耗时:" + mOkHttpData.costTime);
        }

        recordResponse(response);

        if (Env.DEBUG) {
            Log.d(TAG, "okhttp chain.proceed end.");
        }

        DataRecordUtils.recordUrlRequest(mOkHttpData);
        return response;
    }

    /**
     * request
     */
    private void recordRequest(Request request) {
        if (request == null || request.url() == null || TextUtils.isEmpty(request.url().toString())) {
            return;
        }

        mOkHttpData.url = request.url().toString();

        RequestBody requestBody = request.body();
        if (requestBody == null) {
            mOkHttpData.requestSize = request.url().toString().getBytes().length;
            if (Env.DEBUG) {
                Log.d(TAG, "okhttp request 上行数据,大小:" + mOkHttpData.requestSize);
            }
            return;
        }

        long contentLength = 0;
        try {
            contentLength = requestBody.contentLength();
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (contentLength > 0) {
            mOkHttpData.requestSize = contentLength;
        } else {
            mOkHttpData.requestSize = request.url().toString().getBytes().length;
        }
    }

    /**
     * 设置 code responseSize
     */
    private void recordResponse(Response response) {
        if (response == null) {
            return;
        }

        mOkHttpData.code = response.code();

        if (Env.DEBUG) {
            Log.d(TAG, "okhttp chain.proceed 状态码:" + mOkHttpData.code);
        }

        if (!response.isSuccessful()) {
            return;
        }

        ResponseBody responseBody = response.body();
        if (responseBody == null) {
            return;
        }

        long contentLength = responseBody.contentLength();

        if (contentLength > 0) {
            if (Env.DEBUG) {
                Log.d(TAG, "直接通过responseBody取到contentLength:" + contentLength);
            }
        } else {
            BufferedSource source = responseBody.source();
            if (source != null) {
                try {
                    source.request(Long.MAX_VALUE);
                } catch (IOException e) {
                    e.printStackTrace();
                }

                Buffer buffer = source.buffer();
                contentLength = buffer.size();

                if (Env.DEBUG) {
                    Log.d(TAG, "通过responseBody.source()才取到contentLength:" + contentLength);
                }
            }
        }

        mOkHttpData.responseSize = contentLength;

        if (Env.DEBUG) {
            Log.d(TAG, "okhttp 接收字节数:" + mOkHttpData.responseSize);
        }
    }
}

我们看一下拦截器的intercept方法。首先记录一下startNs,mOkHttpData是OkHttpData的一个实例,这个类里会记录请求的url,请求体积,响应体积,请求开始时间,请求消耗时间,以及http返回码。mOkHttpData的startTime就是startNs。通过recordRequest方法对原始的请求做处理之后,发送请求,返回结果保存到response。mOkHttpData的costTime就是此时的时间减去startNs。通过recordResponse处理response。最后,DataRecordUtils.recordUrlRequest(mOkHttpData)保存所有请求相关的数据。
recordRequest函数首先从request中获取请求的url,保存到mOkHttpData的url中。从request中获取requestBody,如果requestBody为空,就把请求的url的length作为requestBody的requestSize,然后直接返回。如果requestBody不为空,获取rqeustBody的contentLength,如果conetentLength大于0,就把contentLength作为mOkHttpData的requestSize,否则,还是把请求url的长度作为mOkHttpData的requestSzie的值。
recordResponse方法首先获取response的code,保存到mOkHttpData的code中。如果请求不成功(code不是2xx),到这里就直接返回了。如果请求成功,获取响应的reqsponseBody,如果responseBody为空,就直接返回;如果不为空,获取responseBody的contentLength,如果contentLength大于0的话,contentLength的长度作为mOkHttpData中responseSize的值。如果contentLength的长度等于0,获取responseBody的BufferedSource,source.request发送请求之后,获取source的buffer,并且把buffer的size作为mOkHttpData的responseSzie。
DataRecordUtils的recordUrlRequest函数只有依据,就是调用QOKHttp.recordUrlRequest(okHttpData.url, okHttpData.code, okHttpData.requestSize,
okHttpData.responseSize, okHttpData.startTime, okHttpData.costTime)
这个方法,生成一个NetInfo的对象,设置好各个字段之后,保存到本地数据库之中。

Argus, 时间序列监控与报警平台.zip Argus, 时间序列监控与报警平台 Argus是一个时间序列监控与报警。 它包括用于配置警报。收集和转换度量&事件。发送通知。创建命名空间和执行策略和配额。它的体系结构允许任何和所有这些服务重新定位到新技术,而不会影响用户。要了解更多的,请查看并查看发 立即下载

相关推荐

360ArgusAPM:奇虎360 Argus APM android sdk源代码解读

360ArgusAPM 奇虎360 Argus APM android sdk源代码解读

探索高效性能监控:ArgusAPM移动性能监控平台

在移动应用的开发与维护过程中,性能问题往往是影响用户体验的关键因素。360公司推出的ArgusAPM移动性能监控平台,正是为了解决这一痛点而生。本文将深入介绍ArgusAPM的核心功能、技术架构及其应用场景,帮助开发者更好地理解和利用这一强大的工具。 ## 项目介绍 ArgusAPM是360手机卫士客户端团队继RePlugin之后推出的又一开源力作。作为一个移动端产品的可视化性能监控平台,Ar...

gitblog_00026的博客 1155

DDR ECC错误注入与寄存器配置实战指南

本文详细介绍了DDR ECC错误注入的核心价值与实战操作指南,包括通过FI_Dx和FI_ECC寄存器注入数据与ECC错误的方法。文章提供了环境准备、寄存器配置、错误检测及系统可靠性测试策略,帮助开发者验证内存系统的纠错能力和可靠性,提升硬件开发的稳定性与效率。

nnn11的博客 1104

ArgusAPM 开源项目指南

**ArgusAPM** 是由360手机卫士团队开发的移动端性能监控平台,旨在帮助开发者实时监测和诊断应用程序的性能问题。这个开源项目是非侵入式的,允许开发者在不改变原有工程结构的情况下轻松接入,其特性包括UI性能、网络性能、内存、进程、文件、卡顿和ANR等多维度的监控,以提升用户体验。 ### 主要特点 - **非侵入式**:无须修改代码,低接入成本。 - **无性能损耗**:优化采集机制,...

gitblog_00233的博客 991

HFSS实战(三)——过孔via TDR仿真

在上一讲中,主要是通过观察S参数确定via的优化是否达到目标。但S参数只能看到一个整体的结果,并不知道via真实的阻抗是多少?想要单独确定via的阻抗,最好还是通过TDR的仿真。

luohuo9844的博客 1万+

SAP BTP-Cloud foundry 构建并部署JAVA应用程序

本文为 SAP BTP Java 应用程序的简单实例, 我们可以用此实例来熟悉SAP BTP 中的java应用开开发流程.在你完成改示例java应用程序以后, 我们可以直接使用该java应用程序进行后续的开发流程, 或直接构建一个新的JAVA应用程序来支持新的业务开发。

seyafly的博客 803

终极性能对比:Qwen3.6-35B-A3B-FP8与其他开源大模型的基准测试

Qwen3.6-35B-A3B-FP8是通义千问团队推出的最新一代开源大型语言模型,采用了先进的FP8量化技术和混合专家架构。这款模型在保持接近原始模型性能的同时,大幅降低了存储和推理成本,为开发者和研究者提供了高效的大语言模型解决方案。🔍 ## 📊 模型架构与技术创新 Qwen3.6-35B-A3B-FP8采用了创新的混合专家架构,拥有256个专家,每个token激活8个专家。模型支持长

gitblog_00051的博客 645

AirSim安装和地图加载

详细教程如何安装AirSim并加载地图

fegxg的博客 3033

推荐:ArgusAPM - 移动性能监控的强大工具

ArgusAPM是由360手机卫士团队倾力打造的一款强大的移动性能监控平台,旨在协助开发者实时监测和管理APP性能,以提高用户的使用体验。这个开源项目已经在多个360产品中得到成功应用,包括手机卫士、清理大师等,现面向全球开发者开放。 ## 项目技术分析 ### 非侵入式设计 ArgusAPM的非侵入式设计允许您无需改动现有代码结构即可轻松接入,极大地降低了接入成本。 ### AOP与Gr...

gitblog_00072的博客 592

使用 MATLAB/Simulink 构建一个多时间尺度下的微电网经济运行优化策略模型

本文介绍了基于Simulink的多能互补微电网系统建模方法,重点关注多时间尺度下的经济运行优化策略。内容包括:系统背景与目标、微电网结构设计(光伏、风电、储能、柴油发电机等模块)、多时间尺度能量管理架构(日前优化、日内滚动优化、实时控制)的实现步骤,以及仿真运行与结果分析。教程详细说明了如何在Simulink中调用优化算法,设置仿真参数,并提供了进阶研究方向和资源推荐。该模型为研究微电网的经济运行和智能调度提供了完整的仿真平台解决方案。

amy_mhd的博客 172

基于BQ25895RTWR的锂电池充电管理硬件设计

BQ25895 是一款适用于单节锂离子电池和锂聚合物电池的高度集成型 5A 开关模式电池充电管理和系统电源路径管理器件。此类器件支持高输入电压快速充电。低阻抗电源路径对开关模式运行效率进行了优化、缩短了电池充电时间并延长了放电阶段的电池使用寿命。• 移动电源、移动 Wi-Fi 热点。• 便携式互联网器件。

corlin6688的博客 1087

卡顿监测 · 方案篇 · Android卡顿监测指导原则

什么是卡顿?Android5.0及以上系统中,如果主线程 + 渲染线程每一帧的执行都超过 16.6ms(60fps 的情况下),那么就可能会出现掉帧,这就是我们俗称的卡顿。什么是卡死?如果界面线程被阻塞超过几秒钟时间,那么用户可能会看到ANR对话框,这就是我们俗称的卡死。当测试提出卡顿问题,测试会新建Bug单给责任人处理。导致卡顿的原因有很多,比如函数非常耗时、I/O 非常慢、线程或锁间竞争等。随着移动端用户越来越注重产品体验,APM系统也逐渐成为互联网公司重要基础设施。

BASK2311的博客 2250

【OS】AUTOSAR OS Alarm实现原理

AUTOSAR OS Alarm实现原理

qq_36056498的博客 1022

360Apm源码解析

360Apm 是什么? 如何收集卡顿(block)信息? 如何收集Okhttp信息? 如何收集帧(fps)信息? 如果收集Activity信息? 如果收集内存信息? 开源框架学习总结: 1.学到一些新的思路。 2.学到一些新的设计模式。 3.扩展知识面 4.学以致用,自己以后有其他的想法,会这个技术,就可以写开源框架。 ...

男儿不展风云志,空有天生八尺躯 1296

鲁棒优化 (Robust Optimization) 算法详解及案例分析

鲁棒优化是一种用于处理不确定性优化问题的方法。其目标是在不确定性参数的可能取值范围内,找到一个对不确定性具有鲁棒性的解。

闲人编程的博客 4330

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Android apm监控框架,移动性能监控 SDK 详细集成文档

移动性能监控 SDK 详细集成文档一. Gradle配置在 Project 的 build.gradle 文件中添加ArgusAPM的相关配置,示例如下:在项目根目录的 build.gradle(注意:不是 app/build.gradle) 中添加以下配置:buildscript {repositories {jcenter()}dependencies {classpath 'com.andr...

weixin_34368102的博客 883

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

如何开发ATC_MiThermometer扩展功能:完整开发者指南

ATC_MiThermometer是一款针对小米温湿度计的开源固件项目,允许开发者自定义设备功能、优化性能并添加新特性。本指南将带你从环境搭建到功能调试,一步步掌握扩展开发的核心技能,即使是新手也能快速上手。 ## 准备开发环境:从克隆到编译 ### 1. 获取项目源码 首先需要克隆官方仓库到本地开发环境: ```bash git clone https://gitcode.com/gh_mi

gitblog_01147的博客 535

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

ArgusAPM 源码解析与学习

ArgusAPM 移动性能监控平台是 360 开源的一款 APM 监测工具。 目前已经停止免费的服务端接入,但是对于我们从客户端的角度来搭建 监测还是有不错的学习参照意义。目前支持如下性能指标:本文也将围绕 总体框架和支持的功能点进行分析。项目分为三个目录,分别是:工程定义了一个名为 的 ,主要有以下两个作用:关于实现一个 的过程这里就不赘述了,下面看一下整体的框架。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vt1jfbtf-1655453421261)(https:/

m0_56255097的博客 919

360 Argus APM 源码分析(2)—— argus-apm-gradle源码分析

argus-apm-gradle源码分析 argus-apm-gradle工程定义了一个gradle plugin,主要有以下两个作用: 支持AOP编程,方便ArgusAPM能够在编译期织入一些性能采集的代码; 通过Gradle插件来管理依赖库,使用户接入ArgusAPM更简单。 argus-apm-gradle使用kotlin语言开发。这里我们假定大家已经熟悉gradle plugin的开发...

hunter800421的专栏 1630

360 重磅开源性能监控平台 ArgusAPM

12 月 16 日,在 360 移动性能开放日上,360 手机卫士技术架构负责人卜云涛向我们介绍了 360 最新开源的性能监控平台 ArgusAPM。ArgusAPM 是 360 手机卫士客户端团队继 RePlugin 之后开源的又一个重量级开源项目。ArgusAPM 是 360 移动端产品使用的可视化性能监控平台,为移动端 APP 提供性能监控与管理,可以迅速发现和定位各类 APP 性能和使用问...

weixin_33816821的博客 693

革命性Android性能监控平台ArgusAPM:一站式解决移动应用性能难题

ArgusAPM是一款功能强大、全面的Android应用性能管理平台,作为360线上移动性能检测平台,它能够帮助开发者全方位监控应用性能,及时发现并解决性能问题,提升用户体验。 ## 为什么选择ArgusAPM? 在移动应用开发中,性能问题往往直接影响用户体验和应用口碑。ArgusAPM作为一款专业的Android性能监控平台,凭借其强大的功能和便捷的使用方式,成为开发者的得力助手。它能够实时

gitblog_00804的博客 834

ANR及卡顿体验优化

性能优化:Android及卡顿体验优化

wzj_what_why_how的博客 1618

360 Argus APM 源码分析(3)—— argus-apm-aop源码分析

argus-apm-aop源码分析 argus-apm-aop主要实现了面向Activity的切面和面向HttpClient和URLConnection的切片。阅读代码需要有AOP和aspectj的基础知识。 TraceActivity TraceActivity类实现对Activity(还有Application)的切面。 @Aspect public class TraceActivity...

hunter800421的专栏 911

360 apm框架Argus源码解析(1)——开始

开始 先看一个简单的代码示例,演示如何集成360 Argus APM: public class ArgusAPMApplication extends Application { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); ...

hunter800421的专栏 1373

Android Camera2 拍照(三)——切换摄像头,延时拍摄和闪光模式

一、切换摄像头 在前后摄像头之间切换,首先需要关闭之前打开的摄像头,关闭preview,之后重新打开新的摄像头,重新打开preview。 public void switchCamera() { if (mCameraId.equals(CAMERA_FRONT)) { mCameraId = CAMERA_BACK; close

hunter800421的专栏 1万+
上一篇: 360 Argus APM 源码分析(3)—— argus-apm-aop源码分析
下一篇: argus-apm-main中的task(1) —— FpsTask
hunter800421
博客等级 码龄22年 60粉丝 97原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值