diff --git a/examples/mp-metrics-counted/src/main/java/org/superbiz/rest/WeatherService.java b/examples/mp-metrics-counted/src/main/java/org/superbiz/rest/WeatherService.java
index ec856fe80a6..99fb2ca3732 100644
--- a/examples/mp-metrics-counted/src/main/java/org/superbiz/rest/WeatherService.java
+++ b/examples/mp-metrics-counted/src/main/java/org/superbiz/rest/WeatherService.java
@@ -18,7 +18,8 @@ public class WeatherService {
@Path("/day/status")
@Counted(monotonic = true, name = "weather_day_status", absolute = true,
displayName = "Weather Day Status",
- description = "This metric shows the weather status of the day.")
+ description = "This metric shows the weather status of the day.",
+ tags = {"weather=day"})
@GET
@Produces(MediaType.TEXT_PLAIN)
public String dayStatus() {
diff --git a/examples/mp-metrics-gauge/README.adoc b/examples/mp-metrics-gauge/README.adoc
new file mode 100644
index 00000000000..84ec2096667
--- /dev/null
+++ b/examples/mp-metrics-gauge/README.adoc
@@ -0,0 +1,125 @@
+= MicroProfile Metrics Gauge
+
+:index-group: MicroProfile
+:jbake-type: page
+:jbake-status: published
+
+This is an example on how to use MicroProfile metrics in TomEE.
+
+.Run the application:
+ mvn clean install tomee:run
+
+Within the application there is an endpoint that will give you the weather temperature in celsius for the day.
+
+.For the day temperature call:
+ GET http://localhost:8080/mp-metrics-gauge/weather/day/temperature
+
+.Response:
+ 30
+
+[discrete]
+==== Gauge Feature
+
+MicroProfile metrics has a gauge feature. The gauge value and type is equal to the annotated method return value and type.
+
+To use this feature you need to annotate the JAX-RS resource method with @Gauge.
+
+....
+@Path("/weather")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+@ApplicationScoped
+public class WeatherService {
+
+ @Path("/day/temperature")
+ @Gauge(name = "weather_day_temperature", absolute = true, unit = "celsius",
+ displayName = "Weather Day Temperature",
+ description = "This metric shows the day temperature.",
+ tags = {"weather=temperature"})
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public Integer dayTemperature() {
+ return 30;
+ }
+}
+....
+
+There are some configurations, as part of @Gauge, that you need to know:
+
+*String name*
+Optional. Sets the name of the metric. If not explicitly given the name of the annotated object is used.
+
+*boolean absolute*
+If true, uses the given name as the absolute name of the metric. If false, prepends the package name and class name before the given name. Default value is false.
+
+*String displayName*
+Optional. A human-readable display name for metadata.
+
+*String description*
+Optional. A description of the metric.
+
+*String[] tags*
+Optional. Array of Strings in the ++++++=++++++format to supply special tags to a metric.++++++++++++
+
+*String unit*
+Unit of the metric. Check the MetricUnits class for a set of pre-defined units.
+
+[discrete]
+==== Metric data
+
+Check the gauge metric doing a _GET_ request:
+
+.Prometheus format:
+ GET http://localhost:8080/mp-metrics-gauge/metrics/application/weather_day_temperature
+
+.Response:
+ # TYPE application:weather_day_temperature_celsius gauge
+ application:weather_day_temperature_celsius{weather="temperature"} 30.0
+
+[discrete]
+===== JSON Format:
+
+For json format add the header _Accept=application/json_ to the request.
+
+ {
+ "weather_day_temperature": 30
+ }
+
+[discrete]
+==== Metric metadata
+
+A metric will have a metadata so you can know more information about it, like displayName, description, tags e etc.
+
+Check the metric metadata doing a _OPTIONS_ request:
+
+.Request
+ OPTIONS http://localhost:8080/mp-metrics-gauge/metrics/application/weather_day_temperature
+
+.Response:
+ {
+ "weather_day_temperature": {
+ "unit": "celsius",
+ "displayName": "Weather Day Temperature",
+ "name": "weather_day_temperature",
+ "typeRaw": "GAUGE",
+ "description": "This metric shows the day temperature.",
+ "type": "gauge",
+ "value": {
+ "unit": "celsius",
+ "displayName": "Weather Day Temperature",
+ "name": "weather_day_temperature",
+ "tagsAsString": "weather=\"temperature\"",
+ "typeRaw": "GAUGE",
+ "description": "This metric shows the day temperature.",
+ "type": "gauge",
+ "reusable": false,
+ "tags": {
+ "weather": "temperature"
+ }
+ },
+ "reusable": false,
+ "tags": "weather=temperature"
+ }
+ }
+
+You can also try it out using the WeatherServiceTest.java available in the project.
diff --git a/examples/mp-metrics-gauge/pom.xml b/examples/mp-metrics-gauge/pom.xml
new file mode 100644
index 00000000000..064d29caeca
--- /dev/null
+++ b/examples/mp-metrics-gauge/pom.xml
@@ -0,0 +1,69 @@
+
+
+
+ examples
+ org.apache.tomee
+ 8.0.0-SNAPSHOT
+
+ 4.0.0
+
+ mp-metrics-gauge
+ war
+
+
+
+ org.apache.tomee
+ javaee-api
+ ${version.javaee-api}
+ provided
+
+
+ org.eclipse.microprofile.metrics
+ microprofile-metrics-api
+ ${microprofile.metrics.version}
+ provided
+
+
+ org.apache.tomee
+ openejb-cxf-rs
+ ${tomee.version}
+ test
+
+
+ org.jboss.arquillian.junit
+ arquillian-junit-container
+ ${version.arquillian.bom}
+ test
+
+
+ org.apache.tomee
+ arquillian-tomee-remote
+ ${tomee.version}
+ test
+
+
+ org.apache.tomee
+ apache-tomee
+ ${tomee.version}
+ zip
+ microprofile
+ test
+
+
+
+
+
+
+ org.apache.tomee.maven
+ tomee-maven-plugin
+ ${project.version}
+
+ microprofile
+ ${artifactId}
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/mp-metrics-gauge/src/main/java/org/superbiz/rest/WeatherService.java b/examples/mp-metrics-gauge/src/main/java/org/superbiz/rest/WeatherService.java
new file mode 100644
index 00000000000..3309ab5f97a
--- /dev/null
+++ b/examples/mp-metrics-gauge/src/main/java/org/superbiz/rest/WeatherService.java
@@ -0,0 +1,28 @@
+package org.superbiz.rest;
+
+import org.eclipse.microprofile.metrics.annotation.Gauge;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+@Path("/weather")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+@ApplicationScoped
+public class WeatherService {
+
+ @Path("/day/temperature")
+ @Gauge(name = "weather_day_temperature", absolute = true, unit = "celsius",
+ displayName = "Weather Day Temperature",
+ description = "This metric shows the day temperature.",
+ tags = {"weather=temperature"})
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public Integer dayTemperature() {
+ return 30;
+ }
+}
diff --git a/examples/mp-metrics-gauge/src/test/java/org/superbiz/rest/WeatherServiceTest.java b/examples/mp-metrics-gauge/src/test/java/org/superbiz/rest/WeatherServiceTest.java
new file mode 100644
index 00000000000..9e9a8fa9d90
--- /dev/null
+++ b/examples/mp-metrics-gauge/src/test/java/org/superbiz/rest/WeatherServiceTest.java
@@ -0,0 +1,139 @@
+package org.superbiz.rest; /**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.json.Json;
+import javax.json.JsonObject;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.StringReader;
+import java.net.URL;
+import java.util.stream.Stream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(Arquillian.class)
+public class WeatherServiceTest {
+
+ @Deployment(testable = false)
+ public static WebArchive createDeployment() {
+ final WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "test.war")
+ .addClass(WeatherService.class)
+ .addAsWebInfResource(new StringAsset(""), "beans.xml");
+ return webArchive;
+ }
+
+ @ArquillianResource
+ private URL base;
+
+ private Client client;
+
+ @Before
+ public void before() {
+ this.client = ClientBuilder.newClient();
+ }
+
+ @After
+ public void after() {
+ this.client.close();
+ }
+
+ @Test
+ public void testGaugeMetric() {
+ WebTarget webTarget = this.client.target(this.base.toExternalForm());
+ final Integer temperature = webTarget
+ .path("/weather/day/temperature")
+ .request()
+ .get(Integer.class);
+ assertEquals(Integer.valueOf(30), temperature);
+
+ final String metricPath = "/metrics/application/weather_day_temperature";
+ assertPrometheusFormat(metricPath);
+ assertJsonFormat(metricPath);
+ }
+
+ private void assertPrometheusFormat(final String metricPath) {
+ WebTarget webTarget = this.client.target(this.base.toExternalForm());
+ final String metric = webTarget
+ .path(metricPath)
+ .request()
+ .accept(MediaType.TEXT_PLAIN)
+ .get(String.class);
+ assertEquals("# TYPE application:weather_day_temperature_celsius gauge\napplication:weather_day_temperature_celsius{weather=\"temperature\"} 30.0\n", metric);
+ }
+
+ private void assertJsonFormat(final String metricPath) {
+ WebTarget webTarget = this.client.target(this.base.toExternalForm());
+ final String metric = webTarget
+ .path(metricPath)
+ .request()
+ .accept(MediaType.APPLICATION_JSON)
+ .get(String.class);
+
+ assertNotNull(metric);
+
+ JsonObject metricJson = Json.createReader(new StringReader(metric)).readObject();
+ JsonObject weatherDayTemperature = metricJson.getJsonObject("weather_day_temperature");
+ assertNotNull(weatherDayTemperature);
+ assertEquals(weatherDayTemperature.getInt("value"), 30);
+ }
+
+ @Test
+ public void testGaugeMetricMetadata() {
+ WebTarget webTarget = this.client.target(this.base.toExternalForm());
+ final Response response = webTarget
+ .path("/metrics/application/weather_day_temperature")
+ .request()
+ .accept(MediaType.APPLICATION_JSON)
+ .options();
+
+ final String metaData = response.readEntity(String.class);
+ JsonObject metadataJson = Json.createReader(new StringReader(metaData)).readObject();
+
+ String[] expectedKeys = {
+ "description",
+ "displayName",
+ "name",
+ "reusable",
+ "tags",
+ "type",
+ "typeRaw",
+ "unit"
+ };
+
+ Stream.of(expectedKeys)
+ .forEach(text ->
+ assertTrue(
+ "Expected: " + text + " to be present in " + metaData,
+ metadataJson.getJsonObject("weather_day_temperature").get(text) != null));
+ }
+}
diff --git a/examples/mp-metrics-gauge/src/test/resources/arquillian.xml b/examples/mp-metrics-gauge/src/test/resources/arquillian.xml
new file mode 100644
index 00000000000..3029d48c033
--- /dev/null
+++ b/examples/mp-metrics-gauge/src/test/resources/arquillian.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+ -1
+ -1
+ microprofile
+ target/apache-tomee-remote
+ target/arquillian-test-working-dir
+
+
+
\ No newline at end of file
diff --git a/examples/pom.xml b/examples/pom.xml
index b4591a77cad..3a9998b9ad3 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -111,6 +111,7 @@
mp-metrics-counted
mp-metrics-histogram
mp-metrics-timed
+ mp-metrics-gauge
mp-rest-jwt
mp-rest-jwt-jwk
mp-rest-jwt-public-key
@@ -239,11 +240,19 @@
java9
- [9,)
+ 9
-
- java-modules
-
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+