Retrofit-Android로 요청 및 응답 본문을 기록하는 방법은 무엇입니까?


129

완전한 요청 / 응답 본문을 로깅하기위한 Retrofit API에서 관련 메서드를 찾을 수 없습니다. Profiler에서 약간의 도움을 기대하고 있었지만 응답에 대한 메타 데이터 만 제공합니다. Builder에서 로그 수준을 설정하려고 시도했지만 이것은 나에게도 도움이되지 않습니다.

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 : 이전에는 무엇이 잘못되었는지 모르겠지만이 코드는 지금 작동합니다.
Jaguar



그것은 이전에 작동하지 않은 경우 아마 즉시 실행이 떨어지게을 엉망
deathangel908

답변:


91

나는 setLogLevel(LogLevel.FULL).setLog(new AndroidLog("YOUR_LOG_TAG")), 그것은 나를 도왔다.
최신 정보. 응답 모델로
디버그 용도로 사용해 볼 수도 있습니다.retrofit.client.Response


2
AndroidLog, 어떤 클래스입니까?
theblang 2014

Retrofit 라이브러리와 함께 제공됩니다.
Alex Dzeshko 2014

2
내가 참조. 불행하게도이 당신에게 제공하지 않습니다 response body는 문서의 상태는하지만, LogLevel.FULL 해야 당신에게를 제공합니다 response body.
theblang

이것은 상세 탭 아래의 android logcat에서 "YOUR_LOG_TAG"로 볼 수 있습니다.
rajeesh 2014 년

4
LogLevel.Full는 갱신이 존재하지 않습니다

121

개조 2.0 :

업데이트 : @by Marcus Pöhls

개조 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의 네 가지 로그 수준이 있습니다. 각 로그 수준을 안내하고 출력을 설명합니다.

추가 정보는 다음을 참조하십시오. Retrofit 2 — 요청 및 응답 기록

이전 답변 :

Retrofit 2에 더 이상 로그인하지 않습니다. 개발 팀은 로깅 기능을 제거했습니다. 솔직히 말해서 로깅 기능은 그다지 신뢰할 수 없었습니다. Jake Wharton은 기록 된 메시지 또는 객체가 가정 된 값이며 사실임을 증명할 수 없다고 명시 적으로 언급했습니다. 서버에 도착하는 실제 요청에는 변경된 요청 본문 또는 다른 것이있을 수 있습니다.

기본적으로 통합 로깅이 없지만 모든 Java 로거를 활용하여 사용자 정의 된 OkHttp 인터셉터 내에서 사용할 수 있습니다.

Retrofit 2에 대한 자세한 내용은 다음을 참조하십시오. Retrofit — 시작하기 및 Android 클라이언트 만들기


1
Retrofit 2.0 로그인 관련 게시물도 있습니다 : futurestud.io/blog/retrofit-2-log-requests-and-responses
peitek

모든 것을 복잡하게 만드는 좋은 방법입니다. Jersey 1 대 Jersey 2 로깅을 상기시킵니다. 더 많은 상용구 코드 ....
breakline

이 방법으로 인터셉터를 추가하면 OkHttp v3에서 UnsupportedOperationException이 발생합니다. 새로운 방법은 다음과 같습니다. OkHttpClient.Builder (). addInterceptor (logging) .build () github.com/square/okhttp/issues/2219
Amagi82

@JawadLeWywadi 그래 당신이 몸 인쇄 할 수있는이 코드를 사용
Dhaval Jivani

Retrofit 2의 경우 이것은 훨씬 쉽습니다.
Gary99

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 오류 코드 가있는 경우 여기에 인터셉터가 있습니다. 이벤트를 전송하기 위해 eventbus를 사용합니다.

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

기본 + 본문을 수행하는 방법이없는 것 같지만 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

이 코드가 로깅에 도움이되기를 바랍니다.
당신은 당신의 Build.Gradle다음 make에 인터셉터를 추가해야합니다 RetrofitClient.

첫 번째 단계

이 줄을 귀하의 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.