Ведение журнала с помощью Retrofit 2
Я пытаюсь получить точный 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
Как я должен вести правильное ведение журнала, учитывая удаление setLog()
и setLogLevel()
которые мы использовали с Retrofit 1?
Переведено автоматически
Ответ 1
В Retrofit 2 вам следует использовать HttpLoggingInterceptor.
Добавить зависимость в build.gradle
. Последняя версия по состоянию на май 2023 года -:
implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0'
Создайте 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);
В случае появления предупреждений об устаревании просто измените setLevel
на:
interceptor.level(HttpLoggingInterceptor.Level.BODY);
Приведенное выше решение выдает вам сообщения logcat, очень похожие на старые, установленные
setLogLevel(RestAdapter.LogLevel.FULL)
В случае java.lang.ClassNotFoundException
:
Для более старой модифицированной версии может потребоваться более старая logging-interceptor
версия. Ознакомьтесь с разделами комментариев для получения подробной информации.
Ответ 2
Я столкнулся с этим, когда мы с вами пытались спросить автора книги Retrofit: любите работать с API на Android (вот ссылка) (нет! Я не делаю для них рекламу .... но они действительно хорошие ребята :) И автор ответил мне очень скоро, используя оба метода ведения журнала в Retrofit 1.9 и 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. Также, если вы читаете ту книгу, о которой я упоминал выше, вы можете обнаружить, что в ней говорится, что метода log с Retrofit 2.0 больше не существует - что, как я спросил автора, неверно, и они обновят книгу в следующем году, рассказав об этом.
// На случай, если вы не очень хорошо знакомы с методом ведения журнала в Retrofit, я хотел бы поделиться кое-чем еще.
Также следует отметить, что вы можете выбрать несколько уровней ведения журнала. Большую часть времени я использую Level.BODY, что дает примерно следующее:
Вы можете найти почти весь http-персонал внутри изображения: заголовок, содержимое и ответ и т.д.
И иногда вам действительно не нужно, чтобы все гости присутствовали на вашей вечеринке: я просто хочу знать, успешно ли она подключена, этот интернет-вызов успешно выполнен в рамках моей активности и фрагмента. Затем вы можете свободно использовать Level.BASIC, который вернет что-то вроде этого:
Можете ли вы найти код состояния 200 OK внутри? Вот и все :)
Также есть еще один, Level.HEADERS, который будет возвращать только заголовок сети. Я, конечно, другая картинка здесь:
Вот и весь трюк с ведением журнала ;)
И я хотел бы поделиться с вами руководством, из которого я многому научился. У них есть куча отличных постов, в которых рассказывается практически обо всем, что связано с Retrofit, и они продолжают обновлять пост, в то же время выходит Retrofit 2.0. Пожалуйста, взгляните на эти работы, которые, я думаю, сэкономят вам массу времени.
Ответ 3
Вот 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
Основная проблема, с которой я столкнулся, заключалась в динамическом добавлении заголовков и регистрации их в debug logcat. Я попытался добавить два перехватчика. Один для ведения журнала, а другой для добавления заголовков на ходу (авторизация токеном). Проблема заключалась в том, что мы можем .addInterceptor или .addNetworkInterceptor. Как сказал мне Джейк Уортон: "Сетевые перехватчики всегда следуют за перехватчиками приложений. Смотрите https://github.com/square/okhttp/wiki/Interceptors". Итак, вот рабочий пример с заголовками и журналами:
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();