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