Class MicrometerMetricsRecorder

java.lang.Object
org.apache.juneau.rest.server.metrics.micrometer.MicrometerMetricsRecorder
All Implemented Interfaces:
MetricsRecorder

public class MicrometerMetricsRecorder extends Object implements MetricsRecorder
MetricsRecorder bridge that records every @RestOp call as a Micrometer Timer sample on the configured MeterRegistry.
Metric shape

Each call records to one Timer named (by default) "http.server.requests" with four tags:

  • method — uppercased HTTP method (e.g. GET, POST).
  • uri — the @RestOp path template (e.g. /users/{id}), not the raw concrete URI. Using the template keeps tag cardinality bounded; raw URIs (/users/123, /users/124, ...) would explode the registry's series count. Empty string when the operation has no path pattern.
  • status — HTTP response status code as a string (e.g. 200, 404, 500).
  • exception — the thrown exception's simple-name (e.g. BadRequest, NullPointerException), or "None" when the call completed normally.

The shape mirrors Spring Boot's WebMvcMetricsFilter convention so existing dashboards / alerts that scrape http.server.requests from Spring Boot services keep working when those services are reimplemented on Juneau.

Wiring

@Configuration public class ObservabilityConfig { @Bean public MeterRegistry meterRegistry() { return new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); } @Bean public MetricsRecorder metricsRecorder(MeterRegistry r) { return new MicrometerMetricsRecorder(r); } }

The MetricsRecorder bean is picked up by juneau-rest-server through the RestContext's bean store and invoked once per @RestOp call.

Customizing the metric name

Pass a non-default name to the two-arg constructor when the default "http.server.requests" doesn't match an existing dashboard / Prometheus rule set:

new MicrometerMetricsRecorder(r, "my.service.http.timer")

Per-operation overrides are available via RestOp.metricName(). When a non-empty metricName is passed to record(...), it takes precedence over the recorder-level timer name. Per-op tags added via RestOp.metricTags() are merged into the standard tag set as additional key=value pairs.

See Also:
Since:
10.0.0
  • Field Details

  • Constructor Details

    • MicrometerMetricsRecorder

      public MicrometerMetricsRecorder(io.micrometer.core.instrument.MeterRegistry registry)
      Constructor using the default timer name "http.server.requests".
      Parameters:
      registry - The Micrometer MeterRegistry to publish timers to. Must not be null.
    • MicrometerMetricsRecorder

      public MicrometerMetricsRecorder(io.micrometer.core.instrument.MeterRegistry registry, String timerName)
      Constructor with a custom timer name.
      Parameters:
      registry - The Micrometer MeterRegistry to publish timers to. Must not be null.
      timerName - The timer name. Must not be null or blank.
  • Method Details

    • getRegistry

      public io.micrometer.core.instrument.MeterRegistry getRegistry()
      Returns the MeterRegistry this recorder publishes to.
      Returns:
      The MeterRegistry.
    • getTimerName

      public String getTimerName()
      Returns the configured timer name.
      Returns:
      The timer name.
    • record

      public void record(String opName, String httpMethod, String uriTemplate, int statusCode, Duration elapsed, Throwable error, String metricName, String metricTags)
      Description copied from interface: MetricsRecorder
      Records one per-request metric event.
      Specified by:
      record in interface MetricsRecorder
      Parameters:
      opName - The fully-qualified @RestOp method name (e.g. "com.example.OrderResource.create(java.lang.String,com.example.Order)"). Never null; never blank.
      httpMethod - The uppercased HTTP method of the request (e.g. "GET", "POST"). Never null; never blank.
      uriTemplate - The @RestOp path template (e.g. "/users/{id}"), not the raw concrete URI. Bridges should use this as the uri tag to keep cardinality bounded. May be empty for resource-level operations that match /*; never null.
      statusCode - The HTTP response status code (e.g. 200, 404, 500). If the handler threw before the status was set, this is the framework's inferred status (typically 500 for an unmapped exception, or the exception's status for a BasicHttpException).
      elapsed - Wall-clock duration of the @RestOp invocation. Never null; never negative.
      error - The exception thrown by the handler, or null if the call completed normally. Bridges typically derive an exception tag from the throwable's simple class name, or "None" when null (mirrors Spring Boot's WebMvcMetricsFilter convention).
      metricName - Per-op metric name override from RestOp.metricName(). Empty string (default) means the implementation should use its own default name derivation. Never null.
      metricTags - Per-op additional metric tags from RestOp.metricTags(). Format: comma-separated key=value pairs (e.g. "team=payments,region=us-east"). Empty string (default) means no additional tags. Never null.
    • record

      public void record(String metricName, String metricTags, Duration elapsed, Throwable error)
      Description copied from interface: MetricsRecorder
      Records one custom (non-request) observation event.

      Unlike MetricsRecorder.record(String, String, String, int, Duration, Throwable, String, String), this entry point is not tied to an HTTP request — it is the substrate for the explicit programmatic observation API (Observations) so application code can time an arbitrary block of work. Bridge implementations record a timer named metricName carrying metricTags (plus an exception tag derived from error).

      The default implementation does nothing — a bridge that does not override it simply does not record custom observations, and the no-backend path stays zero-allocation. The shipped Micrometer bridge overrides it.

      Specified by:
      record in interface MetricsRecorder
      Parameters:
      metricName - The timer name (e.g. "order.load"). Never null; never blank.
      metricTags - Additional tags as comma-separated key=value pairs (e.g. "team=payments,region=us-east"). Empty string means no additional tags. Never null.
      elapsed - Wall-clock duration of the observed block. Never null; never negative.
      error - The exception thrown by the observed block, or null if it completed normally.