首页 文章

使用Retrofit 2进行记录

提问于
浏览
249

我正在尝试获取请求中发送的确切JSON . 这是我的代码:

OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor(){
   @Override public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
      Request request = chain.request();
      Log.e(String.format("\nrequest:\n%s\nheaders:\n%s",
                          request.body().toString(), request.headers()));
      com.squareup.okhttp.Response response = chain.proceed(request);
      return response;
   }
});
Retrofit retrofit = new Retrofit.Builder()
   .baseUrl(API_URL)
   .addConverterFactory(GsonConverterFactory.create())
   .client(client).build();

但我只在日志中看到这个:

request:
com.squareup.okhttp.RequestBody$1@3ff4074d
headers:
Content-Type: application/vnd.ll.event.list+json

鉴于删除了我们曾经用于改造1的 setLog()setLogLevel() ,我该如何进行正确的记录?

16 回答

  • 1

    在Retrofit 2中你应该使用HttpLoggingInterceptor .

    将依赖项添加到 build.gradle

    compile 'com.squareup.okhttp3:logging-interceptor:3.9.1'
    

    创建一个 Retrofit 对象,如下所示:

    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
    
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://backend.example.com")
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    
    return retrofit.create(ApiClient.class);
    

    上面的解决方案为您提供了非常类似于旧设置的logcat消息

    setLogLevel(RestAdapter.LogLevel.FULL)
    

    In case of java.lang.ClassNotFoundException

    较旧的Retrofit版本可能需要较旧的 logging-interceptor 版本 . 有关详细信息,请查看注释部分 .

  • -11

    我遇到了你的事情,我试图问这本书的作者 Retrofit: Love working with APIs on Android (这里是link)(不!我不是为他们制作一些广告......但是他们真的很好人:)而且作者回答说对我来说很快,使用Retrofit 1.9上的Log方法和Retrofit 2.0-beta .

    以下是Retrofit 2.0-beta的代码:

    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();  
    // set your desired log level
    logging.setLevel(Level.BODY);
    
    OkHttpClient httpClient = new OkHttpClient();  
    // add your other interceptors …
    
    // add logging as last interceptor
    httpClient.interceptors().add(logging);  // <-- this is the important line!
    
    Retrofit retrofit = new Retrofit.Builder()  
       .baseUrl(API_BASE_URL)
       .addConverterFactory(GsonConverterFactory.create())
       .client(httpClient)
       .build();
    

    这是在 HttpLoggingInterceptor 的帮助下添加日志记录方法的方法 . 另外,如果你是我上面提到的那本书的读者,你可能会发现它说再没有使用Retrofit 2.0的日志方法了 - 我曾经问过作者,这是不正确的,明年他们会更新这本书关于它 .

    //如果您不熟悉Retrofit中的Log方法,我想分享更多内容 .

    还应注意,您可以选择一些日志级别 . 我大部分时间都使用 Level.BODY ,它会给出一些这样的东西:

    enter image description here

    您可以在图片中找到几乎所有的http人员: Headers ,内容和响应等 .

    有时你真的没有成功连接,在我的Activiy&Fragmetn中成功完成了互联网通话 . 然后你可以自由使用 Level.BASIC ,它将返回如下内容:

    enter image description here

    你能在里面找到状态码 200 OK 吗?这就对了 :)

    还有另一个, Level.HEADERS ,它只返回网络的 Headers . 雅当然另一张图片在这里:

    enter image description here

    这就是所有的记录技巧;)

    我想与大家分享一下there . 他们有很多很棒的帖子谈论与Retrofit相关的几乎所有内容,他们正在继续更新帖子,同时Retrofit 2.0即将推出 . 请看一下这些工作,我认为这将为您节省大量时间 .

  • 0

    这是一个记录请求和响应主体的 Interceptor (使用Timber,基于OkHttp文档中的示例和其他一些SO答案):

    public class TimberLoggingInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
    
            long t1 = System.nanoTime();
            Timber.i("Sending request %s on %s%n%s", request.url(), chain.connection(), request.headers());
            Timber.v("REQUEST BODY BEGIN\n%s\nREQUEST BODY END", bodyToString(request));
    
            Response response = chain.proceed(request);
    
            ResponseBody responseBody = response.body();
            String responseBodyString = response.body().string();
    
            // now we have extracted the response body but in the process
            // we have consumed the original reponse and can't read it again
            // so we need to build a new one to return from this method
    
            Response newResponse = response.newBuilder().body(ResponseBody.create(responseBody.contentType(), responseBodyString.getBytes())).build();
    
            long t2 = System.nanoTime();
            Timber.i("Received response for %s in %.1fms%n%s", response.request().url(), (t2 - t1) / 1e6d, response.headers());
            Timber.v("RESPONSE BODY BEGIN:\n%s\nRESPONSE BODY END", responseBodyString);
    
            return newResponse;
        }
    
        private static String bodyToString(final Request request){
    
            try {
                final Request copy = request.newBuilder().build();
                final Buffer buffer = new Buffer();
                copy.body().writeTo(buffer);
                return buffer.readUtf8();
            } catch (final IOException e) {
                return "did not work";
            }
        }
    }
    
  • 4

    试试这个:

    Request request = chain.request();
    Buffer buffer = new Buffer();
    request.body().writeTo(buffer);
    String body = buffer.readUtf8();
    

    在此之后,在 body 中有您感兴趣的JSON .

  • 2

    我不知道setLogLevel()是否会在Retrofit的最终2.0版本中返回,但是现在你可以使用拦截器进行日志记录 .

    可以在OkHttp wiki中找到一个很好的例子:https://github.com/square/okhttp/wiki/Interceptors

    OkHttpClient client = new OkHttpClient();
    client.interceptors().add(new LoggingInterceptor());
    
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://www.yourjsonapi.com")
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build();
    
  • 4

    对于那些需要在Retrofit中进行高级别日志记录的人,请使用这样的拦截器

    public static class LoggingInterceptor implements Interceptor {
        @Override public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            long t1 = System.nanoTime();
            String requestLog = String.format("Sending request %s on %s%n%s",
                    request.url(), chain.connection(), request.headers());
            //YLog.d(String.format("Sending request %s on %s%n%s",
            //        request.url(), chain.connection(), request.headers()));
            if(request.method().compareToIgnoreCase("post")==0){
                requestLog ="\n"+requestLog+"\n"+bodyToString(request);
            }
            Log.d("TAG","request"+"\n"+requestLog);
    
            Response response = chain.proceed(request);
            long t2 = System.nanoTime();
    
            String responseLog = String.format("Received response for %s in %.1fms%n%s",
                    response.request().url(), (t2 - t1) / 1e6d, response.headers());
    
            String bodyString = response.body().string();
    
            Log.d("TAG","response"+"\n"+responseLog+"\n"+bodyString);
    
            return response.newBuilder()
                    .body(ResponseBody.create(response.body().contentType(), bodyString))
                    .build();
            //return response;
        }
    }
    
    public static String bodyToString(final Request request) {
        try {
            final Request copy = request.newBuilder().build();
            final Buffer buffer = new Buffer();
            copy.body().writeTo(buffer);
            return buffer.readUtf8();
        } catch (final IOException e) {
            return "did not work";
        }
    }`
    

    Courtesyhttps://github.com/square/retrofit/issues/1072#

  • 27

    我面临的主要问题是动态添加标头并将其记录到调试logcat中 . 我试图添加两个拦截器 . 一个用于记录,一个用于在移动中添加标头(令牌授权) . 问题是我们可能是.addInterceptor或.addNetworkInterceptor . 正如杰克沃顿对我说的那样:“网络拦截器总是在应用拦截器之后出现 . 请参阅https://github.com/square/okhttp/wiki/Interceptors” . 所以这里是 Headers 和日志的工作示例:

    OkHttpClient httpClient = new OkHttpClient.Builder()
                //here we can add Interceptor for dynamical adding headers
                .addNetworkInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request request = chain.request().newBuilder().addHeader("test", "test").build();
                        return chain.proceed(request);
                    }
                })
                //here we adding Interceptor for full level logging
                .addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
                .build();
    
        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(gsonBuilder.create()))
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .client(httpClient)
                .baseUrl(AppConstants.SERVER_ADDRESS)
                .build();
    
  • 5

    如果您使用的是Retrofit2和okhttp3,那么您需要知道Interceptor是按队列工作的 . 所以在你的其他拦截器之后添加loggingInterceptor:

    HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            if (BuildConfig.DEBUG)
                loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
    
     new OkHttpClient.Builder()
                    .connectTimeout(60, TimeUnit.SECONDS)
                    .readTimeout(60, TimeUnit.SECONDS)
                    .writeTimeout(60, TimeUnit.SECONDS)
                    .addInterceptor(new CatalogInterceptor(context))//first
                    .addInterceptor(new OAuthInterceptor(context))//second
                    .authenticator(new BearerTokenAuthenticator(context))
                    .addInterceptor(loggingInterceptor)//third, log at the end
                    .build();
    
  • 1

    您还可以添加Facebook的Stetho并查看Chrome中的网络跟踪:http://facebook.github.io/stetho/

    final OkHttpClient.Builder builder = new OkHttpClient.Builder();
    if (BuildConfig.DEBUG) {
        builder.networkInterceptors().add(new StethoInterceptor());
    }
    

    然后在Chrome中打开“chrome:// inspect”...

  • 0

    在Retrofit 2中执行此操作的最佳方法是将logger拦截器添加为networkInterceptor,这将打印出网络标头和您的自定义标头 . 重要的是要记住拦截器作为堆栈工作,并确保在最后添加 Logger .

    OkHttpClient.Builder builder = new OkHttpClient.Builder();
    builder.addInterceptor(new MyCustomInterceptor());
    builder.connectTimeout(60, TimeUnit.SECONDS);
    builder.readTimeout(60, TimeUnit.SECONDS);
    builder.writeTimeout(60, TimeUnit.SECONDS);
    // important line here
    builder.addNetworkInterceptor(LoggerInterceptor());
    
  • 0

    这里的大部分答案几乎涵盖了除此工具之外的所有内容,这是查看日志的最酷方式之一 .

    这是Facebook's Stetho . 这是在 google chrome 上监控/记录应用程序网络流量的绝佳工具 . 你也可以找到hereGithub上 .

    enter image description here

  • 4

    我找到了改造打印日志的方法

    OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request request = chain.request();
                        if (BuildConfig.DEBUG) {
                            Log.e(getClass().getName(), request.method() + " " + request.url());
                            Log.e(getClass().getName(), "" + request.header("Cookie"));
                            RequestBody rb = request.body();
                            Buffer buffer = new Buffer();
                            if (rb != null)
                                rb.writeTo(buffer);
                            LogUtils.LOGE(getClass().getName(), "Payload- " + buffer.readUtf8());
                        }
                        return chain.proceed(request);
                    }
                })
                .readTimeout(60, TimeUnit.SECONDS)
                .connectTimeout(60, TimeUnit.SECONDS)
                .build();
    
                iServices = new Retrofit.Builder()
                        .baseUrl("Your Base URL")
                        .client(okHttpClient)
                        .addConverterFactory(GsonConverterFactory.create())
                        .build()
                        .create(Your Service Interface .class);
    

    适合我 .

  • 10

    对于Retrofit 2.0.2,代码就像

    **HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            OkHttpClient.Builder httpClient=new OkHttpClient.Builder();
            httpClient.addInterceptor(logging);**
    
    
            if (retrofit == null) {
                retrofit = new Retrofit.Builder()
                        .baseUrl(BASE_URL)
                        .addConverterFactory(GsonConverterFactory.create())
                        **.client(httpClient.build())**
                        .build();
            }
    
  • 557

    Kotlin Code

    val interceptor = HttpLoggingInterceptor()
            interceptor.level = HttpLoggingInterceptor.Level.BODY
            val client = OkHttpClient.Builder().addInterceptor(interceptor).build()
            val retrofit = Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
    
            return retrofit.create(PointApi::class.java)
    
  • 4

    这将使用Logging创建一个改进对象 . 不创建单独的对象 .

    private static final Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(new OkHttpClient().newBuilder()
                        .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
                        .readTimeout(READ_TIMEOUT_SECONDS, TimeUnit.SECONDS)
                        .writeTimeout(WRITE_TIMEOUT_SECONDS, TimeUnit.SECONDS)
                        .connectTimeout(CONNECTION_TIMEOUT_SECONDS, TimeUnit.SECONDS)
                        .build())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    
  • 0

    嘿伙计们,我已经找到了解决办法:

    public static <T> T createApi(Context context, Class<T> clazz, String host, boolean debug) {
        if (singleton == null) {
            synchronized (RetrofitUtils.class) {
                if (singleton == null) {
                    RestAdapter.Builder builder = new RestAdapter.Builder();
                    builder
                            .setEndpoint(host)
                            .setClient(new OkClient(OkHttpUtils.getInstance(context)))
                            .setRequestInterceptor(RequestIntercepts.newInstance())
                            .setConverter(new GsonConverter(GsonUtils.newInstance()))
                            .setErrorHandler(new ErrorHandlers())
                            .setLogLevel(debug ? RestAdapter.LogLevel.FULL : RestAdapter.LogLevel.NONE)/*LogLevel.BASIC will cause response.getBody().in() close*/
                            .setLog(new RestAdapter.Log() {
                                @Override
                                public void log(String message) {
                                    if (message.startsWith("{") || message.startsWith("["))
                                        Logger.json(message);
                                    else {
                                        Logger.i(message);
                                    }
                                }
                            });
                    singleton = builder.build();
                }
            }
        }
        return singleton.create(clazz);
    }
    

相关问题