Insights

Request profiling, performance metrics, and a built-in debug GUI.

Enabling insights

Insights is enabled per-route group by calling instrumentWithInsights() after installing the Kontainer. The insights config controls whether collection is active.

fun Route.installApiKontainer(app: App<MyConfig>, insights: InsightsConfig?) {
    installKontainer { call ->
        app.kontainers.create {
            with { call.currentUserProvider() }
            insights?.let { with { insights } }
        }
    }

    instrumentWithInsights(insights)
}

Mounting the GUI

Mount the built-in debug toolbar on your admin host. It provides a web UI for browsing recent requests, database queries, and timing breakdowns.

routing {
    host("admin.*".toRegex()) {
        installWwwKontainer(app, config.api.insights)

        // Mount insights GUI at /_/insights/
        init.use(InsightsGui::class) {
            mount()
        }
    }
}

What it collects

Insights uses per-request Kontainer scoping to collect data throughout a request's lifecycle. Each collector gathers one kind of data:

RequestCollector

HTTP method, URI, headers, query parameters.

ResponseCollector

Status code, response time, content type.

VaultCollector

Database queries executed, query times, results.

RuntimeCollector

JVM heap, thread count, GC stats.

KontainerCollector

Services created, injection times.

UserCollector

Authenticated user info for the request.

How it works

Each collector is a dynamic Kontainer service — a new instance is created for every request. Throughout the request lifecycle, collectors accumulate data. At the end of the request, the collected data is serialized into the API response as metadata.

Insights is the reason Kontainer has per-request scoping. Each collector is a dynamic service that accumulates data throughout one request, then gets serialized and stored. No external APM tools required.