This article is participating in “Java Theme Month – Java Debug Notes Event”, see < Event link > for more details.

Question: Log usage issues with Retrofit 2

I’m trying to get the JSON that was sent in the request. Here’s 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);
      returnresponse; }}); Retrofit retrofit =new Retrofit.Builder()
   .baseUrl(API_URL)
   .addConverterFactory(GsonConverterFactory.create())
   .client(client).build();
Copy the code

But I can only see it in the log:

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

Given Retrofit 1’s removal of the use of setLog() and setLogLevel(), how should I do proper logging?

Answer 1:

In Retrofit 2, you should use Httploggingtor.

Add dependencies to build.gradle. The latest version, as of October 2019, is:

Implementation ‘com. Squareup. Okhttp3: logging – interceptor: 2’

Create a Retrofit object as follows:

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);
Copy the code

If there are methods that deprecate warnings, change setLevel to:

interceptor.level(HttpLoggingInterceptor.Level.BODY);
Copy the code

The above solution gives you a logcat message that is very similar to the original one.


setLogLevel(RestAdapter.LogLevel.FULL)
Copy the code

If there is a Java. Lang. ClassNotFoundException problem, the older version of the Retrofit may need older logging – interceptor version.

Answer 2: This is an Interceptor implementation that logs both the request and response body (using Timber, based on the example in the OkHttp document, and some other StackOverflow answers) :

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"; }}}Copy the code