This page consolidates the public surface of Dirac: artefacts to declare, exported Java modules, supported MicroProfile Metrics 5.1.1 annotations, and the mp.metrics.* keys recognised by the implementation.

Maven artefacts

groupId artifactId Role

io.vidocq.dirac

dirac-mp-metrics-api

Local repackage of microprofile-metrics-api:5.1.1 with an explicit module-info.class. Lifts the jlink blocker (M9).

io.vidocq.dirac

dirac-api

Re-exposition of the MP Metrics spec and stable Dirac SPI (DiracException, HistogramSnapshot, TimerSnapshot), plus the io.vidocq.dirac.spi.gen descriptors (MetricsCompanion) implemented by generated companions.

io.vidocq.dirac

dirac-processor

APT annotation processor (CG-05): generates $$DiracMetrics companion sources at compile time (names, units, tags, scopes resolved statically; gauges as direct functional accessors). Build-time only — never a runtime dependency.

io.vidocq.dirac

dirac-core

Pure-Java implementations: CounterImpl, GaugeImpl, HistogramImpl, TimerImpl, MetricRegistryImpl, BaseMetricsRegistrar, OpenMetricsFormatter, JsonMetricsFormatter. No CDI dependency.

io.vidocq.dirac

dirac-cdi-vauban

CDI interceptors (CountedInterceptor, TimedInterceptor), BCE DiracExtension, producer MetricRegistryProducerBean.

io.vidocq.dirac

dirac-rest

JAX-RS resource MetricsResource (plus the ContentNegotiationFilter @PreMatching filter) exposing GET /metrics. Optional — activated only if Cassini is on the classpath.

io.vidocq.dirac

dirac-bench

JMH benchmarks vs Micrometer / SmallRye Metrics. Not for production.

io.vidocq.dirac

dirac-examples

Standalone and vidocq-mps-integrated examples. Not for production.

io.vidocq.dirac

dirac-tck

Official MP Metrics 5.1.1 TCK runner — in-reactor, gated behind the tck Maven profile (a plain mvn install never builds it). Do not declare as an application dependency.

All artefacts share the version 0.3.0.

Java modules

Module Contents

microprofile.metrics.api

MP Metrics 5.1.1 repackage with an explicit module-info.class. Exports org.eclipse.microprofile.metrics and org.eclipse.microprofile.metrics.annotation.

io.vidocq.dirac.api

Exports io.vidocq.dirac.api (stable public SPI) and io.vidocq.dirac.spi.gen (compile-time MetricsCompanion descriptors implemented by generated $$DiracMetrics companions). requires transitive microprofile.metrics.api.

io.vidocq.dirac.processor

APT processor module — generates the $$DiracMetrics companion sources. Compile-time only.

io.vidocq.dirac.core

io.vidocq.dirac.internal.* — private implementations, exported only to io.vidocq.dirac.cdi.vauban and io.vidocq.dirac.rest.

io.vidocq.dirac.cdi.vauban

io.vidocq.dirac.cdi.internal.* — interceptors and BCE. provides BuildCompatibleExtension with DiracExtension, provides io.vidocq.vauban.api.VaubanComponentProvider with _VaubanComponents (APT-generated, in-module create/inject), and uses io.vidocq.dirac.spi.gen.MetricsCompanion (companions provided by user modules).

io.vidocq.dirac.rest

io.vidocq.dirac.rest.* — JAX-RS resource. opens to jakarta.cdi and jakarta.ws.rs for runtime introspection.

io.vidocq.dirac.internal.* is never exported to application code: any direct dependency signals a regression.

Supported MicroProfile Metrics annotations

Annotation Effect Status

@Counted

Interceptor increments a Counter (LongAdder) on every invocation. Supports name, absolute, description, unit, tags, scope.

✅

@Timed

Interceptor measures duration via System.nanoTime() and feeds a Timer (internal HistogramImpl). Supports the same attributes as @Counted.

✅

@Gauge

Resolved once by DiracExtension at startup via MethodHandle. Method must return a numeric type (int, long, double, Number).

✅

@RegistryScope

Injection qualifier to pick among the three MetricRegistry (APPLICATION, BASE, VENDOR). Without qualifier → APPLICATION registry.

✅

@Metric

Extra metadata on an injection point (name, description, unit, tags).

✅

@Histogram

Annotation absent from the microprofile-metrics-api:5.1.1 JAR used — histograms are declared programmatically.

⚠️ Not exposed by the API

Configuration keys

Dirac reads its configuration without any MicroProfile Config dependency: DistributionConfig resolves each key from System.getProperty(…​) first, then scans every META-INF/microprofile-config.properties visible on the classpath. Exactly three keys are recognised:

Key Effect

mp.metrics.distribution.percentiles

Global percentile list (0.5,0.95,0.99) or per-metric (name=0.5,0.99). An empty value disables percentiles.

mp.metrics.distribution.histogram.buckets

Fixed buckets for Histogram. Global or per metric.

mp.metrics.distribution.timer.buckets

Fixed buckets for Timer, expressed as ms, s, ns, etc. Global or per metric.

mp.metrics.tags and mp.metrics.appName are not implemented: neither key is read, and no global tag is appended to the exposition. The reserved label names mp_scope and mp_app are rejected by MetricRegistryImpl when supplied as user tags.

The MP Metrics 5.1 spec defines no path option (no equivalent of quarkus.smallrye-metrics.path). The /metrics endpoint is fixed by spec §2.3.

MetricUnits types

org.eclipse.microprofile.metrics.MetricUnits enumerates the canonical units:

  • Durations — NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS

  • Sizes — BITS, KILOBITS, MEGABITS, BYTES, KILOBYTES, MEGABYTES, GIGABYTES

  • Generic — NONE, PERCENT, PER_SECOND

Dirac performs no automatic conversion: the unit is exposed as declared. Prometheus convention: express durations as SECONDS, sizes as BYTES.

GET /metrics endpoint

Route

GET /metrics, GET /metrics/{scope}, GET /metrics/{scope}/{name}

Verbs

GET only

Types

text/plain;version=0.0.4;charset=utf-8 (default, OpenMetrics), application/json (MP Metrics §3.2)

Source

MetricRegistryImpl (all three scopes, injected via @RegistryScope)

Status

200 on success, 404 on unknown scope/metric

Implementation

MetricsResource + ContentNegotiationFilter in dirac-rest

Injectable MetricRegistry

@Inject
MetricRegistry application;                                          // APPLICATION

@Inject @RegistryScope(scope = MetricRegistry.BASE_SCOPE)
MetricRegistry base;

@Inject @RegistryScope(scope = MetricRegistry.VENDOR_SCOPE)
MetricRegistry vendor;

Compatibility

  • Java 25 (LTS), Maven 3.9.16.

  • CDI 4.1 Lite (Vauban) or Lite-compatible — the standard Interceptor and BuildCompatibleExtension suffice.

  • JAX-RS 4.0 (Cassini) — only if dirac-rest is used.

  • No MicroProfile Config integration: the mp.metrics.distribution.* keys are read from system properties or META-INF/microprofile-config.properties directly.

  • No Jakarta EE Full Profile dependency.

Bugs and benchmarks

  • BUG.md — tracked reproducible bugs.

  • BENCH.md — JMH benchmarks (vs Micrometer / SmallRye).

Further reading

  • Concepts — MP Metrics 5.1.1 model.

  • Internals — lock-free registry, BCE, formatters.

  • TCK — status and execution.