[java] 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()우리가 개조 1 사용하는 데 사용하는?



답변

Retrofit 2에서는 HttpLoggingInterceptor 를 사용해야합니다 .

에 종속성을 추가하십시오 build.gradle. 2019 년 10 월 기준 최신 버전 :

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

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 :

이전 Retrofit 버전에는 이전 버전이 필요할 수 있습니다 logging-interceptor. 자세한 내용은 의견 섹션을보십시오.


답변

나는 당신이 그 일을 만났고 나는 Retrofit : Android에서 API로 작업하는 것을 좋아합니다 (여기 링크가 있습니다 ). guys 🙂 그리고 저자는 Retrofit 1.9에 대한 Log 메소드와 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 의 도움으로 로깅 메소드를 추가하는 방법입니다 . 또한 내가 위에서 언급 한 책의 독자라면 Retrofit 2.0에는 더 이상 로그 방법이 없다고 말할 수 있습니다. 그것에 대해.

// Retrofit의 Log 메소드에 익숙하지 않은 경우 더 공유하고 싶습니다.

또한 선택할 수있는 몇 가지 로깅 수준이 있습니다. 나는 대부분 Level.BODY를 사용합니다 .

여기에 이미지 설명을 입력하십시오

그림 내에서 거의 모든 http 직원을 찾을 수 있습니다 : 헤더, 내용 및 응답 등

때로는 파티에 참석할 모든 손님이 필요하지 않습니다. 인터넷 연결이 성공적으로 연결되어 있는지, Activiy & Fragmetn 내에서 인터넷 전화가 제대로 연결되었는지 확인하고 싶습니다. 그런 다음 Level.BASIC을 자유롭게 사용할 수 있습니다 .

여기에 이미지 설명을 입력하십시오

상태 코드 200 OK 를 찾을 수 있습니까 ? 그게 다야 🙂

또한 또 하나의 Level.HEADERS가 있는데 , 이는 네트워크의 헤더 만 반환합니다. 물론 여기에 다른 그림이 있습니다.

여기에 이미지 설명을 입력하십시오

이것이 모든 로깅 트릭입니다.)

그리고 나는 많은 것을 배웠 자습서를 공유하고 싶습니다 있다 . 그들은 Retrofit과 관련된 거의 모든 것에 대해 이야기하는 훌륭한 게시물을 가지고 있으며 Retrofit 2.0이 출시되는 동안 게시물을 계속 업데이트하고 있습니다. 많은 시간을 절약 할 수 있다고 생각되는 작업을 살펴보십시오.


답변

다음은 Interceptor요청 및 응답 본문을 모두 기록하는 로그입니다 (OkHttp 문서 및 기타 SO 답변의 예제를 기반으로 Timber 사용).

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


답변

이 시도:

Request request = chain.request();
Buffer buffer = new Buffer();
request.body().writeTo(buffer);
String body = buffer.readUtf8();

그 후, body관심있는 JSON이 있습니다.


답변

내가 직면 한 주요 문제는 동적으로 헤더를 추가하고 디버그 logcat에 로깅하는 것이 었습니다. 두 개의 인터셉터를 추가하려고했습니다. 하나는 로깅을위한 것이고 다른 하나는 이동 중에 헤더를 추가하기위한 것입니다 (토큰 인증). 문제는 .addInterceptor 또는 .addNetworkInterceptor 일 수 있다는 것이 었습니다. Jake Wharton이 “네트워크 인터셉터는 항상 응용 프로그램 인터셉터를 따릅니다. 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();


답변

setLogLevel ()이 최종 2.0 버전의 Retrofit에서 반환되는지 모르겠지만 지금은 인터셉터를 사용하여 로깅 할 수 있습니다.

OkHttp 위키에서 좋은 예를 찾을 수 있습니다 : https://github.com/square/okhttp/wiki/Interceptors

OkHttpClient client = new OkHttpClient();
client.interceptors().add(new LoggingInterceptor());

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://www.yourjsonapi.com")
        .addConverterFactory(GsonConverterFactory.create())
        .client(client)
        .build();


답변

Retrofit2 및 okhttp3을 사용하는 경우 인터셉터가 큐별로 작동한다는 것을 알아야합니다. 따라서 다른 인터셉터 다음에 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))//first
                .addInterceptor(new OAuthInterceptor(context))//second
                .authenticator(new BearerTokenAuthenticator(context))
                .addInterceptor(loggingInterceptor)//third, log at the end
                .build();