Logging

genhttp-kt logs through SLF4J, the logging facade of the JVM, and allows to create loggers via the Server interface. If there is an SLF4J provider on the classpath (such as Logback, Log4j 2 or slf4j-simple), the server logs through it. Otherwise, the host falls back to a console logger of its own (and SLF4J warns once at startup that it found no provider).

Logging Information

The following code shows to obtain a logger from the server instance in a custom Handler implementation. It is recommended to create the logger once in the preparation phase and store the reference somewhere. You can use this pattern anywhere where you have access to Server (e.g. via request.server).

Kotlin
import org.genhttp.api.content.Handler
import org.genhttp.api.infrastructure.Server
import org.genhttp.api.protocol.Request
import org.genhttp.api.protocol.Response

import org.slf4j.Logger

class MyHandler : Handler {

    private var logger: Logger? = null

    override suspend fun prepare(server: Server) {
        logger = server.logging.getLogger(MyHandler::class.java.name)
    }

    override suspend fun handle(request: Request): Response? {
        logger?.info("I am logging important information")

        return null
    }

}

Customize Logging

To log through a logging framework, add its SLF4J provider to your project - genhttp-kt picks it up automatically, and the framework is configured as usual (e.g. with a logback.xml):

build.gradle.kts
dependencies {
    implementation("ch.qos.logback:logback-classic:1.5.18")
}

This way, you can also use OpenTelemetry for logging: its Java agent captures the logs written via Logback or Log4j and exports them via OTLP, without any change to your code:

Shell
java -javaagent:opentelemetry-javaagent.jar -Dotel.service.name=my-service -jar my-service.jar

The logging() method of the host builder allows to pass a custom logging factory (org.slf4j.ILoggerFactory) that should be used by the application instead. The following example uses the console logger of genhttp-kt with debug output:

Kotlin
import org.genhttp.engine.internal.Host
import org.genhttp.engine.shared.infrastructure.logging.ConsoleLoggerFactory
import org.genhttp.modules.layouting.Layout
import org.genhttp.modules.practices.defaults

import org.slf4j.event.Level

suspend fun main() {
    val handler = Layout.create()

    Host.create()
        .logging(ConsoleLoggerFactory(Level.DEBUG))
        .handler(handler)
        .defaults()
        .run()
}

To disable logging, you can pass a no-operation logger factory:

Kotlin
import org.genhttp.engine.internal.Host

import org.slf4j.helpers.NOPLoggerFactory

val host = Host.create()
    .logging(NOPLoggerFactory())

Request Logging

By default, genhttp-kt will install a concern that logs every request and the response it generated (with the logger GenHTTP.Requests at level INFO).

Shell
info: GenHTTP.Requests
      GET /api/ - HTTP 200 - 12 bytes - 18.52 ms
info: GenHTTP.Requests
      GET /favicon.ico - HTTP 404 - 0 bytes - 1.49 ms
info: GenHTTP.Requests
      GET /assets/styles.css - HTTP 200 - 0 bytes - 1.03 ms

If you would like to opt-out of request logging, you can pass a flag to the logging() method of the host builder. ConsoleLoggerFactory.createDefault() returns the factory the host uses by default:

Kotlin
import org.genhttp.engine.internal.Host
import org.genhttp.engine.shared.infrastructure.logging.ConsoleLoggerFactory
import org.genhttp.modules.layouting.Layout
import org.genhttp.modules.practices.defaults

suspend fun main() {
    val handler = Layout.create()

    Host.create()
        .logging(ConsoleLoggerFactory.createDefault(), logRequests = false)
        .handler(handler)
        .defaults()
        .run()
}

With a logging framework, you may also raise the level of the GenHTTP.Requests logger in its configuration instead.