Skip to content

Repository files navigation

jruntime-inspector

CI License Java Maven Central

A lightweight, framework-agnostic runtime profiling library for JVM applications.

Instrument your code with Metrics.start() / Metrics.end(), Metrics.track(), or Metrics.measure() and get a hierarchical Markdown report that pinpoints exactly where your execution time goes — database, parser, mapper, or anything else.

Features

  • Zero external dependencies — JDK only, no Spring, Micronaut, or Quarkus required
  • Framework-agnostic — works with any JVM backend
  • Three instrumentation styles — manual start/end, try-with-resources track(), and functional measure()
  • Hierarchical execution tree — nested calls produce an indented breakdown with percentages
  • Hotspot detection — flags nodes above a configurable threshold automatically
  • Threshold filtering — ignore fast nodes below a configurable duration floor
  • Tag support — attach key-value metadata to any node (table=users, operation=SELECT)
  • Thread-safe — each thread has its own independent context via ThreadLocal
  • Extensible — implement MetricsReporter to add JSON, HTML, or any custom format

Requirements

  • Java 21+
  • Maven 3.8+ (included via Maven Wrapper — no installation needed)

Installation

Add metrics-core to your pom.xml:

<dependency>
    <groupId>org.aocdev</groupId>
    <artifactId>metrics-core</artifactId>
    <version>1.0.0</version>
</dependency>

Quick Start

1. Configure (optional)

Metrics.init(MetricsConfig.builder()
        .hotspotThresholdPercent(40.0)
        .includeThreadName(true)
        .build());

2. Instrument your code

Metrics.startRun("import-job");

try (MetricScope ignored = Metrics.track("processUsers")) {
    Metrics.measure("dbQuery", Map.of("table", "users"), () -> fetchFromDatabase());
    Metrics.measure("parse",   () -> parseResponse());
    Metrics.measure("mapper",  () -> mapToDomain());
}

Metrics.endRun();

3. Get the report

Metrics.report().writeToFile("report.md");

4. Result

# Execution Report — import-job

## Summary
- **Total time:** 218 ms

## Breakdown
- **processUsers** (193 ms) → 88.4%
  - **dbQuery** (120 ms) → 55.0% `table=users`
  - **parse** (40 ms) → 18.4%
  - **mapper** (31 ms) → 14.3%

## Hotspots
- **processUsers** — 193 ms (88.4% of total) ⚠️
- **dbQuery** — 120 ms (55.0% of total) ⚠️

Instrumentation API

Lifecycle

Method Description
Metrics.init(MetricsConfig) Replace the global config. Call once at startup.
Metrics.startRun(String name) Begin a named measurement run on the current thread.
Metrics.endRun() End the current run and finalise the root node.
Metrics.report() Return a MetricReport for the current thread. Call after endRun().

Measurement

Method Style Description
Metrics.start(String name) Manual Begin a block. Pair with end().
Metrics.start(String name, Map<String,String> tags) Manual Same, with metadata tags.
Metrics.end() Manual End the most recently started block.
Metrics.track(String name) try-with-resources Returns MetricScope (AutoCloseable). Calls end() on close.
Metrics.track(String name, Map<String,String> tags) try-with-resources Same, with tags.
Metrics.measure(String name, Runnable) Functional Wraps a Runnable.
Metrics.measure(String name, Map<String,String> tags, Runnable) Functional Same, with tags.
Metrics.measure(String name, Supplier<T>) Functional Wraps a Supplier<T>, returns the value.
Metrics.measure(String name, Map<String,String> tags, Supplier<T>) Functional Same, with tags.

MetricReport

Method Description
report.toMarkdown() Renders the report as a Markdown string.
report.writeToFile(String path) Writes the report to a file (UTF-8). Parent directories are created automatically.

Configuration

MetricsConfig config = MetricsConfig.builder()
        .enabled(true)                   // false = all methods become no-ops
        .thresholdMs(10)                 // skip nodes faster than 10 ms
        .includeThreadName(true)         // include thread name in Summary
        .hotspotThresholdPercent(50.0)   // flag nodes that exceed 50% of total time
        .build();
Option Type Default Description
enabled boolean true Master switch. false makes all calls no-ops with zero overhead.
thresholdMs long 0 Minimum duration (ms) to include a node in the report. 0 = show everything.
includeThreadName boolean false Prints the thread name in the Summary section.
hotspotThresholdPercent double 50.0 Percentage of total run time above which a node is flagged as a hotspot.

Extending the Reporter

Implement MetricsReporter to produce any output format:

public class JsonReporter implements MetricsReporter {

    @Override
    public String generate(MetricNode root, MetricsConfig config) {
        // traverse root.getChildren() recursively and build JSON
    }
}

Pass it to MetricReport directly or contribute it back via a pull request.

Project Structure

jruntime-inspector/
  pom.xml                             # Parent POM (multi-module)
  metrics-core/                       # Library — published to Maven Central
    src/main/java/org/aocdev/
      Metrics.java                    # Main public API
      MetricNode.java                 # Execution tree node
      MetricContext.java              # Per-thread state (ThreadLocal)
      MetricScope.java                # AutoCloseable handle for try-with-resources
      MetricsConfig.java              # Configuration builder
      MetricReport.java               # toMarkdown() / writeToFile()
      reporter/
        MetricsReporter.java          # Extension interface
        MarkdownReporter.java         # Built-in Markdown implementation
  metrics-example/                    # Demo application (not published)
    src/main/java/org/aocdev/example/
      Main.java                       # Simulated import-job demo

Build

./mvnw verify

The demo generates report.md in the working directory:

./mvnw install && ./mvnw -pl metrics-example exec:java

License

Apache License 2.0

Copyright 2026 aocdev (Albert Ortells)

See NOTICE for attribution details.

Contributing

See CONTRIBUTING.md for guidelines on how to contribute to this project.

About

Lightweight, framework-agnostic runtime profiling library for JVM applications. Instrument your code, detect bottlenecks, and generate human-readable Markdown reports.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages