Kotlin (Ktor, Spring Boot) OpenTelemetry style for Maple: zero-code Java agent or manual SDK with OTLP HTTP exporters, inline endpoint + ingest key, semconv resource attributes, OTLP-bridged logs.
Pro shows the line behind each finding and how to fix it
Scanned 10/1/2026
npx -y skills add MapleTechLabs/maple --skill maple-kotlin-style --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Maple Kotlin Style?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/mapletechlabs-maple-kotlin-style)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: maple-kotlin-style
description: "Kotlin (Ktor, Spring Boot) OpenTelemetry style for Maple: zero-code Java agent or manual SDK with OTLP HTTP exporters, inline endpoint + ingest key, semconv resource attributes, OTLP-bridged logs."
---
# Maple Kotlin style
Kotlin runs on the JVM, so the same OpenTelemetry Java agent and SDK apply. Prefer the agent for Spring Boot / Ktor servers; fall back to the manual SDK only for native-image or sealed-module builds.
## Zero-code: Java agent (recommended)
```bash
curl -sLO https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
java \
-javaagent:./opentelemetry-javaagent.jar \
-Dotel.service.name=orders-api \
-Dotel.exporter.otlp.protocol=http/protobuf \
-Dotel.exporter.otlp.endpoint=https://ingest.maple.dev \
-Dotel.exporter.otlp.headers="authorization=Bearer MAPLE_TEST" \
-Dotel.resource.attributes="vcs.repository.url.full=https://github.com/acme/orders-api,vcs.ref.head.revision=${GITHUB_SHA:-}" \
-jar build/libs/app.jar
```
Replace `MAPLE_TEST` with the project's real Maple ingest key once it exists. EU organizations use `https://ingest.eu.maple.dev` as the endpoint. Keep these flags inline where the JVM is launched (`Procfile`, `Dockerfile`, or `JAVA_TOOL_OPTIONS`). Do not move them behind unset env vars. The agent does not read `application.yml`.
The agent auto-instruments Ktor, Spring Boot (MVC, WebFlux), kotlinx.coroutines context propagation, JDBC (so Exposed), R2DBC, Kafka, gRPC, OkHttp, AWS SDK, and more.
## Manual SDK (Ktor, no agent)
```kotlin
val MAPLE_ENDPOINT = "https://ingest.maple.dev" // EU: https://ingest.eu.maple.dev
val MAPLE_KEY = "MAPLE_TEST" // public ingest key (maple_pk_…), or MAPLE_TEST until the user has one
fun initTelemetry(): OpenTelemetrySdk {
val headers = mapOf("authorization" to "Bearer $MAPLE_KEY")
val resource = Resource.getDefault().merge(Resource.create(
Attributes.builder()
.put("service.name", "orders-api")
.put("deployment.environment.name",
System.getenv("DEPLOYMENT_ENV") ?: "development")
.put("vcs.repository.url.full", "https://github.com/acme/orders-api")
.put("vcs.ref.head.revision", System.getenv("GITHUB_SHA") ?: "")
.build()))
val spanExporter = OtlpHttpSpanExporter.builder()
.setEndpoint("$MAPLE_ENDPOINT/v1/traces")
.setHeaders { headers }
.build()
return OpenTelemetrySdk.builder()
.setTracerProvider(SdkTracerProvider.builder()
.addSpanProcessor(BatchSpanProcessor.builder(spanExporter).build())
.setResource(resource)
.build())
.buildAndRegisterGlobal()
}
```
Add the equivalent log and metric exporters in the same builder. Resolve versions through `io.opentelemetry:opentelemetry-bom`.
## Bounded business spans
```kotlin
private val tracer = GlobalOpenTelemetry.getTracer("orders.api")
suspend fun submitOrder(orderId: String, tenantId: String) {
val span = tracer.spanBuilder("order.submit")
.setAttribute("tenant.id", tenantId)
.setAttribute("order.id", orderId)
.startSpan()
try {
withContext(span.asContextElement()) {
chargeOrder(orderId)
}
} catch (e: Exception) {
span.recordException(e)
span.setStatus(StatusCode.ERROR, e.message ?: "")
throw e
} finally {
span.end()
}
}
```
`asContextElement()` comes from `io.opentelemetry:opentelemetry-extension-kotlin` (`import io.opentelemetry.extension.kotlin.asContextElement`). Do not call `span.makeCurrent()` in a `suspend` function: the scope is thread-local and leaks or is lost when the coroutine resumes on another thread.
## Logs
Bridge whatever the project uses (Logback, SLF4J, Log4j2). With the agent, Logback and Log4j2 are bridged automatically. With the manual SDK, add `opentelemetry-logback-appender-1.0` (or `opentelemetry-log4j-appender-2.17`), declare its appender in `logback.xml`, and call `OpenTelemetryAppender.install(sdk)` after building the SDK. Existing logger calls then carry `trace_id` / `span_id` and reach Maple. Do not replace the user's existing logger.
## Coexistence
If the project runs a Datadog, New Relic, or Honeycomb agent, leave it in place. Two bytecode agents on one JVM can conflict, so test the combination once before shipping.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!