Skip to content

Latest commit

 

History

History
182 lines (127 loc) · 7.91 KB

appendix.adoc

File metadata and controls

182 lines (127 loc) · 7.91 KB

Appendix

Alternatives considered

We addressed some significant questions while creating MicroProfile Metrics v5.0.

API or no API

In light of the increasing prevalence of developer use of APIs from Micrometer and OpenTelemetry, we considered whether we should continue to have a distinct API for MicroProfile Metrics. We decided to continue our path of providing an API for the following reasons:

  1. provides an easy-to-use metrics API for application developers

  2. provides continuity for the existing MicroProfile Metrics user community

  3. provides a MicroProfile-style API (for example, CDI-based annotations), and configurability (MicroProfile Config), for ease of adoption by MicroProfile users

  4. ensures compatibility across APIs within the same MicroProfile release

We also considered feedback from an informal poll in which a majority of respondents said they would use a MicroProfile Metrics API, given the other options.

Fixed implementation or vendor-chosen implementation

We considered whether MicroProfile Metrics should require vendors to use a particular metrics library in their implementations. The benefit of requiring a particular metrics library would be the potential for improved consistency across vendors. The benefits of not requiring a particular metrics library would be avoiding MicroProfile potentially overreaching by telling vendors which libraries to use, and leaving flexibility for vendors to change their implementation in the future if needed. Ultimately, we decided to not require a specific metrics library to be used in the implementation. Vendors may choose to implement using Micrometer libraries, OpenTelemetry libraries, Dropwizard libraries, custom code, or anything else they choose.

Example configuration format for base and vendor-specific data

The following is an example configuration in YAML format.

base:
  - name: "thread-count"
    mbean: "java.lang:type=Threading/ThreadCount"
    description: "Number of currently deployed threads"
    unit: "none"
    type: "gauge"
  - name: "peak-thread-count"
    mbean: "java.lang:type=Threading/PeakThreadCount"
    description: "Max number of threads"
    unit: "none"
    type: "gauge"
  - name: "total-started-thread-count"
    mbean: "java.lang:type=Threading/TotalStartedThreadCount"
    description: "Number of threads started for this server"
    unit: "none"
    type: "counter"
  - name: "max-heap"
    mbean: "java.lang:type=Memory/HeapMemoryUsage#max"
    description: "Number of threads started for this server"
    unit: "bytes"
    type: "counter"
    tags: "kind=memory"

vendor:
  - name: "msc-loaded-modules"
    mbean: "jboss.modules:type=ModuleLoader,name=BootModuleLoader-2/LoadedModuleCount"
    description: "Number of loaded modules"
    unit: "none"
    type: "gauge"

This configuration can be backed into the runtime or be provided via an external configuration file.

Example Metric Registry Factory

Sample skeleton factory class to produce MetricRegistry via CDI
@ApplicationScoped
public class MetricRegistryFactory {

    @Produces
    @Default
    public MetricRegistry getMetricRegistry(InjectionPoint ip) {

        RegistryScope registryTypeAnnotation = ip.getAnnotated().getAnnotation(RegistryScope.class);

        if (registryTypeAnnotation == null) {
            return getOrCreate(MetricRegistry.APPLICATION_SCOPE);
        } else {
            String annoScope = registryTypeAnnotation.scope();
            return getOrCreate(annoScope);
        }
    }

    @Produces
    @RegistryType(type = MetricRegistry.Type.APPLICATION)
    public MetricRegistry getApplicationRegistry() {
        return getOrCreate(MetricRegistry.Type.APPLICATION);
    }

    @Produces
    @RegistryType(type = MetricRegistry.Type.BASE)
    public MetricRegistry getBaseRegistry() {
        return getOrCreate(MetricRegistry.Type.BASE);
    }

    @Produces
    @RegistryType(type = MetricRegistry.Type.VENDOR)
    public MetricRegistry getVendorRegistry() {
        return getOrCreate(MetricRegistry.Type.VENDOR);
    }

}

Migration hints

To version 5.0

SimpleTimer / @SimplyTimed

The SimpleTimer class and @SimplyTimed annotation have been removed. This change was made to make it possible to implement the spec using commonly used metrics libraries that lack a similar metric type.

Use Timer class or @Timed annotation instead. Alternatively, you can create your own Gauge to track the total time and your own Counter to track the total number of hits of something you want to time.

ConcurrentGauge / @ConcurrentGauge

The ConcurrentGauge class and @ConcurrentGauge annotation have been removed. This change was made to make it possible to implement the spec using commonly used metrics libraries that lack a similar metric type.

Use Gauge class or @Gauge annotation instead. A Gauge allows you to track a value that may go up or down over time. If you need to track the recent maximum or minimum with precision (as was handled by a ConcurrentGauge), create a separate Gauge for each of those statistics, in addition to the Gauge to track the current value of what you are observing.

Meter / @Metered

The Meter class and @Metered annotation have been removed. This change was made to make it possible to implement the spec using commonly used metrics libraries that lack a similar metric type.

Use Counter class or @Counted annotation instead. Tools, such as Prometheus, are able to compute the rate of increase of an observed metric over a specified period of time.

Snapshot

The Snapshot class has been modified to avoid restricting the list of percentiles to a fixed set of percentile values. This change was made in anticipation of making the list of percentiles be configurable in the future. As in prior releases, the Timer and Histogram classes still track the 50th, 75th, 95th, 98th, 99th, and 99.9th percentiles in the corresponding Snapshot.

Use snapshot.percentileValues() method, then iterate over the returned array of PercentileValue objects to find the value at the specific percentile you’re interested in.

Metric names

The base_, vendor_ and application_ prefixes for metric names that were used in prior releases have been replaced by a tag named mp_scope with value base, vendor, or application (you can also register metrics with custom scopes).

When using the Prometheus format output from the /metrics endpoint, use metric_name{mp_scope="scopeValue",…​} instead of scopeValue_metric_name{…​} where metric_name is the Prometheus-formatted name of your metric and scopeValue is one of base, vendor, application or a custom value.