Kotlin Integration
Coroutine-aware tracing for Kotlin and Ktor with automatic context propagation across suspend functions, Exposed ORM spans, and deep JVM runtime metrics — one Gradle dependency away.
How It Works
Add the Gradle Dependency
Add implementation("net.tigerops:tigerops-kotlin:0.1.+") to your build.gradle.kts dependencies block. The artifact includes the OpenTelemetry Kotlin SDK, coroutine context propagation, and OTLP exporters for TigerOps endpoints.
Attach the Java Agent
Add -javaagent:/path/to/tigerops-agent.jar to your JVM startup arguments. For Gradle tasks, set jvmArgs("-javaagent:...") in your application run task. The agent bytecode-instruments Ktor, JDBC, and HTTP client libraries automatically.
Configure via application.yaml
Set TIGEROPS_API_KEY, TIGEROPS_SERVICE_NAME, and TIGEROPS_ENVIRONMENT as environment variables or in application.yaml. Ktor's built-in config system is supported. Kotlin Multiplatform project configurations work with the jvm target.
Coroutine Spans & JVM Metrics
TigerOps automatically propagates trace context across coroutine suspensions and thread switches. Ktor request spans, Exposed query traces, coroutine dispatcher metrics, JVM heap data, and GC telemetry start flowing within seconds.
What You Get Out of the Box
Coroutine-Aware Context Propagation
Trace context flows automatically across suspend function boundaries, coroutine scope switches, and dispatcher changes. Child coroutines inherit the parent span context. withContext and async blocks preserve trace continuity without boilerplate.
Ktor Server Route Tracing
Every Ktor HTTP request creates a root span with route path, HTTP method, status code, and response time. Ktor pipeline phase timings are captured as ordered child spans. Plugin and feature execution times are individually measured.
Ktor HTTP Client Spans
Outbound HTTP calls via the Ktor HttpClient are auto-instrumented. Each call creates a child span with target host, method, response status, and duration. W3C TraceContext headers are injected into outgoing requests automatically.
Exposed ORM Query Spans
SQL queries executed via JetBrains Exposed DSL and DAO layers become child spans with normalized SQL text, table names, execution time, and affected row count. Transaction boundary spans wrap sets of related queries for easy grouping.
Kotlin Flow & Channel Metrics
TigerOps measures Kotlin Flow collection rates, backpressure buffer utilization, and channel send/receive latency. Flow operators that introduce delays or transform-heavy workloads are highlighted in the trace timeline.
JVM & Coroutine Dispatcher Metrics
Continuous JVM metrics include heap, GC pauses, and thread counts. Coroutine dispatcher queue depth, active coroutine count, and runnable-waiting ratios are emitted per named dispatcher (IO, Default, Unconfined).
Install & Initialize
One Gradle dependency and one JVM flag. Full Kotlin and Ktor observability.
// build.gradle.kts
dependencies {
implementation("net.tigerops:tigerops-kotlin:0.1.+")
}
tasks.withType<JavaExec> {
jvmArgs("-javaagent:/path/to/tigerops-agent.jar")
}
// application.yaml
tigerops:
api-key: ${TIGEROPS_API_KEY}
service-name: my-kotlin-app
environment: production
ktor:
trace-pipeline-phases: true
slow-query-threshold-ms: 100
// Application.kt — Ktor server setup
import net.tigerops.ktor.TigerOps
fun main() {
embeddedServer(Netty, port = 8080) {
install(TigerOps) {
serviceName = "my-kotlin-app"
environment = "production"
}
routing {
get("/orders/{id}") {
val orderId = call.parameters["id"]!!
val order = fetchOrder(orderId) // auto-traced DB call
call.respond(order)
}
}
}.start(wait = true)
}
// Manual span in a suspend function
import net.tigerops.span
suspend fun processPayment(paymentId: String): Result {
return span("payment.process") { s ->
s.setAttribute("payment.id", paymentId)
val validated = validatePayment(paymentId) // suspends, context preserved
chargePayment(validated) // suspends, context preserved
}
}Common Questions
Which Kotlin and Ktor versions are supported?
Kotlin 1.8, 1.9, and 2.x are supported. Ktor 2.x and 3.x server and client are instrumented. The Java agent requires JVM 11 or higher. Kotlin Multiplatform JVM targets are supported; native and JS targets use the manual SDK.
How does TigerOps propagate context across structured concurrency scopes?
TigerOps installs a custom CoroutineContext element that carries the active span. When you launch or async a new coroutine, Kotlin structured concurrency copies the parent context, including the TigerOps span element, into the child scope automatically.
Does TigerOps work with Spring Boot Kotlin applications?
Yes. The Java agent instruments Spring MVC and Spring WebFlux regardless of language. For Kotlin-idiomatic code, the tigerops-kotlin module adds coroutine-aware span helpers and suspend-compatible span builder functions on top of the Spring instrumentation.
Can I trace Kotlin Multiplatform shared business logic?
Shared KMP code can use the tigerops-kmp-common module which provides an expect/actual span API. The JVM actual delegates to the full OpenTelemetry SDK; the native and JS actuals use lightweight no-op or platform-specific implementations.
What overhead does coroutine context propagation add?
TigerOps uses a single immutable CoroutineContext element per trace. Context inheritance during coroutine creation is O(1). Benchmarks show under 50ns added overhead per coroutine launch with tracing enabled at the default 10% sampling rate.
Full Kotlin Observability in One Gradle Dependency
Coroutine-aware tracing, Ktor spans, Exposed ORM visibility, and JVM metrics — no manual instrumentation required.