Skip to content

Captures HTTP client traffic and pretty prints it with any Java logger. Supported clients: OkHttp, OkHttp3, ApacheHttpClient.

License

Notifications You must be signed in to change notification settings

dkorobtsov/plinter

Repository files navigation

Plinter (Pretty Logging Interceptor)

This library makes working with APIs easy and convenient. Just attach interceptor to your favorite HTTP client and forward all requests and responses to any Java logger (or use default one). Simple as that.

release-badge Maven Central DOI

License: MIT CodeQL Quality Gate Status

Coverage Maintainability Rating Security Rating Reliability Rating

Console Logging Example

Features

  • No configuration needed, works as is
  • Easy to customize if needed
  • Several output formats supported out of the box
  • Supports most popular HTTP clients
  • Supports all Java/Kotlin loggers
  • Can be used with Feign or Retrofit
  • Works with clients created by Swagger-codegen
  • Pretty prints all HTTP request and response details
  • Pretty prints JSON, XML and HTML bodies, etc. (basically any readable content)

Clients supported

Loggers supported

Any Java or Kotlin logger - jul, log4j, slf4j, logback, log4j2 etc

Quickstart

Interceptor should work as is - without any additional configuration, only need to add appropriate dependency. By default, JUL logger will be used with INFO level and minimal format displaying message only.

All artefacts are deployed to: https://repo.maven.apache.org/maven2/io/github/dkorobtsov/plinter/

Gradle

repositories {
    mavenCentral()
}

OkHttp

To start using interceptor with OkHttp client add following dependency to classpath:

Maven:

<dependency>
    <groupId>io.github.dkorobtsov.plinter</groupId>
    <artifactId>okhttp-interceptor</artifactId>
</dependency>

Gradle:

dependencies {
  implementation("io.github.dkorobtsov.plinter:okhttp-interceptor:$LATEST_VERSION")
}

Check releases for latest interceptor version.

Basic usage example:

    OkHttpLoggingInterceptor interceptor = new OkHttpLoggingInterceptor(LoggerConfig.builder().build());
    
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(interceptor)
        .build();

Tip: Can be used with REST client created by swagger-codegen using okhttp-gson template.

OkHttp3

To start using interceptor with OkHttp3 client add following dependency to classpath:

Maven:

<dependency>
    <groupId>io.github.dkorobtsov.plinter</groupId>
    <artifactId>okhttp3-interceptor</artifactId>
    <version>$LATEST_VERSION</version>
</dependency>

Gradle:

dependencies {
  implementation("io.github.dkorobtsov.plinter:okhttp3-interceptor:$LATEST_VERSION")
}

Check releases for latest interceptor version.

Basic usage example:

    OkHttp3LoggingInterceptor interceptor = new OkHttp3LoggingInterceptor(LoggerConfig.builder().build());

    OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(interceptor)
        .build();

Apache HttpClient

To start using interceptor with Apache Http client add following dependency to classpath:

Maven:

<dependency>
    <groupId>io.github.dkorobtsov.plinter</groupId>
    <artifactId>apache-interceptor</artifactId>
    <version>$LATEST_VERSION</version>
</dependency>

Gradle:

dependencies {
  implementation("io.github.dkorobtsov.plinter:apache-interceptor:$LATEST_VERSION")
}

Check releases for latest interceptor version.

Basic usage example:

    ApacheRequestInterceptor requestInterceptor = new ApacheRequestInterceptor(LoggerConfig.builder().build());
    ApacheResponseInterceptor responseInterceptor = new ApacheResponseInterceptor(LoggerConfig.builder().build());
    
    CloseableHttpClient client = HttpClientBuilder
        .create()
        .addInterceptorFirst(requestInterceptor)
        .addInterceptorFirst(responseInterceptor)
        .setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy())
        .build();   

Advanced Configuration

Interceptor can be used with any existing Java logger - just need to provide your own LogWriter implementation.

Simple configuration for Log4j2 with printing in separate thread:

    OkHttp3LoggingInterceptor interceptor = new OkHttp3LoggingInterceptor(
        LoggerConfig.builder()
            .logger(new LogWriter() {
              final Logger logger = LogManager.getLogger("HttpLogger");

              @Override
              public void log(String msg) {
                logger.debug(msg);
              }
            })
            .withThreadInfo(true)
            .loggable(true)
            .maxLineLength(180)
            .level(Level.BASIC)
            .executor(Executors.newSingleThreadExecutor(r -> new Thread(r, "HttpPrinter")))
            .build());

    OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(interceptor)
        .build();

    // Can be used with Retrofit or Feign
    Retrofit retrofitAdapter = new Retrofit.Builder()
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .baseUrl("https://.../")
        .client(okHttpClient)
        .build();

Or more sophisticated approach with custom logging pattern.

    LogWriter log4j2Writer = new LogWriter() {
      final String OK_HTTP_LOG_PATTERN = "[OkHTTP] %msg%n";
      final Logger log = LogManager.getLogger("OkHttpLogger");

      {
        final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        final Configuration config = ctx.getConfiguration();

        LoggerConfig loggerConfig = new LoggerConfig("OkHttpLogger", Level.TRACE, false);
        PatternLayout layout = PatternLayout
            .newBuilder()
            .withPattern(OK_HTTP_LOG_PATTERN)
            .build();

        final Appender appender = ConsoleAppender
            .newBuilder()
            .withName("OkHttpConsoleAppender")
            .withLayout(layout)
            .build();

        appender.start();

        loggerConfig.addAppender(appender, Level.TRACE, null);
        config.addLogger("OkHttpLogger", loggerConfig);
        ctx.updateLoggers();
      }

      @Override
      public void log(String msg) {
        log.debug(msg);
      }
    };

    OkHttp3LoggingInterceptor interceptor = new OkHttp3LoggingInterceptor(LoggerConfig.builder()
        .logger(log4j2Writer)
        .build());

Logger Configuration

Interceptor can be configured by providing your own LoggerConfig.

Check supported options descriptions below:

Format

Default logger's format can be easily changed using predefined JUL logging patterns:

.format(LogFormatter.JUL_DATE_LEVEL_MESSAGE)
        .JUL_FULL                // [Date][Thread][Level] Message
        .JUL_DATE_LEVEL_MESSAGE  // [Date][Level] Message
        .JUL_THREAD_MESSAGE      // [Thread] Message
        .JUL_LEVEL_MESSAGE       // [Level] Message
        .JUL_DATE_MESSAGE        // [Date] Message
        .JUL_MESSAGE_ONLY        // Message

Note that given setting works only with default JUL logger, if logger is provided manually, built-in formatters will be ignored.

Tip: when logger is in "message only" mode, json response can be copied from console and converted to POJO with this service in a matter of seconds.

Executor

Add executor that allows to perform sequential concurrent print.

        .executor(Executors.newSingleThreadExecutor(r -> new Thread(r, "HttpPrinter")))

Line Length

If needed, max output length can be modified. Default value: 110. Valid values: 80-180.

        .maxLineLength(160) 

Thread Info

If enabled, current thread name will be present in intercepted event's header.

        .withThreadInfo(true/false) 

Level

.setLevel(Level.BASIC)
	      .NONE       // No logs
	      .BASIC      // Logging url, method, headers and body.
	      .HEADERS    // Logging url, method and headers
	      .BODY       // Logging url, method and body

Loggable

Enable or disable interceptor. If set to false, interceptor will ignore all traffic.

        .loggable(true/false) 

Credits

This library was heavily inspired and initially forked from LoggingInterceptor for Android by Ihsan Bal and completely rewritten by Dmitri Korobtsov to provide more flexibility and support for native Java loggers. Support for OkHttp2 and Apache clients introduced by Andrew Zakordonets. Part of internal requests/responses handling logic based on OkHttp3 client's code with slight modifications to remove external dependencies.

Contribution Guidelines

Contributions are welcome from everyone. To ensure a smooth collaboration, please refer to the CONTRIBUTING.md file for detailed instructions.


Find this library helpful? Show some support:

GitHub followers GitHub forks GitHub stars Twitter Follow


About

Captures HTTP client traffic and pretty prints it with any Java logger. Supported clients: OkHttp, OkHttp3, ApacheHttpClient.

Topics

Resources

License

Stars

Watchers

Forks

Languages