zoukankan      html  css  js  c++  java
  • Okhttp3日志采集功能

    原文地址以示尊重:http://www.jianshu.com/p/d836271b1ae4

    日志采集是一个APP必备的功能,可以方便开发人员快速定位问题,解决问题,那么我们在使用okhttp的时候应该怎样添加日志功能呢?

    直接上干货

    private class LogInterceptor implements Interceptor {
            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Log.v("zcb", "request:" + request.toString());
                long t1 = System.nanoTime();
                okhttp3.Response response = chain.proceed(chain.request());
                long t2 = System.nanoTime();
                Log.v("zcb", String.format(Locale.getDefault(), "Received response for %s in %.1fms%n%s",
                        response.request().url(), (t2 - t1) / 1e6d, response.headers()));
                okhttp3.MediaType mediaType = response.body().contentType();
                String content = response.body().string();
                Log.i("zcb", "response body:" + content);
                return response.newBuilder()
                        .body(okhttp3.ResponseBody.create(mediaType, content))
                        .build();
            }
        }
    
    
        ...
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .addInterceptor(new LogInterceptor())
                    .build();

    首先我们实现了一个拦截器LogInterceptor,里面做了三件事情:打印request内容->执行request->打印response内容,过程简单清晰。但是有一个地方需要注意一下,在调用了response.body().string()方法之后,response中的流会被关闭,我们需要创建出一个新的response给应用层处理。手快的同学已经敲完了代码并验证了一遍,发现拦截器中能获取到body的内容,但是在拦截器外面就获取不到了。

    这是为什么呢?Talk is cheap show me the code。先看一下response.body().string()的实现

    public final String string() throws IOException {
        return new String(bytes(), charset().name());
      }

    string()调用了bytes()来获取内容

    public final byte[] bytes() throws IOException {
        //省略部分代码
        BufferedSource source = source();
        byte[] bytes;
        try {
          bytes = source.readByteArray();
        } finally {
          Util.closeQuietly(source);
        }
        //省略部分代码
        return bytes;
      }

    bytes()方法中先得到了BufferedSource,然后将BufferedSource中的内容读取出来,最后将BufferedSource中的文件流关闭,似乎并没有什么问题。等等,我们在拦截器中将BufferedSource中的文件流关闭,而在ResponseBody中没有相应的数据缓存,所以我们在拦截器外部再想获取body的内容就失败了,一切终于真相大白。

    可以看到,我们在拦截器中相当于手动处理了网络请求的整个过程,这就意味着在拦截器中可以做非常多的事情,例如虚拟一个返回结果等等,这些就不是本文的内容了。

    Update
    使用Logging Interceptor可以很轻松的实现日志采集功能,具体细节参考

    参考内容:
    [1]. https://github.com/square/okhttp/wiki/Interceptors

  • 相关阅读:
    年末反思
    Flink运行时架构
    Phoenix 启动报错:Error: ERROR 726 (43M10): Inconsistent namespace mapping properties. Cannot initiate connection as SYSTEM:CATALOG is found but client does not have phoenix.schema.
    Clickhouse学习
    Flink简单认识
    IDEA无法pull代码到本地,Can't Update No tracked branch configured for branch master or the branch doesn't exist.
    第1章 计算机系统漫游
    简单的 Shell 脚本入门教程
    开源≠免费 常见开源协议介绍
    MySQL 视图
  • 原文地址:https://www.cnblogs.com/zhang-cb/p/6076655.html
Copyright © 2011-2022 走看看