Bagaimana cara mencatat permintaan dan respons tubuh dengan Retrofit-Android?

129

Saya tidak dapat menemukan metode yang relevan di Retrofit API untuk mencatat badan permintaan / respons lengkap. Saya mengharapkan bantuan di Profiler (tetapi itu hanya menawarkan meta-data tentang respon). Saya mencoba menyetel level log di Builder, tetapi ini juga tidak membantu saya:

RestAdapter adapter = (new RestAdapter.Builder()).
                setEndpoint(baseUrl).
                setRequestInterceptor(interceptor).
                setProfiler(profiler).
                setClient(client).
                setExecutors(MyApplication.getWebServiceThreadPool()).
                setLogLevel(LogLevel.FULL).
                setLog(new RestAdapter.Log() {
                    @Override
                    public void log(String msg) {
                        Log.i(TAG, msg);
                    }
                }).
                build();

EDIT: Kode ini berfungsi sekarang. Saya tidak tahu mengapa itu tidak berfungsi sebelumnya. Mungkin karena saya menggunakan retrofit versi lama.

Jaguar
sumber
Apakah Anda pernah memikirkan hal ini? Dokumentasi mengatakan bahwa FULLseharusnya memberikan tubuh tetapi sepertinya tidak.
theblang
1
@mattblang: Saya tidak tahu apa yang salah sebelumnya, tetapi kode ini berfungsi sekarang.
Jaguar
Kemungkinan duplikat Penebangan dengan Retrofit 2
bryant1410
Mungkin proses instan mengacaukannya jika tidak bekerja lebih awal
deathangel908

Jawaban:

91

Saya menggunakan setLogLevel(LogLevel.FULL).setLog(new AndroidLog("YOUR_LOG_TAG")), itu membantu saya.
MEMPERBARUI.
Anda juga dapat mencoba untuk tujuan debug digunakan retrofit.client.Responsesebagai model respons

Alex Dzeshko
sumber
2
AndroidLog, kelas apa itu?
theblang
Muncul dengan perpustakaan Retrofit.
Alex Dzeshko
2
Saya melihat. Sayangnya ini tidak memberi Anda response body, meskipun dinyatakan di dokumen yang LogLevel.FULL seharusnya memberi Anda response body.
theblang
Ini dapat dilihat dengan "YOUR_LOG_TAG" di logcat android di bawah tab verbose.
rajeesh
4
LogLevel.Full tidak ada pada retrofit 2
121

Retrofit 2.0 :

PEMBARUAN: @oleh Marcus Pöhls

Masuk Retrofit 2

Retrofit 2 sepenuhnya bergantung pada OkHttp untuk operasi jaringan apa pun. Karena OkHttp adalah dependensi peer Retrofit 2, Anda tidak perlu menambahkan dependensi tambahan setelah Retrofit 2 dirilis sebagai rilis stabil.

OkHttp 2.6.0 dikirimkan dengan interseptor logging sebagai ketergantungan internal dan Anda dapat langsung menggunakannya untuk klien Retrofit Anda. Retrofit 2.0.0-beta2 masih menggunakan OkHttp 2.5.0. Rilis selanjutnya akan meningkatkan ketergantungan ke versi OkHttp yang lebih tinggi. Itulah mengapa Anda perlu mengimpor interseptor logging secara manual. Tambahkan baris berikut ke impor gradle dalam file build.gradle Anda untuk mengambil dependensi interseptor logging.

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

Anda juga dapat mengunjungi halaman GitHub Square tentang pencegat ini

Tambahkan Logging ke Retrofit 2

Saat mengembangkan aplikasi Anda dan untuk tujuan debugging, ada baiknya memiliki fitur log yang terintegrasi untuk menampilkan informasi permintaan dan respons. Karena logging tidak lagi terintegrasi secara default di Retrofit 2, kita perlu menambahkan interseptor logging untuk OkHttp. Untungnya OkHttp sudah dikirimkan dengan pencegat ini dan Anda hanya perlu mengaktifkannya untuk OkHttpClient Anda.

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

Kami merekomendasikan untuk menambahkan logging sebagai interseptor terakhir, karena ini juga akan mencatat informasi yang Anda tambahkan dengan interseptor sebelumnya ke permintaan Anda.

Tingkat Log

Mencatat terlalu banyak informasi akan meledakkan monitor Android Anda, itulah sebabnya interseptor logging OkHttp memiliki empat level log: NONE, BASIC, HEADERS, BODY. Kami akan memandu Anda melalui setiap level log dan menjelaskan hasilnya.

informasi lebih lanjut silakan kunjungi: Retrofit 2 - Log Permintaan dan Tanggapan

JAWABAN LAMA:

tidak perlu masuk ke Retrofit 2 lagi. Tim pengembangan menghapus fitur logging. Sejujurnya, fitur logging tidak begitu andal. Jake Wharton secara eksplisit menyatakan bahwa pesan atau objek yang dicatat adalah nilai yang diasumsikan dan tidak dapat dibuktikan kebenarannya. Permintaan sebenarnya yang tiba di server mungkin memiliki badan permintaan yang berubah atau sesuatu yang lain.

Meskipun tidak ada pencatatan terintegrasi secara default, Anda dapat memanfaatkan pencatat Java apa pun dan menggunakannya dalam pencegat OkHttp yang disesuaikan.

informasi lebih lanjut tentang Retrofit 2 silakan lihat: Retrofit - Memulai dan Membuat Klien Android

Dhaval Jivani
sumber
1
Ada juga pos khusus untuk masuk ke Retrofit 2.0: futurestud.io/blog/retrofit-2-log-requests-and-responses
peitek
Cara yang bagus untuk membuat segalanya lebih rumit dari yang seharusnya. Mengingatkan saya pada penebangan Jersey 1 vs Jersey 2. Lebih banyak kode boilerplate ....
breakline
Menambahkan interseptor dengan cara ini sekarang akan menghasilkan UnsupportedOperationException di OkHttp v3. Cara baru adalah: OkHttpClient.Builder (). AddInterceptor (logging) .build () github.com/square/okhttp/issues/2219
Amagi82
@JawadLeWywadi ya menggunakan kode ini Anda dapat mencetak tubuh
Dhaval Jivani
Untuk Retrofit 2, ini jauh lebih mudah.
Gary99
31

Pembaruan untuk Retrofit 2.0.0-beta3

Sekarang Anda harus menggunakan okhttp3 dengan pembuatnya. Juga pencegat lama tidak akan berfungsi. Tanggapan ini disesuaikan untuk Android.

Ini salin cepat tempel untuk Anda dengan barang baru.

1. Ubah file gradle Anda menjadi

  compile 'com.squareup.retrofit2:retrofit:2.0.0-beta3'
  compile "com.squareup.retrofit2:converter-gson:2.0.0-beta3"
  compile "com.squareup.retrofit2:adapter-rxjava:2.0.0-beta3"
  compile 'com.squareup.okhttp3:logging-interceptor:3.0.1'

2. Periksa kode contoh ini:

dengan impor baru. Anda dapat menghapus Rx jika Anda tidak menggunakannya, juga menghapus apa yang tidak Anda gunakan.

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.GsonConverterFactory;
import retrofit2.Retrofit;
import retrofit2.RxJavaCallAdapterFactory;
import retrofit2.http.GET;
import retrofit2.http.Query;
import rx.Observable;

public interface APIService {

  String ENDPOINT = "http://api.openweathermap.org";
  String API_KEY = "2de143494c0b2xxxx0e0";

  @GET("/data/2.5/weather?appid=" + API_KEY) Observable<WeatherPojo> getWeatherForLatLon(@Query("lat") double lat, @Query("lng") double lng, @Query("units") String units);


  class Factory {

    public static APIService create(Context context) {

      OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
      builder.readTimeout(10, TimeUnit.SECONDS);
      builder.connectTimeout(5, TimeUnit.SECONDS);

      if (BuildConfig.DEBUG) {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
        builder.addInterceptor(interceptor);
      }

      //Extra Headers

      //builder.addNetworkInterceptor().add(chain -> {
      //  Request request = chain.request().newBuilder().addHeader("Authorization", authToken).build();
      //  return chain.proceed(request);
      //});

      builder.addInterceptor(new UnauthorisedInterceptor(context));
      OkHttpClient client = builder.build();

      Retrofit retrofit =
          new Retrofit.Builder().baseUrl(APIService.ENDPOINT).client(client).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();

      return retrofit.create(APIService.class);
    }
  }
}

Bonus

Saya tahu ini offtopic tapi menurut saya keren.

Jika ada kode kesalahan http yang tidak sah , ini adalah pencegat. Saya menggunakan eventbus untuk mentransmisikan acara tersebut.

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import com.androidadvance.ultimateandroidtemplaterx.BaseApplication;
import com.androidadvance.ultimateandroidtemplaterx.events.AuthenticationErrorEvent;

import de.greenrobot.event.EventBus;
import java.io.IOException;
import javax.inject.Inject;
import okhttp3.Interceptor;
import okhttp3.Response;

public class UnauthorisedInterceptor implements Interceptor {

  @Inject EventBus eventBus;

  public UnauthorisedInterceptor(Context context) {
    BaseApplication.get(context).getApplicationComponent().inject(this);
  }

  @Override public Response intercept(Chain chain) throws IOException {
    Response response = chain.proceed(chain.request());
    if (response.code() == 401) {
      new Handler(Looper.getMainLooper()).post(() -> eventBus.post(new AuthenticationErrorEvent()));
    }
    return response;
  }
}

kode diambil dari https://github.com/AndreiD/UltimateAndroidTemplateRx (proyek saya).

OWADVL
sumber
9

Tampaknya tidak ada cara untuk melakukan + body dasar, tetapi Anda dapat menggunakan FULL dan memfilter header yang tidak Anda inginkan.

RestAdapter adapter = new RestAdapter.Builder()
                          .setEndpoint(syncServer)
                          .setErrorHandler(err)
                          .setConverter(new GsonConverter(gson))
                          .setLogLevel(logLevel)
                          .setLog(new RestAdapter.Log() {
                              @Override
                              public void log(String msg) {
                                  String[] blacklist = {"Access-Control", "Cache-Control", "Connection", "Content-Type", "Keep-Alive", "Pragma", "Server", "Vary", "X-Powered-By"};
                                  for (String bString : blacklist) {
                                      if (msg.startsWith(bString)) {
                                          return;
                                      }
                                  }
                                  Log.d("Retrofit", msg);
                              }
                          }).build();

Tampaknya saat mengganti log, badan diawali dengan tag yang mirip dengan

[ 02-25 10:42:30.317 25645:26335 D/Retrofit ]

jadi seharusnya mudah untuk membuat log dasar + isi dengan menyesuaikan filter khusus. Saya menggunakan daftar hitam, tetapi daftar putih juga dapat digunakan tergantung kebutuhan Anda.

Xeridea
sumber
4

kode di bawah ini berfungsi baik dengan header dan tanpa header untuk mencetak permintaan & respons log. Catatan: Hanya komentar baris .addHeader () jika tidak menggunakan header.

HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                //.addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
                .addNetworkInterceptor(new Interceptor() {

                    @Override

                    public okhttp3.Response intercept(Chain chain) throws IOException {
                        Request request = chain.request().newBuilder()
                                // .addHeader(Constant.Header, authToken)
                                   .build();
                        return chain.proceed(request);
                    }
                }).build();

        final Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Constant.baseUrl)
                .client(client) // This line is important
                .addConverterFactory(GsonConverterFactory.create())
                .build();
Mukesh Parmar
sumber
3

Saya harap kode ini akan membantu Anda untuk masuk.
Anda hanya perlu menambahkan interceptor di Build.Gradlemake Anda RetrofitClient.

Langkah pertama

Tambahkan baris ini ke build.gradle

 implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1' 

Tahap kedua

Buat Klien Retrofit Anda


   public class RetrofitClient {

    private Retrofit retrofit;
    private static OkHttpClient.Builder httpClient =
            new OkHttpClient.Builder();
    private static RetrofitClient instance = null;
    private static ApiServices service = null;
    private static HttpLoggingInterceptor logging =
            new HttpLoggingInterceptor();

    private RetrofitClient(final Context context) {
        httpClient.interceptors().add(new Interceptor() {
            @Override
            public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
                Request originalRequest = chain.request();
                Request.Builder builder = originalRequest.newBuilder().
                        method(originalRequest.method(), originalRequest.body());
                okhttp3.Response response = chain.proceed(builder.build());
                /*
                Do what you want
                 */
                return response;
            }
        });

        if (BuildConfig.DEBUG) {
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            // add logging as last interceptor
            httpClient.addInterceptor(logging);
        }

        retrofit = new Retrofit.Builder().client(httpClient.build()).
                baseUrl(Constants.BASE_URL).
                addConverterFactory(GsonConverterFactory.create()).build();
        service = retrofit.create(ApiServices.class);
    }


    public static RetrofitClient getInstance(Context context) {
        if (instance == null) {
            instance = new RetrofitClient(context);
        }
        return instance;
    }

    public ApiServices getApiService() {
        return service;
    }
}

Panggilan

RetrofitClient.getInstance(context).getApiService().yourRequestCall(); 
Talha Bilal
sumber
2

Jika Anda menggunakan Retrofit2 dan okhttp3 maka Anda perlu tahu bahwa Interceptor bekerja berdasarkan antrian. Jadi tambahkan loggingInterceptor di akhir, setelah Interceptors Anda yang lain:

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))
                .addInterceptor(new OAuthInterceptor(context))
                .authenticator(new BearerTokenAuthenticator(context))
                .addInterceptor(loggingInterceptor)//at the end
                .build();
NickUnuchek
sumber