otel span exporter · jvm agent

cartographer.trace()

A JVM agent and Maven plugin that instruments every non-synthetic method — constructors included — under a package you configure, wrapping each in an OpenTelemetry span for the duration of your test run.

dev & test tooling only — not for production workloads

Where the agent sits

The Maven plugin injects the agent into the test JVM with -javaagent, the same mechanism JaCoCo uses. The agent instruments matching classes at load time and records spans; the plugin and IDE view just read what it writes.

maven-plugin configures test JVM test JVM -javaagent attached cartographer-agent Byte Buddy + OTel SDK target/cartographer/ JSON per test method OTLP backend Jaeger · Grafana · Datadog intellij-plugin reads target/cartographer/ configures runs in writes exports (optional) visualized by

A trace, rendered

Spans nest by call depth, drawn to scale — the fastest way to spot a method being re-executed when it shouldn't be: a cache miss, a redundant query, an unwanted re-init.

trace_id: com.example.MyTest.testFindUser total 72ms
0 20ms 40ms 60ms 80ms testFindUser UserRepository.load UserRepository.load cache lookup SELECT users WHERE id = ? UserRepository.load (dup) SELECT users WHERE id = ? (repeat) ▲ identical query, executed twice — cache never warmed

Cartographer surfaces this without a single added log line — it's just what the spans show.

Three modules

instrumentation

cartographer-agent

Does the actual instrumenting at class-load time via Byte Buddy, and exports OTel spans to disk and/or an OTLP endpoint.

build integration

cartographer-maven-plugin

Wires the agent into your test JVM. Includes a setup goal that adds the Maven profile to your pom.xml automatically.

ide view

cartographer-intellij-plugin

A tool window for browsing trace output as an in-IDE waterfall — no external Jaeger instance required.

Quick start

# let the plugin add the profile for you
$ mvn com.antwerkz:cartographer-maven-plugin:setup
$ mvn test -Dcartographer writing target/cartographer/com.example.MyTest.testFoo.json

Cartographer vs. Java Flight Recorder

JFR is a general-purpose, always-on JVM profiler built for production diagnostics. Cartographer is narrower on purpose — it exists to turn a single test run into a readable, per-test call trace.

Cartographer Java Flight Recorder
Primary use case Understanding one test's behavior — call structure, duplicate work, timing Low-overhead production profiling and incident diagnosis
Instrumentation scope Every non-synthetic method in a configured package, via bytecode rewriting at load time Sampling-based, plus opt-in JDK/JFR event types; not per-method call tracing
Granularity Exact — every call is a span, nested by call depth Statistical — stack samples at an interval, not exhaustive call capture
Output format OpenTelemetry spans, written per test method under target/cartographer/ .jfr binary recordings, opened in JDK Mission Control
Viewing the result In-IDE waterfall (IntelliJ plugin) or any OTLP/Jaeger-compatible backend JDK Mission Control, or third-party JFR viewers
Scope of a "run" One trace per test method, isolated from other tests where possible One recording per JVM process, spanning everything that ran in it
Setup Maven plugin adds -javaagent to the test JVM, mirroring JaCoCo Built into the JDK (8u262+/11+); enabled with JVM flags, no agent needed
Overhead model Higher per-method overhead by design — acceptable because it targets test runs, not production Designed for <1% overhead so it's safe to leave on in production
Intended environment Local dev and CI test runs only Development, CI, and production

They're complementary, not competing: reach for JFR when you need to know what a running JVM is doing; reach for Cartographer when you need to know exactly what one test did, and why it did it twice.