Skip to content

davidafsilva/vertx-logging-interceptor

Repository files navigation

Vertx Logging Interceptor

Master Build Status Coverage Report Latest Release License

This small library plugs into Vert.x's logging delegation by leveraging its flexible configuration, allowing third-party interceptors to be built and plugged into the application logging mechanism.

Table of Contents

Usage

Import

  1. Add maven central repository to your configuration
  2. Import the library

Gradle

Groovy:

repositories {
    mavenCentral()
}
dependencies {
    implementation("pt.davidafsilva.vertx:vertx-logging-interceptor:0.1.3")
}

Maven

<dependencies>
  <dependency>
    <groupId>pt.davidafsilva.vertx</groupId>
    <artifactId>vertx-logging-interceptor</artifactId>
    <version>0.1.3</version>
  </dependency>
</dependencies>

Configuration

Similarly, as Vert.x, it provides 4 possible configurations. One for each supported logging library:

Factory Description
VertxJULLogDelegateFactory Creates loggers bound to Java Util Logging
VertxLog4jLogDelegateFactory Creates loggers bound to Apache Log4j (v1)
VertxLog4j2LogDelegateFactory Creates loggers bound to Apache Log4j (v2)
VertxSLF4JLogDelegateFactory Creates loggers bound to the available SLF4J implementation

Choose one of the above class names (use FQN) according to your runtime logging library and configure it through the vertx.logger-delegate-factory-class-name system property. Alternatively, you can set it through a JVM argument:

-Dvertx.logger-delegate-factory-class-name=pt.davidafsilva.vertx.logging.factory.<chosen delegate factory>

Interceptor Creation

After configuring the appropriate logger factory, creating an interceptor can be achieved by implementing the LogInterceptor interface along with the required methods. Optionally, you can opt for NoOpLogInterceptor which provides an empty skeleton for all the required methods.

There are essentially two types of interceptors, blocking and non-blocking.
Blocking interceptors are characterized by returning LogPropagation.BLOCK as the/a possible outcome of an interception call. These interceptors, upon returning LogPropagation.BLOCK will effectively stop both the execution of any other interceptors in the chain alongside with the actual logging to the underlying logger.
On the other hand, non-blocking interceptors do not affect any sub-sequent operations. They always return LogPropagation.CONTINUE.

Blocking Interceptors

object LogMessagesCounterInterceptor : NoOpLogInterceptor {
    private val counter = AtomicLong()

    override fun intercept(logger: String, message: Any?): LogPropagation {
        counter.incrementAndGet()
        return LogPropagation.CONTINUE
    }
    
    fun totalLoggedMessages(): Long = counter.get()
}

Non-Blocking Interceptors

object BadWordLogInterceptor : NoOpLogInterceptor {
    override fun intercept(logger: String, message: Any?): LogPropagation {
        val strMessage = message.toString()
        return when {
            "badword" in strMessage -> LogPropagation.BLOCK
            else -> LogPropagation.CONTINUE
        }
    }
}
⚠️ There's currently no support for mutating log messages.

Registering Interceptors

Registering your own or built-in interceptors through the centralized LogInterceptors storage layer.

LogInterceptors.register(BadWordLogInterceptor) // applicable to all levels
LogInterceptors.register(Level.WARN, ThreadBlockedLogInterceptor(registry)) // built-in interceptor
LogInterceptors.register(Level.INFO, LogMessagesCounterInterceptor()) // counts all info messages

Built-In Interceptors

ThreadBlockedLogInterceptor

This interceptor aims to capture thread blocks that are detect by Vert.x BlockedThreadChecker, providing a metric around it.

The exported metric has the following properties:

Name type Tags
vertx_thread_blocked_total Counter thread: the name of the blocked thread

Note that the metric name can be customized by specifying the optional metricName constructor parameter.

For the sake of illustration, the metric exported through a prometheus formatted endpoint:

# HELP vertx_thread_blocked_total Number of thread blocks detected
# TYPE vertx_thread_blocked_total counter
vertx_thread_blocked_total{thread="vert.x-eventloop-thread-0,5,main",} 1.0

Building

At the project root, run the following command:

./gradlew clean build

The above command will run both the tests and verification checks.