OkHttp Events事件

1、Events

Events允许捕获应用程序的HTTP调用的指标,可以使用事件来监控以下参数:

  • 应用发起的HTTP请求大小及频率
  • 请求在底层网络上的性能
2、EventListener
  • 在没有经过重定向和重试的网络请求数据流程图:
    在这里插入图片描述

  • EventListener使用示例代码

class OkEventListener : EventListener() {

    private val TAG = "tag"
    private var callStartTime: Long = 0

    override fun callStart(call: Call) {
        super.callStart(call)
        callStartTime = System.currentTimeMillis()
        mLog("callStart  url=== ${call.request().url}")
    }

    override fun callEnd(call: Call) {
        super.callEnd(call)
        printEvent("callEnd  url===${call.request().url}")
    }

    override fun dnsStart(call: Call, domainName: String) {
        super.dnsStart(call, domainName)
        printEvent("dnsStart")
    }

    override fun dnsEnd(call: Call, domainName: String, inetAddressList: List<InetAddress>) {
        super.dnsEnd(call, domainName, inetAddressList)
        printEvent("dnsEnd")
    }

    override fun connectStart(call: Call, inetSocketAddress: InetSocketAddress, proxy: Proxy) {
        super.connectStart(call, inetSocketAddress, proxy)
        printEvent("connectStart")
    }

    override fun connectEnd(
        call: Call,
        inetSocketAddress: InetSocketAddress,
        proxy: Proxy,
        protocol: Protocol?
    ) {
        super.connectEnd(call, inetSocketAddress, proxy, protocol)
        printEvent("connectEnd")
    }

    override fun connectionReleased(call: Call, connection: Connection) {
        super.connectionReleased(call, connection)
        printEvent("connectionReleased")
    }

    override fun connectFailed(
        call: Call,
        inetSocketAddress: InetSocketAddress,
        proxy: Proxy,
        protocol: Protocol?,
        ioe: IOException
    ) {
        super.connectFailed(call, inetSocketAddress, proxy, protocol, ioe)
        printEvent("connectFailed")
    }

    override fun requestHeadersStart(call: Call) {
        super.requestHeadersStart(call)
        printEvent("requestHeadersStart")
    }

    override fun requestHeadersEnd(call: Call, request: Request) {
        super.requestHeadersEnd(call, request)
        printEvent("requestHeadersEnd")
    }

    override fun requestBodyStart(call: Call) {
        super.requestBodyStart(call)
        printEvent("requestBodyStart")
    }

    override fun requestBodyEnd(call: Call, byteCount: Long) {
        super.requestBodyEnd(call, byteCount)
        printEvent("requestBodyEnd")
    }

    override fun requestFailed(call: Call, ioe: IOException) {
        super.requestFailed(call, ioe)
        printEvent("requestBodyFailed")
    }


    override fun responseHeadersStart(call: Call) {
        super.responseHeadersStart(call)
        printEvent("responseHeadersStart")
    }

    override fun responseHeadersEnd(call: Call, response: Response) {
        super.responseHeadersEnd(call, response)
        printEvent("responseHeadersEnd")
    }

    override fun responseBodyStart(call: Call) {
        super.responseBodyStart(call)
        printEvent("responseBodyStart")
    }

    override fun responseBodyEnd(call: Call, byteCount: Long) {
        super.responseBodyEnd(call, byteCount)
        printEvent("responseBodyEnd")
    }


    private fun printEvent(name: String) {
        val elapsedTime: Long = System.currentTimeMillis() - callStartTime
        mLog("time=== $elapsedTime ms name=== $name")
    }

    private fun mLog(str: String) {
        Log.d(TAG, str)
    }

}
  • 同一个请求get和post请求日志
2021-07-06 17:50:54.065 28217-28217/com.example.myapplication D/tag: callStart  url=== https://publicobject.com/helloworld.txt
2021-07-06 17:50:54.068 28217-28672/com.example.myapplication D/tag: time=== 3 ms name=== dnsStart
2021-07-06 17:50:54.073 28217-28672/com.example.myapplication D/tag: time=== 8 ms name=== dnsEnd
2021-07-06 17:50:54.073 28217-28672/com.example.myapplication D/tag: time=== 8 ms name=== connectStart
2021-07-06 17:50:54.461 28217-28672/com.example.myapplication D/tag: time=== 396 ms name=== connectEnd
2021-07-06 17:50:54.462 28217-28672/com.example.myapplication D/tag: time=== 397 ms name=== requestHeadersStart
2021-07-06 17:50:54.462 28217-28672/com.example.myapplication D/tag: time=== 397 ms name=== requestHeadersEnd
2021-07-06 17:50:54.922 28217-28672/com.example.myapplication D/tag: time=== 857 ms name=== responseHeadersStart
2021-07-06 17:50:54.922 28217-28672/com.example.myapplication D/tag: time=== 857 ms name=== responseHeadersEnd
2021-07-06 17:50:54.923 28217-28672/com.example.myapplication D/tag:  get success  response=== okhttp3.internal.http.RealResponseBody@326b64a
2021-07-06 17:50:56.015 28217-28217/com.example.myapplication D/tag: callStart  url=== https://publicobject.com/helloworld.txt
2021-07-06 17:50:56.020 28217-28672/com.example.myapplication D/tag: time=== 6 ms name=== dnsStart
2021-07-06 17:50:56.020 28217-28672/com.example.myapplication D/tag: time=== 6 ms name=== dnsEnd
2021-07-06 17:50:56.021 28217-28672/com.example.myapplication D/tag: time=== 7 ms name=== connectStart
2021-07-06 17:50:56.429 28217-28672/com.example.myapplication D/tag: time=== 415 ms name=== connectEnd
2021-07-06 17:50:56.430 28217-28672/com.example.myapplication D/tag: time=== 416 ms name=== requestHeadersStart
2021-07-06 17:50:56.431 28217-28672/com.example.myapplication D/tag: time=== 417 ms name=== requestHeadersEnd
2021-07-06 17:50:56.870 28217-28672/com.example.myapplication D/tag: time=== 856 ms name=== responseHeadersStart
2021-07-06 17:50:56.870 28217-28672/com.example.myapplication D/tag: time=== 856 ms name=== responseHeadersEnd
2021-07-06 17:50:56.871 28217-28672/com.example.myapplication D/tag:  post success  response=== okhttp3.internal.http.RealResponseBody@3b2d697
3、EventListener.Factory

在前面的示例中,我们使用了一个callStartNanos来跟踪每个事件的运行时间。这很方便,但是如果多个Call请求同时执行,由于不能区分请求url生命周期,就会有问题了。为了适应这种情况,可以使用Factory为每个Call创建一个新的EventListener实例,可以实现每个listener保持特定于调用的状态。

  • OkEventFactoryListener
class OkEventFactoryListener(callId:Long,startTime:Long) : EventListener() {

    private val TAG = "factory"
    private var mCallStartNanos: Long = startTime
    private val mCallId=callId

    override fun callStart(call: Call) {
        super.callStart(call)
        printEvent("callStart")
    }

    override fun callEnd(call: Call) {
        super.callEnd(call)
        printEvent("callEnd")
    }

    override fun dnsStart(call: Call, domainName: String) {
        super.dnsStart(call, domainName)
        printEvent("dnsStart")
    }

    override fun dnsEnd(call: Call, domainName: String, inetAddressList: List<InetAddress>) {
        super.dnsEnd(call, domainName, inetAddressList)
        printEvent("dnsEnd")
    }

    override fun connectStart(call: Call, inetSocketAddress: InetSocketAddress, proxy: Proxy) {
        super.connectStart(call, inetSocketAddress, proxy)
        printEvent("connectStart")
    }

    override fun connectEnd(
        call: Call,
        inetSocketAddress: InetSocketAddress,
        proxy: Proxy,
        protocol: Protocol?
    ) {
        super.connectEnd(call, inetSocketAddress, proxy, protocol)
        printEvent("connectEnd")
    }

    override fun connectionReleased(call: Call, connection: Connection) {
        super.connectionReleased(call, connection)
        printEvent("connectionReleased")
    }

    override fun connectFailed(
        call: Call,
        inetSocketAddress: InetSocketAddress,
        proxy: Proxy,
        protocol: Protocol?,
        ioe: IOException
    ) {
        super.connectFailed(call, inetSocketAddress, proxy, protocol, ioe)
        printEvent("connectFailed")
    }

    override fun requestHeadersStart(call: Call) {
        super.requestHeadersStart(call)
        printEvent("requestHeadersStart")
    }

    override fun requestHeadersEnd(call: Call, request: Request) {
        super.requestHeadersEnd(call, request)
        printEvent("requestHeadersEnd")
    }

    override fun requestBodyStart(call: Call) {
        super.requestBodyStart(call)
        printEvent("requestBodyStart")
    }

    override fun requestBodyEnd(call: Call, byteCount: Long) {
        super.requestBodyEnd(call, byteCount)
        printEvent("requestBodyEnd")
    }

    override fun requestFailed(call: Call, ioe: IOException) {
        super.requestFailed(call, ioe)
        printEvent("requestBodyFailed")
    }


    override fun responseHeadersStart(call: Call) {
        super.responseHeadersStart(call)
        printEvent("responseHeadersStart")
    }

    override fun responseHeadersEnd(call: Call, response: Response) {
        super.responseHeadersEnd(call, response)
        printEvent("responseHeadersEnd")
    }

    override fun responseBodyStart(call: Call) {
        super.responseBodyStart(call)
        printEvent("responseBodyStart")
    }

    override fun responseBodyEnd(call: Call, byteCount: Long) {
        super.responseBodyEnd(call, byteCount)
        printEvent("responseBodyEnd")
    }

    private fun printEvent(name: String) {
        val elapsedTime: Long = System.currentTimeMillis() - mCallStartNanos
        mLog("callId== $mCallId  time=== $elapsedTime ms name=== $name")
    }

    private fun mLog(str: String) {
        Log.d(TAG, str)
    }

    companion object {
        private val nextCallId: AtomicLong = AtomicLong(1L)
        fun create(): Factory {
            return object : Factory {
                override fun create(call: Call): EventListener {
                    val callId: Long = nextCallId.getAndIncrement()
                    Log.d("factory", "callId==  $callId  url==${call.request().url}")
                    return OkEventFactoryListener(callId,System.currentTimeMillis())
                }

            }
        }
    }

}
  • 请求日志
2021-07-06 17:55:26.587 29140-29140/com.example.myapplication D/factory: callId==  1  url==https://publicobject.com/helloworld.txt
2021-07-06 17:55:26.588 29140-29140/com.example.myapplication D/factory: callId== 1  time=== 1 ms name=== callStart
2021-07-06 17:55:26.603 29140-29248/com.example.myapplication D/factory: callId== 1  time=== 16 ms name=== dnsStart
2021-07-06 17:55:26.607 29140-29248/com.example.myapplication D/factory: callId== 1  time=== 20 ms name=== dnsEnd
2021-07-06 17:55:26.612 29140-29248/com.example.myapplication D/factory: callId== 1  time=== 25 ms name=== connectStart
2021-07-06 17:55:27.068 29140-29248/com.example.myapplication D/factory: callId== 1  time=== 481 ms name=== connectEnd
2021-07-06 17:55:27.070 29140-29248/com.example.myapplication D/factory: callId== 1  time=== 483 ms name=== requestHeadersStart
2021-07-06 17:55:27.071 29140-29248/com.example.myapplication D/factory: callId== 1  time=== 484 ms name=== requestHeadersEnd
2021-07-06 17:55:27.438 29140-29248/com.example.myapplication D/factory: callId== 1  time=== 851 ms name=== responseHeadersStart
2021-07-06 17:55:27.439 29140-29248/com.example.myapplication D/factory: callId== 1  time=== 852 ms name=== responseHeadersEnd
2021-07-06 17:55:28.914 29140-29140/com.example.myapplication D/factory: callId==  2  url==https://www.baidu.com/
2021-07-06 17:55:28.914 29140-29140/com.example.myapplication D/factory: callId== 2  time=== 0 ms name=== callStart
2021-07-06 17:55:28.918 29140-29248/com.example.myapplication D/factory: callId== 2  time=== 4 ms name=== dnsStart
2021-07-06 17:55:28.946 29140-29248/com.example.myapplication D/factory: callId== 2  time=== 32 ms name=== dnsEnd
2021-07-06 17:55:28.947 29140-29248/com.example.myapplication D/factory: callId== 2  time=== 33 ms name=== connectStart
2021-07-06 17:55:29.035 29140-29248/com.example.myapplication D/factory: callId== 2  time=== 121 ms name=== connectEnd
2021-07-06 17:55:29.036 29140-29248/com.example.myapplication D/factory: callId== 2  time=== 122 ms name=== requestHeadersStart
2021-07-06 17:55:29.036 29140-29248/com.example.myapplication D/factory: callId== 2  time=== 122 ms name=== requestHeadersEnd
2021-07-06 17:55:29.059 29140-29248/com.example.myapplication D/factory: callId== 2  time=== 145 ms name=== responseHeadersStart
2021-07-06 17:55:29.060 29140-29248/com.example.myapplication D/factory: callId== 2  time=== 146 ms name=== responseHeadersEnd

4、Events with Failures

向服务端发起创建连接失败时,会调用connectFailed(),Http请求永久失败时,会调用callFailed()方法

  • 调用流程图如下:
    在这里插入图片描述

  • connectionFail日志

2021-07-07 12:26:53.019 11814-11984/com.example.myapplication D/tag:  get success  response=== okhttp3.internal.http.RealResponseBody@cea5bb6
2021-07-07 12:26:59.182 11814-11814/com.example.myapplication D/tag: callStart  url=== https://publicobject.com/helloworld.txt
2021-07-07 12:26:59.190 11814-11984/com.example.myapplication D/tag: time=== 8 ms name=== dnsStart
2021-07-07 12:26:59.192 11814-11984/com.example.myapplication D/tag: time=== 10 ms name=== dnsEnd
2021-07-07 12:26:59.193 11814-11984/com.example.myapplication D/tag: time=== 11 ms name=== connectStart
2021-07-07 12:26:59.608 11814-11984/com.example.myapplication D/tag: time=== 426 ms name=== connectEnd
2021-07-07 12:26:59.609 11814-11984/com.example.myapplication D/tag: time=== 427 ms name=== requestHeadersStart
2021-07-07 12:26:59.610 11814-11984/com.example.myapplication D/tag: time=== 428 ms name=== requestHeadersEnd
2021-07-07 12:27:00.138 11814-11984/com.example.myapplication D/tag: time=== 956 ms name=== responseHeadersStart
2021-07-07 12:27:00.138 11814-11984/com.example.myapplication D/tag: time=== 956 ms name=== responseHeadersEnd
2021-07-07 12:27:00.138 11814-11984/com.example.myapplication D/tag:  get success  response=== okhttp3.internal.http.RealResponseBody@ac3a153
2021-07-07 12:27:07.422 11814-11814/com.example.myapplication D/tag: callStart  url=== https://www.nytimes.com/
2021-07-07 12:27:07.432 11814-11984/com.example.myapplication D/tag: time=== 10 ms name=== dnsStart
2021-07-07 12:27:07.498 11814-11984/com.example.myapplication D/tag: time=== 76 ms name=== dnsEnd
2021-07-07 12:27:07.499 11814-11984/com.example.myapplication D/tag: time=== 77 ms name=== connectStart
2021-07-07 12:27:17.512 11814-11984/com.example.myapplication D/tag: time=== 10090 ms name=== connectFailed
2021-07-07 12:27:17.512 11814-11984/com.example.myapplication D/tag: fail e===failed to connect to www.nytimes.com/31.13.87.19 (port 443) from /10.208.95.23 (port 43204) after 10000ms   cause=== null

5、Events with Retries and Follow-Ups

OKHttp具有自动重试和重连机制,当连接失败时或者由于url变更发起重定向时,event事件监听会在单个http请求中回掉多次,但是单个http请求的callStart()和callEnd方法只会调用一次

  • 流程图如下
    在这里插入图片描述

  • 参考: https://square.github.io/okhttp/events/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值