Skip to content

Commit

Permalink
Metrics 4.0 implementation (helidon-io#3847)
Browse files Browse the repository at this point in the history
  • Loading branch information
tjquinno authored Feb 1, 2022
1 parent cff467e commit 303112e
Show file tree
Hide file tree
Showing 73 changed files with 3,921 additions and 1,441 deletions.
80 changes: 47 additions & 33 deletions docs/mp/guides/05_metrics.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,24 @@ include::{metrics-common}[tag=build-and-run-intro]
.Text response:
----
# TYPE base_REST_request_total counter
# HELP base_REST_request_total The number of invocations and total response time of RESTful resource methods since the start of the server.
# HELP base_REST_request_total The number of invocations and total response time of this RESTful resource method since the start of the server. The metric will not record the elapsed time nor count of a REST request if it resulted in an unmapped exception. Also tracks the highest recorded time duration within the previous completed full minute and lowest recorded time duration within the previous completed full minute.
base_REST_request_total{class="io.helidon.examples.quickstart.mp.GreetResource",method="getDefaultMessage"} 0
# TYPE base_REST_request_elapsedTime_seconds gauge
base_REST_request_elapsedTime_seconds{class="io.helidon.examples.quickstart.mp.GreetResource",method="getDefaultMessage"} 0.0
# TYPE base_REST_request_maxTimeDuration_seconds gauge
base_REST_request_maxTimeDuration_seconds{class="io.helidon.examples.quickstart.mp.GreetResource",method="getDefaultMessage"} NaN
# TYPE base_REST_request_minTimeDuration_seconds gauge
base_REST_request_minTimeDuration_seconds{class="io.helidon.examples.quickstart.mp.GreetResource",method="getDefaultMessage"} NaN
base_REST_request_total{class="io.helidon.examples.quickstart.mp.GreetResource",method="getMessage_java.lang.String"} 0
base_REST_request_elapsedTime_seconds{class="io.helidon.examples.quickstart.mp.GreetResource",method="getMessage_java.lang.String"} 0.0
base_REST_request_total{class="io.helidon.examples.quickstart.mp.GreetResource",method="updateGreeting_jakarta.json.JsonObject"} 0
base_REST_request_elapsedTime_seconds{class="io.helidon.examples.quickstart.mp.GreetResource",method="updateGreeting_jakarta.json.JsonObject"} 0.0
base_REST_request_maxTimeDuration_seconds{class="io.helidon.examples.quickstart.mp.GreetResource",method="getMessage_java.lang.String"} NaN
base_REST_request_minTimeDuration_seconds{class="io.helidon.examples.quickstart.mp.GreetResource",method="getMessage_java.lang.String"} NaN
...
# TYPE base_REST_request_unmappedException_total counter
# HELP base_REST_request_unmappedException_total The total number of unmapped exceptions that occur from this RESTful resouce method since the start of the server.
base_REST_request_unmappedException_total{class="io.helidon.examples.quickstart.mp.GreetResource",method="getDefaultMessage"} 0
base_REST_request_unmappedException_total{class="io.helidon.examples.quickstart.mp.GreetResource",method="getMessage_java.lang.String"} 0
...
include::{metrics-common}[tag=metrics-prometheus-output]
----
Expand All @@ -58,12 +68,15 @@ include::{metrics-common}[tag=curl-metrics-json]
"base": {
"REST.request":
{
"count;class=io.helidon.examples.quickstart.mp.GreetResource;method=getDefaultMessage":0,
"elapsedTime;class=io.helidon.examples.quickstart.mp.GreetResource;method=getDefaultMessage":0.0,
"count;class=io.helidon.examples.quickstart.mp.GreetResource;method=getMessage_java.lang.String":0,
"elapsedTime;class=io.helidon.examples.quickstart.mp.GreetResource;method=getMessage_java.lang.String":0.0,
"count;class=io.helidon.examples.quickstart.mp.GreetResource;method=updateGreeting_jakarta.json.JsonObject":0,
"elapsedTime;class=io.helidon.examples.quickstart.mp.GreetResource;method=updateGreeting_jakarta.json.JsonObject":0.0
"count;class=io.helidon.examples.quickstart.mp.GreetResource;method=getDefaultMessage": 0,
"elapsedTime;class=io.helidon.examples.quickstart.mp.GreetResource;method=getDefaultMessage": 0,
"maxTimeDuration;class=io.helidon.examples.quickstart.mp.GreetResource;method=getDefaultMessage": null,
"minTimeDuration;class=io.helidon.examples.quickstart.mp.GreetResource;method=getDefaultMessage": null,
"count;class=io.helidon.examples.quickstart.mp.GreetResource;method=getMessage_java.lang.String": 0,
"elapsedTime;class=io.helidon.examples.quickstart.mp.GreetResource;method=getMessage_java.lang.String": 0,
"maxTimeDuration;class=io.helidon.examples.quickstart.mp.GreetResource;method=getMessage_java.lang.String": null,
"minTimeDuration;class=io.helidon.examples.quickstart.mp.GreetResource;method=getMessage_java.lang.String": null,
...
},
include::{metrics-common}[tag=base-metrics-json-output]
},
Expand Down Expand Up @@ -229,7 +242,7 @@ public class GreetingCards {
@Counted(name = "cardCount", absolute = true) //<1>
@Metered(name = "cardMeter", absolute = true, unit = MetricUnits.MILLISECONDS) //<2>
@Timed(name = "cardTimer", absolute = true, unit = MetricUnits.MILLISECONDS) //<3>
public JsonObject anyCard() throws InterruptedException {
public JsonObject anyCard() {
return createResponse("Here are some random cards ...");
}
Expand Down Expand Up @@ -257,29 +270,30 @@ curl -H "Accept: application/json" http://localhost:8080/metrics/application
----
{
"cardCount": 2,
"cardMeter": { // <1>
"cardMeter": { // <1>
"count": 2,
"meanRate": 0.3664337145491488,
"oneMinRate": 0.4,
"fiveMinRate": 0.4,
"fifteenMinRate": 0.4
"meanRate": 0.15653506570241812,
"oneMinRate": 0,
"fiveMinRate": 0,
"fifteenMinRate": 0
},
"cardTimer": { // <2>
"count": 2,
"meanRate": 0.36649792432150535,
"oneMinRate": 0.4,
"fiveMinRate": 0.4,
"fifteenMinRate": 0.4,
"min": 12944,
"max": 2078856,
"mean": 1045900.0,
"stddev": 1032956.0,
"p50": 2078856.0,
"p75": 2078856.0,
"p95": 2078856.0,
"p98": 2078856.0,
"p99": 2078856.0,
"p999": 2078856.0
"elapsedTime": 2,
"meanRate": 0.15651866263362785,
"oneMinRate": 0,
"fiveMinRate": 0,
"fifteenMinRate": 0,
"min": 0,
"max": 2,
"mean": 1.0506565,
"stddev": 1.0405735,
"p50": 2.09123,
"p75": 2.09123,
"p95": 2.09123,
"p98": 2.09123,
"p99": 2.09123,
"p999": 2.09123
}
}
----
Expand All @@ -289,7 +303,7 @@ curl -H "Accept: application/json" http://localhost:8080/metrics/application
==== Reusing Metrics
You can share a metric across multiple endpoints by specifying the reusable field in the metric annotation as
You can share a metric across multiple endpoints simply by specifying the same metric annotation as
demonstrated below.
[source,java]
Expand All @@ -316,23 +330,23 @@ public class GreetingCards {
@GET
@Produces(MediaType.APPLICATION_JSON)
@Counted(name = "anyCard",absolute = true)
@Counted(name = "anyCard", absolute = true)
public JsonObject anyCard() throws InterruptedException {
return createResponse("Here are some cards ...");
}
@GET
@Path("/birthday")
@Produces(MediaType.APPLICATION_JSON)
@Counted(name = "specialEventCard", absolute = true, reusable = true) // <1>
@Counted(name = "specialEventCard", absolute = true) // <1>
public JsonObject birthdayCard() throws InterruptedException {
return createResponse("Here are some birthday cards ...");
}
@GET
@Path("/wedding")
@Produces(MediaType.APPLICATION_JSON)
@Counted(name = "specialEventCard", absolute = true, reusable = true) // <2>
@Counted(name = "specialEventCard", absolute = true) // <2>
public JsonObject weddingCard() throws InterruptedException {
return createResponse("Here are some wedding cards ...");
}
Expand Down
84 changes: 54 additions & 30 deletions docs/se/guides/05_metrics.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ import jakarta.json.Json;
import jakarta.json.JsonBuilderFactory;
import jakarta.json.JsonObject;
import org.eclipse.microprofile.metrics.Counter; // <1>
import org.eclipse.microprofile.metrics.MetricRegistry;
import org.eclipse.microprofile.metrics.MetricRegistry; // <1>
public class GreetingCards implements Service {
Expand Down Expand Up @@ -287,13 +287,16 @@ the application.
MetricsSupport metrics = MetricsSupport.create();
GreetService greetService = new GreetService(config);
HealthSupport health = HealthSupport.builder()
.addLiveness(HealthChecks.healthChecks()) // Adds a convenient set of checks
.build();
return Routing.builder()
.register(JsonSupport.create())
.register(metrics)
.register(health) // Health at "/health"
.register(metrics) // Metrics at "/metrics"
.register("/greet", greetService)
.register("/cards", new GreetingCards()) //<1>
.build();
.register("/cards", new GreetingCards()) // <1>
.build();
}
----
<1> Add the `GreetingCards` service to the `Routing.builder`. Helidon will route any REST requests with
Expand Down Expand Up @@ -426,7 +429,7 @@ import jakarta.json.Json;
import jakarta.json.JsonBuilderFactory;
import jakarta.json.JsonObject;
import org.eclipse.microprofile.metrics.MetricRegistry; // <1>
import org.eclipse.microprofile.metrics.Timer;
import org.eclipse.microprofile.metrics.Timer; // <1>
public class GreetingCards implements Service {
Expand Down Expand Up @@ -476,26 +479,28 @@ curl -H "Accept: application/json" http://localhost:8080/metrics/application
----
{
"cardTimer": {
"count": 1,
"meanRate": 0.03843465264149663, // <1>
"oneMinRate": 0.014712537947741825,
"fiveMinRate": 0.0032510706679223173,
"fifteenMinRate": 0.0011018917421948848,
"min": 40876527, // <2>
"max": 40876527,
"mean": 40876527,
"stddev": 0.0,
"p50": 40876527,
"p75": 40876527,
"p95": 40876527,
"p98": 40876527,
"p99": 40876527,
"p999": 40876527
"count": 1, // <1>
"elapsedTime": 26683406, // <2>
"meanRate": 0.05669258258076838,
"oneMinRate": 0,
"fiveMinRate": 0,
"fifteenMinRate": 0,
"min": 26683406, // <2>
"max": 26683406,
"mean": 26683406,
"stddev": 0,
"p50": 26683406,
"p75": 26683406,
"p95": 26683406,
"p98": 26683406,
"p99": 26683406,
"p999": 26683406
}
}
----
<1> These are the same fields used by `Meter`.
<2> These are the `Timer` fields that measure the duration of the `getDefaultMessageHandler` method. Some of these values
<1> The first several fields (except for `elapsedTime`) are the same ones used by `Meter`.
<2> The `elapsedTime` field and the rest starting with `min` are the `Timer` fields that measure the duration of the `getDefaultMessageHandler` method. Some of these values
will change each time you invoke the `/cards` endpoint.
Expand Down Expand Up @@ -694,7 +699,9 @@ curl -H "Accept: application/json" http://localhost:8080/metrics/application
[[simple_timer_metric]]
==== Simple Timer Metric
The `SimpleTimer` metric counts invocations and accumulates duration (in seconds). In the following example,
The `SimpleTimer` metric counts invocations and accumulates duration (in seconds).
It also records the minimum and maximum values sampled during the previous complete minute.
In the following example,
a `SimpleTimer` metric is used to count and measure the duration of a method's execution. Whenever the REST `/cards`
endpoint is called, the `SimpleTimer` updates its count and total elapsed time.
Expand All @@ -713,7 +720,7 @@ import jakarta.json.Json;
import jakarta.json.JsonBuilderFactory;
import jakarta.json.JsonObject;
import org.eclipse.microprofile.metrics.MetricRegistry; // <1>
import org.eclipse.microprofile.metrics.SimpleTimer;
import org.eclipse.microprofile.metrics.SimpleTimer; // <!>
public class GreetingCards implements Service {
Expand Down Expand Up @@ -759,15 +766,32 @@ curl -H "Accept: application/json" http://localhost:8080/metrics/application
.JSON response:
----
{
"cardSimpleTimer":
{
"count":1, <1>
"elapsedTime":0.034274025 <2>
}
"cardSimpleTimer": {
"count": 1, // <1>
"elapsedTime": 13455720, // <2>
"maxTimeDuration": null, // <3>
"minTimeDuration": null
}
}
----
<1> How many times the `getDefaultMessageHandler` method ran.
<2> Cumulative time spent in the `getDefaultMessageHandler` method during its executions.
<3> Simple timers report the minimum and maximum durations recorded over the preceding complete minute. The JSON output contains `null` for these values if the simple timer recorded no observations during the preceding complete minute.
If you retrieve the metrics again shortly after the current minute has completed, the simple timer reports useful values.
[source,json]
.JSON response after the current minute completes:
----
{
"cardSimpleTimer": {
"count": 1,
"elapsedTime": 13455720,
"maxTimeDuration": 13455720,
"minTimeDuration": 13455720
}
}
----
If you again wait until the _next_ complete minute without accessing the greeting card endpoint again and rerun the metrics query, the simple timer reports null values again because there was no activity in the preceding complete minute.
include::{metrics-common}[tag=k8s-and-prometheus-integration]
Expand Down
10 changes: 8 additions & 2 deletions examples/metrics/exemplar/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2021 Oracle and/or its affiliates.
Copyright (c) 2021, 2022 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -15,7 +15,8 @@
See the License for the specific language governing permissions and
limitations under the License.
--><project xmlns="http://maven.apache.org/POM/4.0.0"
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
Expand Down Expand Up @@ -62,6 +63,11 @@
<artifactId>helidon-tracing-zipkin</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
Expand Down
7 changes: 6 additions & 1 deletion examples/metrics/filtering/se/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2021 Oracle and/or its affiliates.
Copyright (c) 2021, 2022 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -46,6 +46,11 @@
<groupId>io.helidon.metrics</groupId>
<artifactId>helidon-metrics</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
Expand Down
7 changes: 6 additions & 1 deletion examples/metrics/kpi/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2021 Oracle and/or its affiliates.
Copyright (c) 2021, 2022 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -46,6 +46,11 @@
<groupId>io.helidon.metrics</groupId>
<artifactId>helidon-metrics</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Oracle and/or its affiliates.
* Copyright (c) 2021, 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -29,6 +29,12 @@ public abstract class AbstractMetric implements HelidonMetric {
private final Metadata metadata;
private volatile boolean isDeleted;

/**
* Common initialization logic in creating a new metric.
*
* @param registryType type of metric registry the metric is registered in
* @param metadata metric metadata describing the metric
*/
protected AbstractMetric(String registryType, Metadata metadata) {
this.registryType = registryType;
this.metadata = metadata;
Expand Down
Loading

0 comments on commit 303112e

Please sign in to comment.