2

My concern is about how much OkHttp log should be printed out.
On certain screens of my app, there are way too many API calls --> logcat is flooded so I'd like to limit/ turn off logging there except for one-off debugging

I'm new to Dagger 2 and dependency injection, been following this tutorial.

I have the following which works but I'm not sure if there is any bad practice there or if it could be improved further:
(There are about 20 Retrofit API interfaces/ 20 different endpoints in my app)

@Module
public class NetModule {

    private String mBaseUrl;
    private final HttpLoggingInterceptor LOGGING_FULL = new HttpLoggingInterceptor().setLevel
        (HttpLoggingInterceptor
                .Level.BODY);
private final HttpLoggingInterceptor LOGGING_HEADERS = new HttpLoggingInterceptor().setLevel
        (HttpLoggingInterceptor
                .Level.HEADERS);

    // Constructor needs one parameter to instantiate.
    public NetModule(String baseUrl) {
        this.mBaseUrl = baseUrl;
    }

    @Provides
    @Singleton
    OkHttpClient.Builder provideOkHttpClientBuilder() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        //...
        return builder;
    }

    @Provides
    @Singleton
    Retrofit.Builder provideRetrofitBuilder() {
        return new Retrofit.Builder()
                .baseUrl(mBaseUrl);
    }

    @Provides
    @Singleton
    Api1 provideApi1(OkHttpClient.Builder okHttpClientBuilder, Retrofit.Builder retrofitBuilder) {
        if (BuildConfig.DEBUG || !BuildConfig.FLAVOR.equals(FLAVOUR_PRODUCTION)) {
            okHttpClientBuilder.addInterceptor(LOGGING_HEADERS);
        }
        return retrofitBuilder.client(okHttpClientBuilder.build()).build().create(Api1.class);
    }
    @Provides
    @Named("logging_full")
    @Singleton
    Api1 provideApi1FullLog(OkHttpClient.Builder okHttpClientBuilder, Retrofit.Builder retrofitBuilder) {
        if (BuildConfig.DEBUG || !BuildConfig.FLAVOR.equals(FLAVOUR_PRODUCTION)) {
            okHttpClientBuilder.addInterceptor(LOGGING_FULL);
        }
        return retrofitBuilder.client(okHttpClientBuilder.build()).build().create(Api1.class);
    }
    //... Repeats for Api2, Api3, ..., Api20

}

Usage:
1) In most cases, logging body is not required so:

@Inject
Api1 api1;

2) In some cases, logging body is required then:

@Inject
@Named("logging_full")
Api1 api2;
ericn
  • 12,476
  • 16
  • 84
  • 127

1 Answers1

2

I think this is an overengineered solution. If you need different behavior at the http interceptor layer, you shouldn't have to deal with different instances of Api, httpclients, or anything else.

This would be my first approach at your problem.

1) Use a single instance for the Api and a single instance for OkHttpClient (no multiple Dagger providers)

2) Have a single interceptor for debug, and none for production. This way you avoid the if( Build.DEBUG ) logic.

3) Add a custom header per endpoint

   interface YourApi {

      @Headers("YourCustomLoggingHeader: HEADERS")
      @GET("/your_path")
      ReturnType yourApiMethod( ParamType p);
   }

4) If the interceptor was injected (debug build), then check for the header in the intercept method and log accordingly.

    @Override public Response intercept(Chain chain) throws IOException {

         String headerValue = chain.request().headers().get("YourCustomLoggingHeader");

         if( TextUtils.isEmpty(headervalue)){
            return = chain.proceed(request);
         }

         // TODO remove header for real request

         switch( headerValue ){
           case "HEADERS":
                //TODO log headers 
                break;
           case "BODY":
                //TODO log body 
                break;
         }
    }

This is pseudo code, as I am not on the IDE.

Robert Estivill
  • 12,369
  • 8
  • 43
  • 64
  • thanks @RobertEstivill but you also missed the point :) I'm not concerned about including/ excluding HTTP headers. My concern is about how much OkHttp log should be printed out. On certain screens, there are way too many API calls --> logcat is flooded so I'd like to limit/ turn off logging there except for one-off debugging – ericn Jun 21 '17 at 09:02
  • The Header serves as a per/endpoint configuration. Of course you can also base logging behavior on all the request attributes (example: path). But having an externally configured attribute is a more visible option. If you need to change behavior on runtime, then you will have to hold on to the HttpLogginInterceptor instance and modify it's state so it behaves differently between calls – Robert Estivill Jun 21 '17 at 09:17