如何使用Retrofit-Android记录请求和响应正文?

Jag*_*uar 117 logging android retrofit retrofit2

我在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();
Run Code Online (Sandbox Code Playgroud)

编辑:此代码现在正在运行.我不知道它为什么不提前工作.可能是因为我正在使用一些旧版本的改造.

Dha*_*ani 112

改造2.0:

更新:@byMarcusPö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'
Run Code Online (Sandbox Code Playgroud)

您还可以访问Square关于此拦截器的GitHub页面

添加日志到改造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();
Run Code Online (Sandbox Code Playgroud)

我们建议将日志记录添加为最后一个拦截器,因为这也会将您使用先前拦截器添加的信息记录到您的请求中.

日志级别

记录太多信息会炸毁您的Android监视器,这就是为什么OkHttp的日志拦截器有四个日志级别:NONE,BASIC,HEADERS,BODY.我们将引导您完成每个日志级别并描述其输出.

更多信息,请访问:改造2 - 日志请求和响应

老答案:

没有登录Retrofit 2了.开发团队删除了日志记录功能.说实话,记录功能无论如何都不可靠.杰克沃顿明确表示,记录的消息或对象是假定值,并且无法证明它们是真实的.到达服务器的实际请求可能具有已更改的请求正文或其他内容.

即使默认情况下没有集成日志记录,您也可以利用任何Java记录器并在自定义的OkHttp拦截器中使用它.

有关Retrofit 2的更多信息,请参阅: Retrofit - 入门和创建Android客户端


Ale*_*hko 87

我用过setLogLevel(LogLevel.FULL).setLog(new AndroidLog("YOUR_LOG_TAG")),它帮助了我.
UPDATE.
您还可以尝试将调试目的retrofit.client.Response用作响应模型

  • `AndroidLog`,那是什么类? (2认同)
  • 我知道了.不幸的是,这并没有给你"响应体",尽管它在文档中声明`LogLevel.FULL`**应该**给你'响应体'. (2认同)
  • LogLevel.Full在改造2中不存在 (2认同)

OWA*_*DVL 30

更新Retrofit 2.0.0-beta3

现在你必须使用okhttp3和builder.旧的拦截器也行不通.此响应是针对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'
Run Code Online (Sandbox Code Playgroud)

2.检查以下示例代码:

随着新的进口.如果不使用它,可以删除Rx,也可以删除不使用的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);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

奖金

我知道它是offtopic但我发现它很酷.

如果有未经授权的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;
  }
}
Run Code Online (Sandbox Code Playgroud)

代码取自https://github.com/AndreiD/UltimateAndroidTemplateRx(我的项目).

  • 很好的答案.在这个时间点它应该在顶部. (3认同)

Xer*_*dea 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();
Run Code Online (Sandbox Code Playgroud)

似乎在覆盖日志时,正文的前缀是类似的标记

[ 02-25 10:42:30.317 25645:26335 D/Retrofit ]
Run Code Online (Sandbox Code Playgroud)

所以通过调整自定义过滤器来记录基本+主体应该很容易.我正在使用黑名单,但根据您的需要也可以使用白名单.


Muk*_*mar 5

下面的代码适用于有标题和没有标题的打印日志请求和响应。注意:如果不使用标题,只需注释 .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();
Run Code Online (Sandbox Code Playgroud)