OkHttp的性能指标拦截(首包,剩余包时间,resultCode)

最近,部门接到新的任务就是做httpClient,URLConnection,OKhttpClient,webview的网络性能指标进行监控,当然这些指标最准确的方法还是使用jni在底层建链与dns解析,发包等函数进行hook,再进行指标采集。但领导要求我们在java层尝试一下,今天主要记录下,我对OkHttp网络指标采集的调研结果和尝试。

1   OkHttpClient client = new OkHttpClient();
2   Request request = new Request.Builder().url(url).get().build();
3   Response response = client.newCall(request).execute();

 对于httpClient我们通尝都是替换execute()方法,然后对httpClient的对像进行更改配置自己的拦截功能,查看源码,发现OkHttpClient相对不同的是execute方法并不在OkHttpClient,而是newCall方法中new 了一个call实例。

1 public Call newCall(Request request) {
2     return new Call(this, request);
3   }

//Call构造器中,对OkHttpClient进行了深拷备,所以对newCall之后的OkHttpClient配置都将无法生效,所以我们必须在newCall之前将拦截代码进行塞入
 Call(OkHttpClient client, Request originalRequest) {
  // Copy the client. Otherwise changes (socket factory, redirect policy,
  // etc.) may incorrectly be reflected in the request when it is
  // executed.
  this.client = client.copyWithDefaults();
  this.originalRequest = originalRequest;
 }

发现Call类并不是final的,所以决定对其继承,因为 Call的构造器是protected的,所以子类需要在相同的包名下,而上层的拦截于是这样实现的

1   public static Call newCall(OkHttpClient okHttpClient, Request paramRequest)
2     {
3       return new MyCall(okHttpClient, paramRequest, okHttpClient.newCall(paramRequest));
4     }

MyCall类的中的public,protected方法进行重写(execute(),enqueue(Callback paramCallback),cancel(),isCanceled()),实现使用传入的call进行调用,重写getResponse方法

 1  @Override
 2         Response getResponse(Request request, boolean forWebSocket) throws IOException {
 3             RequestBody body = request.body();
 4             if (body != null) {
 5                 Request.Builder requestBuilder = request.newBuilder();
 6 
 7                 MediaType contentType = body.contentType();
 8                 if (contentType != null) {
 9                     requestBuilder.header("Content-Type", contentType.toString());
10                 }
11 
12                 long contentLength = body.contentLength();
13                 if (contentLength != -1) {
14                     requestBuilder.header("Content-Length", Long.toString(contentLength));
15                     requestBuilder.removeHeader("Transfer-Encoding");
16                 } else {
17                     requestBuilder.header("Transfer-Encoding", "chunked");
18                     requestBuilder.removeHeader("Content-Length");
19                 }
20 
21                 request = requestBuilder.build();
22             }
23 
24             // Create the initial HTTP engine. Retries and redirects need new engine
25             // for each attempt.
26             engine = new HttpEngine(client, request, false, false, forWebSocket, null, null, null, null);
27 
28             int followUpCount = 0;
29             while (true) {
30                 if (canceled) {
31                     engine.releaseConnection();
32                     throw new IOException("Canceled");
33                 }
34 
35                 try {
36                     Timer requestTime = ThreadLocalMetricsRecorder.getInstance().getRequestTimer();
37                     Timer responseTime = ThreadLocalMetricsRecorder.getInstance().getResponseTimer();
38                     requestTime.start();
39                     engine.sendRequest();
40                     requestTime.stop();
41                     responseTime.start();
42                     engine.readResponse();
43                     responseTime.stop();
44                 } catch (RequestException e) {
45                     // The attempt to interpret the request failed. Give up.
46                     throw e.getCause();
47                 } catch (RouteException e) {
48                     // The attempt to connect via a route failed. The request will
49                     // not have been sent.
50                     HttpEngine retryEngine = engine.recover(e);
51                     if (retryEngine != null) {
52                         engine = retryEngine;
53                         continue;
54                     }
55                     // Give up; recovery is not possible.
56                     throw e.getLastConnectException();
57                 } catch (IOException e) {
58                     // An attempt to communicate with a server failed. The request
59                     // may have been sent.
60                     HttpEngine retryEngine = engine.recover(e, null);
61                     if (retryEngine != null) {
62                         engine = retryEngine;
63                         continue;
64                     }
65 
66                     // Give up; recovery is not possible.
67                     throw e;
68                 }
69 
70                 Response response = engine.getResponse();
71                 Request followUp = engine.followUpRequest();
72 
73                 if (followUp == null) {
74                     if (!forWebSocket) {
75                         engine.releaseConnection();
76                     }
77                     return response;
78                 }
79 
80                 if (++followUpCount > MAX_FOLLOW_UPS) {
81                     throw new ProtocolException("Too many follow-up requests: " + followUpCount);
82                 }
83 
84                 if (!engine.sameConnection(followUp.url())) {
85                     engine.releaseConnection();
86                 }
87 
88                 Connection connection = engine.close();
89                 request = followUp;
90                 engine = new HttpEngine(client, request, false, false, forWebSocket, connection, null, null, response);
91             }
92         }

算出首包,剩余包时间和拦截重定向,通过重写enqueue方法,获取清求的错误与response

 1         @Override
 2         public void enqueue(Callback paramCallback)
 3         {
 4 //          a();
 5           this.e.enqueue(new Callback() {
 6             
 7             @Override
 8             public void onResponse(Response response) throws IOException {
 9                 
10             }
11             
12             @Override
13             public void onFailure(Request request, IOException e) {
14                 
15             }
16         });
17         }

 

posted on 2016-03-17 11:58  壮士暮年心不死  阅读(3217)  评论(0编辑  收藏  举报

导航