The MicroProfile Metrics API allows us to easily generate monitoring data (things like CPU load, disk space usage, number of HTTP requests, etc.). Payara Micro provides a metrics endpoint that can provide this data with no additional effort on our part.
/metrics/base is defined by the MicroProfile standard, meaning that all MicroProfile implementations (such as Payara Micro) must implement it. It provides information about the JVM that is running our instance of Payara Micro, things like the number of Java classes loaded into memory, JVM uptime, JVM memory information, etc.
/metrics/vendor allows us to retrieve vendor-specific metric information.
/metrics/application allows us to retrieve our application-specific metrics, which we can generate via annotations.
/metrics displays all metric information, including the data in /metrics/base, /metrics/vendor, and metrics/application.
Data generated by the MicroProfile Metrics API is meant to be read by monitoring tools that can automatically alert us if an application is using too much CPU, memory, disk space, or any other number of warnings. By default, the output of the MicroProfile Config endpoints is in Prometheus format.
Prometheus is a very popular open source monitoring tool. Since Prometheus is so popular, the format it uses to read metrics data has been adopted by several other monitoring tools. By generating data in Prometheus format, MicroProfile Config is automatically compatible with several monitoring tools. If we wish to receive metric data in JSON format instead, all we need to do is set the Accept HTTP header in our request to application/json.
Base Metrics
We can access base metrics by sending a GET request to the /metrics/base endpoint of our Payara Micro instance.
Vendor Metrics
Payara Server allows us to expose JMX beans as custom vendor metrics; at the time of writing, this functionality is not available in Payara Micro.
Application Metrics
MicroProfile metrics provides a number of annotations we can use to annotate our methods, which can provide application metrics with very little effort on our part.
absolute: A boolean value indicating if the name of the metric should be absolute or if it should be appended to the fully qualified name of the class.
description: A description for our metric.
displayName: A human-readable display for the metric.
name: The name of the metric, if not specified, defaults to the method name we are annotating.
tags: Used to differentiate metrics with the same name.
unit: The unit of measurement for the metric.
@Counted
@Gauge
The unit attribute of @Gauge is required; we can assign any arbitrary string value to it; for instance, if we were returning the number of employees in an organization, the unit could be "employees"; if we were returning the number of widgets produced in a factory, the unit could be "widgets"; and so on and so forth.
@ConcurrentGauge
In our example, we are simply sleeping for ten seconds; this allows us to make a few calls to the endpoint and call the metrics endpoint so that we can get relevant example data.
@ConcurrentGauge returns not only the concurrent number of invocations to the method but also the minimum and maximum number of concurrent invocations to the method in the previous minute.
@Metered
@Timed
@SimplyTimed
Programmatic Application Metrics
Most MicroProfile metrics annotations have an equivalent implementation we can use programmatically. For example, the Counter interface is the equivalent of the @Counted annotation. Implementing metrics programmatically allows us to exert more control over the value of our annotations; with Counter, for example, we can increase or even decrease the counter based on our business requirements, as opposed to the @Counted annotation, which only increases the counter when the annotated method is invoked, and there is no way to decrease the counter via the annotation.
In the preceding example, we inject an implementation of the Counter interface via the CDI @Inject annotation and the MicroProfile @Metric annotation. @Metric identifies the counter instance as a metric and lets the MicroProfile Metrics API know it needs to use it to generate application-specific metrics.
Once we have injected a Counter implementation, we can increase or decrease the counter as our business requirements dictate. In our example, the counter is keeping track of the number of employees in a List; it increases every time an employee is hired and decreases every time an employee is fired.
Programmatic Metrics
Metric Interface | Annotation |
---|---|
Counter | @Counted |
ConcurrentGauge | @ConcurrentGauge |
SimpleTimer | @SimpleTimer |
Timer | @Timer |
In this example, we inject an instance of SimpleTimer via the @Inject and @Metric annotations as usual, when we wrap the call to add an employee to the list in a lambda expression and pass the resulting Runnable implementation to the time() method in our SimpleTimer.
Configuring MicroProfile Metrics in Payara Micro
We can configure metrics in Payara Micro via the set-metrics-configuration asadmin command via a command file passed as a post boot command file or similar.
Disabling Metrics
Securing Metrics
By default, the /metrics endpoint is unsecured, meaning any random unauthenticated user can access it.
The value of the --roles argument is a comma-separated list of roles allowed to access the generated metrics.
Customizing the Metrics Endpoint
The value of the --endpoint argument is the context root of our custom metrics endpoint.
Static Metrics
Summary
In this chapter, we covered Payara Micro support for the MicroProfile Metrics API. We generate metrics to be consumed by monitoring tools. We covered how to use annotations provided by MicroProfile metrics to generate metrics with almost no effort on our part; we also saw how we can generate metrics programmatically for cases when we need more control on how to generate those metrics.