11 April 2018

These are my personal notes on getting familiar with MicroProfile 1.3. In specific Metrics 1.1. As a basis, I have been using the tutorial on OpenLiberty.io. Not suprising, I am using OpenLiberty (version 18.0.0.1). The server.xml which serves as the starting-point is described here. I am just listing the used features here:

server.xml
<featureManager>
    <feature>javaee-7.0</feature>
    <feature>localConnector-1.0</feature>
    <feature>microProfile-1.3</feature>
</featureManager>

Some differences:

  • javaee-7.0 is used, as Java EE 8 seems not to be supported yet by the release builds.

  • microProfile-1.3 to enable all features as part of MicroProfile 1.3

As a starting-point for the actual project I am using my Java EE WAR template.

To get all MicroProfile 1.3 dependencies available in your gradle-build, you can add the following provided-dependency:

providedCompile 'org.eclipse.microprofile:microprofile:1.3'

Now lets write a simple Rest-service to produce some metrics.

@Stateless
@Path("magic")
public class MagicNumbersResource {

	static int magicNumber = 0;

	@POST
	@Consumes("text/plain")
	@Counted(name = "helloCount", absolute = true, monotonic = true, description = "Number of times the hello() method is requested")
	@Timed(name = "helloRequestTime", absolute = true, description = "Time needed to get the hello-message")
	public void setMagicNumber(Integer num) throws InterruptedException {
		TimeUnit.SECONDS.sleep(2);
		magicNumber = num;
	}

	@Gauge(unit = MetricUnits.NONE, name = "magicNumberGuage", absolute = true, description = "Magic number")
	public int getMagicNumber() {
		return magicNumber;
	}
}

I am using:

  • A @Timed metric that records the percentiles and averages for the duration of the method-invocation

  • A @Counted metric that counts the number of invocations

  • A @Gauge metric that just takes the return-value of the annotated method as the metric-value.

Now deploy and invoke curl -X POST -H "Content-Type: text/plain" -d "42" http://localhost:9080/mptest/resources/magic. (This assumes the application/WAR is named mptest).

Now open http://localhost:9080/metrics in the browser. You should see the following prometheus-formatted metrics:

# TYPE application:hello_request_time_rate_per_second gauge
application:hello_request_time_rate_per_second 0.1672874737158507
# TYPE application:hello_request_time_one_min_rate_per_second gauge
application:hello_request_time_one_min_rate_per_second 0.2
# TYPE application:hello_request_time_five_min_rate_per_second gauge
application:hello_request_time_five_min_rate_per_second 0.2
# TYPE application:hello_request_time_fifteen_min_rate_per_second gauge
application:hello_request_time_fifteen_min_rate_per_second 0.2
# TYPE application:hello_request_time_mean_seconds gauge
application:hello_request_time_mean_seconds 2.005084111
# TYPE application:hello_request_time_max_seconds gauge
application:hello_request_time_max_seconds 2.005084111
# TYPE application:hello_request_time_min_seconds gauge
application:hello_request_time_min_seconds 2.005084111
# TYPE application:hello_request_time_stddev_seconds gauge
application:hello_request_time_stddev_seconds 0.0
# TYPE application:hello_request_time_seconds summary
# HELP application:hello_request_time_seconds Time needed to get the hello-message
application:hello_request_time_seconds_count 1
application:hello_request_time_seconds{quantile="0.5"} 2.005084111
application:hello_request_time_seconds{quantile="0.75"} 2.005084111
application:hello_request_time_seconds{quantile="0.95"} 2.005084111
application:hello_request_time_seconds{quantile="0.98"} 2.005084111
application:hello_request_time_seconds{quantile="0.99"} 2.005084111
application:hello_request_time_seconds{quantile="0.999"} 2.005084111 (1)
# TYPE application:magic_number_guage gauge
# HELP application:magic_number_guage Magic number
application:magic_number_guage 42 (3)
# TYPE application:hello_count counter
# HELP application:hello_count Number of times the hello() method is requested
application:hello_count 1 (2)
  1. This is one of the percentiles from @Timed. Due to the sleep, it is close to two seconds.

  2. This metrics is based on @Counted. We invoked the method once via curl.

  3. This metric is based on the @Gauge. We did a post with curl to set the magicNumber to 42. So, this is what the gauge will get from getMagicNumber().

As a final note: I like the Java EE-approach of having a single dependency to develop against (javax:javaee-api:7.0). I have used the same approach here for the Microprofile. If you instead only want to enable the metrics-feature in Liberty and only want to program against the related API, you can instead have used the following feature in the server.xml:

<feature>mpMetrics-1.1</feature>

And the following dependency in your build.gradle:

providedCompile 'org.eclipse.microprofile.metrics:microprofile-metrics-api:1.1'

I find this approach more cumbersome if multiple MicroProfile APIs are used; and the neglectable difference in startup-time of Liberty confirms that there is no disadvantage.

In a later post we will look at what can be done with the metrics.