Logging with Retrofit 2

2018-12-31 19:54发布

I'm trying to get the exact JSON that is being sent in the request. Here is my code:

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();

But I only see this in the logs:

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

How am I supposed to do proper logging, given the removal of setLog() and setLogLevel() which we used to use with Retrofit 1?

16条回答
看淡一切
2楼-- · 2018-12-31 20:39

I don't know if setLogLevel() will return in the final 2.0 version of Retrofit but for now you can use an interceptor for logging.

A good example can found in 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();
查看更多
宁负流年不负卿
3楼-- · 2018-12-31 20:41

I met the thing as you and I tried to ask the author of the book Retrofit: Love working with APIs on Android (here is the link) (nope! I am not making some ads for them....but they are really nice guys :) And the author replied to me very soon, with both Log method on Retrofit 1.9 and Retrofit 2.0-beta.

And here is the code of 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();

This is how to add logging method with the help of HttpLoggingInterceptor. Also if you are the reader of that book I mentioned above, you may find that it says there is not log method with Retrofit 2.0 anymore -- which, I had asked the author, is not correct and they will update the book next year talking about it.

// In case you are not that familiar with the Log method in Retrofit, I would like to share something more.

Also should be noticed that there are some Logging Levels you could pick. I use the Level.BODY most of the time, which will give some thing like this:

enter image description here

You can find almost all the http staff inside the picture: the header, the content and response, etc.

And sometimes you really don't need all the guests to attend your party: I just want to know whether it's successfully connected, that internet call is successfully made within my Activiy & Fragmetn. Then you are free to use Level.BASIC, which will return something like this:

enter image description here

Can you find the status code 200 OK inside? That is it :)

Also there is another one, Level.HEADERS, which will only return the header of the network. Ya of course another picture here:

enter image description here

That's all of the Logging trick ;)

And I would like to share you with the tutorial I learned a lot there. They have a bunch of great post talking about almost everything related to Retrofit, and they are continuing updating the post, at the same time Retrofit 2.0 is coming. Please take a look at those work, which I think will save you lots of time.

查看更多
美炸的是我
4楼-- · 2018-12-31 20:41

For those who need high level logging in Retrofit, use the interceptor like this

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";
    }
}`

Courtesy: https://github.com/square/retrofit/issues/1072#

查看更多
梦寄多情
5楼-- · 2018-12-31 20:42

hey guys,i already find solution:

  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);
}
查看更多
登录 后发表回答