Retrofit-Androidでリクエストとレスポンスの本文を記録する方法は?


129

完全なリクエスト/レスポンス本文をログに記録するためのRetrofit APIの関連メソッドが見つかりません。プロファイラーでいくつかの助けを期待していました(ただし、応答に関するメタデータしか提供していません)。私はビルダーでログレベルを設定しようとしましたが、これも私には役立ちません:

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

編集:このコードは現在機能しています。それが以前に機能しなかった理由がわかりません。古いバージョンのレトロフィットを使用していた可能性があります。


これを理解したことはありますか?ドキュメントはそれFULLが体を与えると思われているがそれはそうではないようです。
theblang 2014

1
@mattblang:以前は何が悪かったのかわかりませんが、このコードは現在機能しています。
ジャガー



それが上手くいかなかった場合、おそらく即時実行はsmthを台無しにしたでしょう
deathangel908

回答:


91

私が使用したsetLogLevel(LogLevel.FULL).setLog(new AndroidLog("YOUR_LOG_TAG"))、それは私を助けました。
更新。応答モデルとして
デバッグ目的で使用することもできますretrofit.client.Response


2
AndroidLog、それはどのクラスですか?
theblang 2014

それはレトロフィットライブラリが付属しています。
Alex Dzeshko 2014

2
そうですか。残念ながら、これはあなたにを与えませんがresponse body、それはあなたにLogLevel.FULL 与えるべきドキュメントで述べていますresponse body
theblang 2014

これは、詳細タブの下のAndroid logcatの「YOUR_LOG_TAG」で確認できます。
rajeesh 14

4
LogLevel.Fullはレトロフィット2に存在しません

121

レトロフィット2.0

更新:@ MarcusPöhls

Retrofit 2へのログイン

Retrofit 2は、ネットワーク操作を完全にOkHttpに依存しています。OkHttpはRetrofit 2のピア依存関係であるため、Retrofit 2が安定リリースとしてリリースされたら、追加の依存関係を追加する必要はありません。

OkHttp 2.6.0には、内部依存関係としてロギングインターセプターが付属しており、Retrofitクライアントで直接使用できます。Retrofit 2.0.0-beta2は引き続きOkHttp 2.5.0を使用します。将来のリリースでは、依存性をより高いOkHttpバージョンにバンプします。そのため、ロギングインターセプターを手動でインポートする必要があります。次の行をbuild.gradleファイル内のGradleインポートに追加して、ロギングインターセプターの依存関係をフェッチします。

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

このインターセプターについては、SquareのGitHubページにもアクセスできます。

ログをRetrofit 2に追加

アプリの開発中やデバッグの目的で、リクエストとレスポンスの情報を表示するためのログ機能を統合すると便利です。ロギングはRetrofit 2にデフォルトで統合されなくなったため、OkHttpのロギングインターセプターを追加する必要があります。幸いなことに、OkHttpにはすでにこのインターセプターが付属しており、OkHttpClientに対してのみアクティブ化する必要があります。

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

最後のインターセプターとしてロギングを追加することをお勧めします。これにより、以前のインターセプターで追加した情報もリクエストに記録されます。

ログレベル

あまりにも多くの情報をログに記録すると、Androidモニターが破壊されます。そのため、OkHttpのログインターセプターには、NONE、BASIC、HEADERS、BODYの4つのログレベルがあります。各ログレベルについて説明し、その出力について説明します。

詳細については、次のWebサイトをご覧ください:Retrofit 2 —リクエストとレスポンスのログ

古い答え:

Retrofit 2にログインしなくなりました。開発チームはロギング機能を削除しました。正直なところ、ロギング機能はとにかく信頼性が高くありませんでした。Jake Whartonは、ログに記録されたメッセージまたはオブジェクトは想定された値であり、それらが真であることを証明できなかったと明示的に述べました。サーバーに到着する実際のリクエストでは、リクエストの本文などが変更されている可能性があります。

デフォルトでは統合ロギングはありませんが、Javaロガーを利用して、カスタマイズされたOkHttpインターセプター内で使用できます。

Retrofit 2の詳細については、次を参照してください: Retrofit — Getting Started and Create an Android Client



すべてを本来よりも複雑にする優れた方法。ジャージー1とジャージー2のロギングを思い出します。その他のボイラープレートコード....
ブレークライン2016年

この方法でインターセプターを追加すると、OkHttp v3でUnsupportedOperationExceptionが発生します。新しい方法は次のとおりです。OkHttpClient.Builder()。addInterceptor(logging).build() github.com/square/okhttp/issues/2219
Amagi82

@JawadLeWywadiはい、このコードを使用して本文を印刷できます
Dhaval Jivani

Retrofit 2の場合、これははるかに簡単です。
Gary99 2017

31

Retrofit 2.0.0-beta3のアップデート

次に、ビルダーでokhttp3を使用する必要があります。また、古いインターセプターは機能しません。この応答はAndroid用に調整されています。

新しいものを使って、簡単なコピー貼り付けを行います。

1. Gradleファイルを次のように変更します

  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.このサンプルコードを確認します。

新しい輸入品で。Rxを使用しない場合は削除し、使用しない場合は削除することができます。

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

ボーナス

私はそれが話題外であることを知っていますが、それはクールだと思います。

未承認の httpエラーコードがある場合、インターセプターは次のとおりです。イベントの送信にはイベントバスを使用しています。

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

コードはhttps://github.com/AndreiD/UltimateAndroidTemplateRx(私のプロジェクト)から取得します


9

基本的な+ bodyを行う方法はないようですが、FULLを使用して、不要なヘッダーをフィルタリングできます。

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

ログを上書きすると、本文の前に次のようなタグが付けられるようです

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

したがって、カスタムフィルターを調整することで、基本+本体を簡単に記録できるはずです。私はブラックリストを使用していますが、必要に応じてホワイトリストを使用することもできます。


4

以下のコードは、ヘッダーの有無にかかわらず、ログ要求と応答を出力するために機能しています。注:ヘッダーを使用しない場合は、.addHeader()行をコメント化してください。

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

3

このコードがロギングに役立つことを願っています。then makeに
インターセプターを追加するだけです。 Build.GradleRetrofitClient

最初の一歩

この行を build.gradle

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

第二段階

レトロフィットクライアントを作成する


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

呼び出す

RetrofitClient.getInstance(context).getApiService().yourRequestCall(); 

2

Retrofit2とokhttp3を使用している場合は、Interceptorがキューによって機能することを知る必要があります。したがって、他のインターセプターの後に、最後にloggingInterceptorを追加します。

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


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.