The microprofile-metrics
quickstart demonstrates the use of the MicroProfile Metrics specification use in {productName}.
MicroProfile Metrics allows applications to expose different metrics from their execution which is necessary to provide monitoring of essential system parameters. The metrics are provided by default in the well-known Prometheus metric format which allows applications utilizing MicroProfile Metrics to be easily integrated in the common monitoring solutions.
In this quickstart, we build a collection of REST resources that expose
functionalities of the MicroProfile Metrics specification. The metrics are exposed
through the management interface at /metrics
path according to the specification.
Metrics will be collected as a part of the REST invocations.
We recommend that you follow the instructions that create the application step by step. However, you can also go right to the completed example which is available in this directory.
mvn archetype:generate \
-DgroupId=org.wildfly.quickstarts \
-DartifactId=microprofile-metrics \
-DinteractiveMode=false \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-webapp
cd microprofile-metrics
Open the project in your favourite IDE.
Open the generated pom.xml
.
The first thing to do is to setup our dependencies. Add the following section to your
pom.xml
:
<dependencyManagement>
<dependencies>
<!-- importing the microprofile BOM adds MicroProfile specs -->
<dependency>
<groupId>org.wildfly.bom</groupId>
<artifactId>wildfly-microprofile</artifactId>
<version>{versionMicroprofileBom}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Now we need to add the following dependencies:
<!-- Import the MicroProfile Metrics API, we use provided scope as the API is included in the server -->
<dependency>
<groupId>org.eclipse.microprofile.metrics</groupId>
<artifactId>microprofile-metrics-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- Import the CDI API, we use provided scope as the API is included in the server -->
<dependency>
<groupId>jakarta.enterprise</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- Import the Jakarta REST API, we use provided scope as the API is included in the server -->
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
<scope>provided</scope>
</dependency>
Note
|
Because the MicroProfile Metrics specifications uses CDI injection to expose some of its functionality in the user application we need to also include the CDI API dependency. |
All dependencies can have provided scope.
As we are going to be deploying this application to the {productName} server, let’s also add a maven plugin that will simplify the deployment operations (you can replace the generated build section):
<build>
<!-- Set the name of the archive -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- Allows to use mvn wildfly:deploy -->
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
As this is a Jakarta REST application we need to also create an application class.
Create org.wildfly.quickstarts.microprofile.metrics.JaxRsApplication
with the following
content:
Note
|
The new file should be created in
src/main/java/org/quickstarts/microprofile/metrics/JaxRsApplication.java .
|
package org.wildfly.quickstarts.microprofile.metrics;
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;
@ApplicationPath("/")
public class JaxRsApplication extends Application {
}
Now we are ready to start working with MicroProfile Metrics.
The MicroProfile Metrics exposes all collected metrics at a single REST endpoint
/metrics
. Even without any direct interaction, {productName} server already collects
and exposes some metrics. You can check the metrics anytime by accessing the
http://localhost:9990/metrics
endpoint using your browser or
curl http://localhost:9990/metrics
.
Note
|
Don’t forget to have {productName} server started. |
You will get back a text file similar to this:
# HELP base_cpu_processCpuLoad Displays the "recent cpu usage" for the Java Virtual Machine process.
# TYPE base_cpu_processCpuLoad gauge
base_cpu_processCpuLoad 0.005753138075313807
# HELP base_memory_committedNonHeap_bytes Displays the amount of memory that is committed for the Java virtual machine to use.
# TYPE base_memory_committedNonHeap_bytes gauge
base_memory_committedNonHeap_bytes 8.9915392E7
This is a Prometheus format which is directly consumable by
the Prometheus monitoring system. This is a default
format. If you prefer for your testing to use rather the JSON format you need to
specify the HTTP header Accepted: application/json
with for
instance curl -H "Accept: application/json" http://localhost:9990/metrics
.
The MicroProfile Metrics specification defines three different scopes of metrics:
-
Base scope (
/metrics/base
)- the metrics that all MicroProfile vendors have to provide -
Vendor scope (
/metrics/vendor
) - vendor specific metrics -
Application scope (
/metrics/application
) - application specific metrics
Base scope metrics cover the metrics that are generally useful in any environment
like memory.usedHeap
or thread.count
. For the full list of required metrics
please access the
http://localhost:9990/metrics/base
endpoint using your browser or
curl http://localhost:9990/metrics/base
.
Vendor metrics represent custom metrics that are provided by the implementation of
the MicroProfile Metrics specification which are in our case the custom metrics
provided by the {productName} server. To see the full list please access
the http://localhost:9990/metrics/vendor
endpoint using your browser or
curl http://localhost:9990/metrics/vendor
. You can note that there are custom
metrics exposed by the individual {productName} subsystems which are prefixed by
wildfly_
.
The application scope covers the metrics defined by your application. We will demonstrate how to define application metrics in the following sections.
So far we’ve accessed the metrics only with the HTTP GET requests which will always return the individual values of the requested metrics. The specification also provides an OPTIONS method requests for users to request the metrics metadata:
Perform a request
curl -X OPTIONS -H "Accept: application/json" http://localhost:9990/metrics
and you
can see that the returned JSON now contains metadata about individual metrics like
unit, type, description, display name and tags. We will see later on how you can
change these values for your custom applications scoped metrics.
So far we’ve covered how we can access the metrics which are already predefined in the {productName} server. Let’s now define some custom application metrics.
The MicroProfile Metrics specification defines several types of application metrics:
-
@Counted
- counts the invocations of the annotated object -
@Timed
- tracks the duration of the annotated object -
@Gauge
- samples the value of the annotated object -
@ConcurrentGauge
- gauge that counts parallel invocations of the annotated object -
@Metered
- tracks the frequency of invocation of the annotated object -
@Metric
- injection of the metric object
Let’s see how we can use these annotations in our application. Create a new class
org.wildfly.quickstarts.microprofile.metrics.PrimeNumberChecker
:
package org.wildfly.quickstarts.microprofile.metrics;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/")
@ApplicationScoped
public class PrimeNumberChecker {
@GET
@Path("/prime/{number}")
@Produces(MediaType.TEXT_PLAIN)
public String checkIfPrime(@PathParam("number") long number) {
if (number < 1) {
return "Only natural numbers can be prime numbers.";
}
if (number == 1) {
return "1 is not prime.";
}
if (number == 2) {
return "2 is prime.";
}
if (number % 2 == 0) {
return number + " is not prime, it is divisible by 2.";
}
for (int i = 3; i < Math.floor(Math.sqrt(number)) + 1; i = i + 2) {
if (number % i == 0) {
return number + " is not prime, is divisible by " + i + ".";
}
}
return number + " is prime.";
}
}
This class represents a simple REST endpoint that is able to determine whether the number passed as a path parameter is a prime number.
Build and redeploy the application
$ mvn clean package wildfly:deploy
Now you can access http://localhost:8080/microprofile-metrics/prime/350
endpoint using your browser or
curl http://localhost:8080/microprofile-metrics/prime/350
to check whether the
number 350
is a prime number.
Note
|
You can of course try this endpoint with different numbers. |
Now we are ready to add our custom metrics to this REST resource. If you try to access
the application metrics now (http://localhost:9990/metrics/application
) it should be
empty.
Update the PrimeNumberChecker
:
package org.wildfly.quickstarts.microprofile.metrics;
import org.eclipse.microprofile.metrics.annotation.Counted;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/")
@ApplicationScoped
public class PrimeNumberChecker {
@GET
@Path("/prime/{number}")
@Produces(MediaType.TEXT_PLAIN)
@Counted
public String checkIfPrime(@PathParam("number") long number) {
if (number < 1) {
return "Only natural numbers can be prime numbers.";
}
if (number == 1) {
return "1 is not prime.";
}
if (number == 2) {
return "2 is prime.";
}
if (number % 2 == 0) {
return number + " is not prime, it is divisible by 2.";
}
for (int i = 3; i < Math.floor(Math.sqrt(number)) + 1; i = i + 2) {
if (number % i == 0) {
return number + " is not prime, is divisible by " + i + ".";
}
}
return number + " is prime.";
}
}
Just by adding this single annotation we are already exposing the counter metric
that will be counting the invocations of the annotated method. If you now redeploy
your application (mvn clean package wildfly:deploy
) and try to access your
application metrics again (http://localhost:9990/metrics/application
) you will see
something like this:
{
"org.wildfly.quickstarts.microprofile.metrics.PrimeNumberChecker.checkIfPrime": 0
}
Try now to invoke the REST endpoint several times and you will see the counter works as expected.
If you perform an OPTIONS request for this metrics, it’s values should be empty.
$ curl -X OPTIONS -H "Accept: application/json" http://localhost:9990/metrics/application
{
"org.wildfly.quickstarts.microprofile.metrics.PrimeNumberChecker.checkIfPrime": {
"unit": "none",
"type": "counter",
"description": "",
"displayName": "",
"tags": [
[
]
]
}
}
To change these values you can simply edit the parameters in the @Counted
annotation (similarly for other annotations).
@Counted(name = "performedChecks", displayName="Performed Checks", description = "How many prime checks have been performed.")
And rebuild, redeploy your application to the {productName} server and access the application metrics metadata again:
mvn clean package wildfly:deploy
curl -X OPTIONS -H "Accept: application/json" http://localhost:9990/metrics/application
{
"org.wildfly.quickstarts.microprofile.metrics.PrimeNumberChecker.performedChecks": {
"unit": "none",
"type": "counter",
"description": "How many prime checks have been performed.",
"displayName": "Performed Checks",
"tags": [
[
]
]
}
}
Timed annotation declares a timer which will time the duration of how long our
method is executing. Add the following annotation to our checkIfPrime
method:
@GET
@Path("/prime/{number}")
@Produces(MediaType.TEXT_PLAIN)
@Counted(name = "performedChecks", displayName="Performed Checks", description = "How many prime checks have been performed.")
@Timed(name = "checksTimer", absolute = true, description = "A measure of how long it takes to perform the primality test.", unit = MetricUnits.MILLISECONDS)
public String checkIfPrime(@PathParam("number") long number) {
Note
|
Note the parameter absolute = true this will make our metric name to be
not prefixed by the fully qualified package of the class where our check is located.
|
And rebuild, redeploy your application to the {productName} server, invoke the method several times, and access the application metrics data again:
mvn clean package wildfly:deploy
curl http://localhost:8080/microprofile-metrics/prime/350
curl http://localhost:8080/microprofile-metrics/prime/7
curl http://localhost:8080/microprofile-metrics/prime/29
curl -H "Accept: application/json" http://localhost:9990/metrics/application
{
"org.wildfly.quickstarts.microprofile.metrics.PrimeNumberChecker.performedChecks": 3,
"checksTimer": {
"p99": 0.136153,
"min": 0.01075,
"max": 0.136153,
"mean": 0.07816790480018097,
"p50": 0.088464,
"p999": 0.136153,
"stddev": 0.05164982729810127,
"p95": 0.136153,
"p98": 0.136153,
"p75": 0.136153,
"fiveMinRate": 0.0,
"fifteenMinRate": 0.0,
"meanRate": 5.254614407952331,
"count": 3,
"oneMinRate": 0.0
}
}
Note the name of our timer check is only what we defined in our annotation because of
the absolute = true
. You can also access particular check directly:
curl -H "Accept: application/json" http://localhost:9990/metrics/application/checksTimer
{
"checksTimer": {
"p99": 0.136153,
"min": 0.01075,
"max": 0.136153,
"mean": 0.07816790480018097,
"p50": 0.088464,
"p999": 0.136153,
"stddev": 0.05164982729810127,
"p95": 0.136153,
"p98": 0.136153,
"p75": 0.136153,
"fiveMinRate": 0.4595570030187892,
"fifteenMinRate": 0.5489683372380184,
"meanRate": 0.03506919414327886,
"count": 3,
"oneMinRate": 0.1581582828694362
}
}
Gauge is the most variable metric which is fully up to the application. It is
required to define the metric type for this kind of metric. Let’s update
the PrimeNumberChecker
:
package org.wildfly.quickstarts.microprofile.metrics;
import org.eclipse.microprofile.metrics.MetricUnits;
import org.eclipse.microprofile.metrics.annotation.Counted;
import org.eclipse.microprofile.metrics.annotation.Gauge;
import org.eclipse.microprofile.metrics.annotation.Timed;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/")
@ApplicationScoped
public class PrimeNumberChecker {
private long highestPrimeNumberSoFar = 2;
@GET
@Path("/prime/{number}")
@Produces(MediaType.TEXT_PLAIN)
@Counted(name = "performedChecks", displayName="Performed Checks", description = "How many prime checks have been performed.")
@Timed(name = "checksTimer", absolute = true, description = "A measure of how long it takes to perform the primality test.", unit = MetricUnits.MILLISECONDS)
public String checkIfPrime(@PathParam("number") long number) {
if (number < 1) {
return "Only natural numbers can be prime numbers.";
}
if (number == 1) {
return "1 is not prime.";
}
if (number == 2) {
return "2 is prime.";
}
if (number % 2 == 0) {
return number + " is not prime, it is divisible by 2.";
}
for (int i = 3; i < Math.floor(Math.sqrt(number)) + 1; i = i + 2) {
if (number % i == 0) {
return number + " is not prime, is divisible by " + i + ".";
}
}
if (number > highestPrimeNumberSoFar) {
highestPrimeNumberSoFar = number;
}
return number + " is prime.";
}
@Gauge(name = "highestPrimeNumberSoFar", unit = MetricUnits.NONE, description = "Highest prime number so far.")
public Long highestPrimeNumberSoFar() {
return highestPrimeNumberSoFar;
}
}
Warning
|
The metric unit for gauges is required to be defined in the annotation. |
And rebuild, redeploy your application to the {productName} server, invoke the method several times, and access the application metrics data again:
mvn clean package wildfly:deploy
curl http://localhost:8080/microprofile-metrics/prime/350
curl http://localhost:8080/microprofile-metrics/prime/7
curl http://localhost:8080/microprofile-metrics/prime/29
curl -H "Accept: application/json" http://localhost:9990/metrics/application
{
"org.wildfly.quickstarts.microprofile.metrics.PrimeNumberChecker.highestPrimeNumberSoFar": 29,
"org.wildfly.quickstarts.microprofile.metrics.PrimeNumberChecker.performedChecks": 3,
"checksTimer": {
"p99": 0.187263,
"min": 0.02916,
"max": 0.187263,
"mean": 0.121405,
"p50": 0.147792,
"p999": 0.187263,
"stddev": 0.06718801966124616,
"p95": 0.187263,
"p98": 0.187263,
"p75": 0.187263,
"fiveMinRate": 0.0,
"fifteenMinRate": 0.0,
"meanRate": 5.571895665830193,
"count": 3,
"oneMinRate": 0.0
}
}
Of course, gauges can be any value your application need. This is a fully customizable metric type.
As stated above, concurrent gauge is a gauge that count the number of parallel
accesses to a particular object. Let’s add a new method to PrimeNumbersChecker
:
private CountDownLatch countDownLatch = new CountDownLatch(1);
@GET
@Path("/parallel")
@ConcurrentGauge(name = "parallelAccess", description = "Number of parallel accesses")
public void parallelAccess() throws InterruptedException {
countDownLatch.await();
System.out.println("DONE");
}
@GET
@Path("/parallel-finish")
public void parallelFinish() {
countDownLatch.countDown();
System.out.println("Finished parallel execution");
}
Now let’s try to exercise it:
mvn clean package wildfly:deploy
for i in {1..3}; do curl http://localhost:8080/microprofile-metrics/parallel & done
sleep 1
curl -H "Accept: application/json" http://localhost:9990/metrics/application
{
"org.wildfly.quickstarts.microprofile.metrics.PrimeNumberChecker.highestPrimeNumberSoFar": 2,
"org.wildfly.quickstarts.microprofile.metrics.PrimeNumberChecker.performedChecks": 0,
"org.wildfly.quickstarts.microprofile.metrics.PrimeNumberChecker.parallelAccess": {
"current": 3,
"min": 0,
"max": 0
},
"checksTimer": {
"p99": 0.0,
"min": 0.0,
"max": 0.0,
"mean": 0.0,
"p50": 0.0,
"p999": 0.0,
"stddev": 0.0,
"p95": 0.0,
"p98": 0.0,
"p75": 0.0,
"fiveMinRate": 0.0,
"fifteenMinRate": 0.0,
"meanRate": 0.0,
"count": 0,
"oneMinRate": 0.0
}
}
As you can see the 3 started requests are currently executed in parallel. You can
finish them by a call to http://localhost:8080/microprofile-metrics/parallel-finish
.
A meter is a metric type that tracks the frequency of incovations. Let’s update our
checkIfPrime
method:
@GET
@Path("/prime/{number}")
@Produces(MediaType.TEXT_PLAIN)
@Counted(name = "performedChecks", displayName="Performed Checks", description = "How many prime checks have been performed.")
@Timed(name = "checksTimer", absolute = true, description = "A measure of how long it takes to perform the primality test.", unit = MetricUnits.MILLISECONDS)
@Metered(name = "checkIfPrimeFrequency", absolute = true)
public String checkIfPrime(@PathParam("number") long number) {
And rebuid, redeploy your application to the {productName} server, invoke the method several times, and access the application metrics data again:
mvn clean package wildfly:deploy
curl http://localhost:8080/microprofile-metrics/prime/350
curl http://localhost:8080/microprofile-metrics/prime/7
curl http://localhost:8080/microprofile-metrics/prime/29
curl -H "Accept: application/json" http://localhost:9990/metrics/application
{
"org.wildfly.quickstarts.microprofile.metrics.PrimeNumberChecker.highestPrimeNumberSoFar": 7,
"checkIfPrimeFrequency": {
"fiveMinRate": 0.0,
"fifteenMinRate": 0.0,
"meanRate": 6.804175994067375,
"count": 3,
"oneMinRate": 0.0
},
"org.wildfly.quickstarts.microprofile.metrics.PrimeNumberChecker.performedChecks": 3,
"org.wildfly.quickstarts.microprofile.metrics.PrimeNumberChecker.parallelAccess": {
"current": 0,
"min": 0,
"max": 0
},
"checksTimer": {
"p99": 0.063733,
"min": 0.00611,
"max": 0.063733,
"mean": 0.04252133333333333,
"p50": 0.057721,
"p999": 0.063733,
"stddev": 0.0258634224640815,
"p95": 0.063733,
"p98": 0.063733,
"p75": 0.063733,
"fiveMinRate": 0.0,
"fifteenMinRate": 0.0,
"meanRate": 6.794024967566174,
"count": 3,
"oneMinRate": 0.0
}
}
The last annotation is the @Metric
which is used to inject or produce a metric.
Let’s add the following code into PrimeNumberChecker
:
@Inject
@Metric(name = "injectedCounter", absolute = true)
private Counter injectedCounter;
@GET
@Path("/injected-metric")
public String injectedMetric() {
injectedCounter.inc();
return "counter invoked";
}
And rebuid, redeploy your application to the {productName} server, invoke the method several times, and access the application metrics data again:
mvn clean package wildfly:deploy
curl http://localhost:8080/microprofile-metrics/injected-metric
curl http://localhost:8080/microprofile-metrics/injected-metric
curl http://localhost:8080/microprofile-metrics/injected-metric
curl -H "Accept: application/json" http://localhost:9990/metrics/application/injectedCounter
{
"injectedCounter": 3
}
The types that can be injected and produced are Counter
, Timer
, Meter
,
Histogram
. Gauge
can be only produced.
A metric registry a collection of metrics that corresponds to the different metric
scopes the MicroProfile Metrics specification defines. To access the
MetricRegistry
you can inject and use it like this. Add the following code to
PrimeNumberChecker
:
@Inject
@RegistryType(type = MetricRegistry.Type.APPLICATION)
private MetricRegistry applicationRegistry;
@GET
@Path("/registry")
public void registry() {
// register a new application scoped metric
Counter programmaticCounter = applicationRegistry.counter(Metadata.builder()
.withName("programmaticCounter")
.withDescription("Programmatically created counter")
.build());
programmaticCounter.inc(42);
}
Note
|
You need to also set the Java language level to Java 8 to use the interface method invocations. |
And rebuid, redeploy your application to the {productName} server, invoke the method , and access the application metrics data again:
mvn clean package wildfly:deploy
curl http://localhost:8080/microprofile-metrics/registry
curl -H "Accept: application/json" http://localhost:9990/metrics/application/programmaticCounter
{
"programmaticCounter": 42
}
The tag is basically only a key-value pair that can be associated with a metric. This
means that we can have a metrics which have the same name if the tags differ. This
kind of labels are very common in modern microservices orchestration services like
Kubernetes. Tags can be set as a part of metadata in the
individual annotations or when you are registering a new metric with the metric
registry. Add the following code to PrimeNumberChecker
:
@GET
@Path("/duplicates")
@Counted(name = "duplicatedCounter", absolute = true, tags = {"type=original"})
public String duplicates() {
return "duplicated metrics";
}
@GET
@Path("/duplicates2")
@Counted(name = "duplicatedCounter", absolute = true, tags = {"type=copy"})
public String duplicates2() {
return "duplicated metrics";
}
And rebuid, redeploy your application to the {productName} server, invoke the method , and access the application metrics data again:
mvn clean package wildfly:deploy
curl http://localhost:8080/microprofile-metrics/duplicates
curl http://localhost:8080/microprofile-metrics/duplicates2
curl -H "Accept: application/json" http://localhost:9990/metrics/application/duplicatedCounter
{
"duplicatedCounter;type=original": 1,
"duplicatedCounter;type=copy": 1
}
So far we exposed the metrics from our service but we didn’t consume them efficiently
(in production we need to monitor services for long periods so manually invoking
/metrics
endpoint is not acceptable). As mentioned above, MicroProfile Metrics
expose the metrics by default in the Prometheus format. So let’s route our exposed
metrics from {productName} to an instance of Prometheus.
Note
|
In this section we will be running external microservices as Docker containers. If you don’t have Docker installed on your machine please follow the instructions at https://www.docker.com/get-started. |
Prometheus is a monitoring system and time series database. You can find more information at https://prometheus.io/. To start the Prometheus instance on our local computer we need:
-
a
prometheus.yml
file with the following content - prometheus.yml -
Docker installed and running
To start the prometheus docker container run the following command:
docker run --rm --name prometheus -p 9090:9090 --network host \
-v /path/to/prometheus.yml:/etc/prometheus/prometheus.yml:Z prom/prometheus:v2.14.0 \
--config.file=/etc/prometheus/prometheus.yml
Wait for the container to start and then you can access http://localhost:9090
in
your browser to view the Prometheus console. Because we configured Prometheus (in
prometheus.yml
) to scrap our prime-checker
service running on {productName} server
we can directly access the collected metrics which Prometheus collects from
http://localhost:9990/metrics
. You can test it by typing for instance
application_org_wildfly_quickstart_microprofile_metrics_PrimeNumberChecker_performedChecks_total
as the query expression and executing this query.
Congratulations. Your service metrics are now queried by Prometheus every second so you can try to make a few request for prime numbers and see the values reflected in the console.
Now that we have the Prometheus collecting the metrics we can expose Grafana. Grafana is analytics & monitoring solution which can be viewed as a nice presentation of metrics which we are being collected in the Prometheus. You can find more information about Grafana at https://grafana.com/.
To run Grafana make sure that the Prometheus is started and collecting metrics. If you followed previous section, the prometheus should be running.
To start Grafana you can run:
docker run --rm -p 3000:3000 --network host grafana/grafana:6.4.4
This will expose Grafana console at http://localhost:3000
. You can login with
default admin user (admin:admin
).
The first thing we need to do with the new Grafana instance is to add a data source.
Click the Add data source
button on the welcome page. Select Prometheus
. In
the HTTP section set URL to be http://localhost:9090
and change the Scrape
interval
to be 1s
. Click Save & Test
.
Now is the time to add a new dashboard with the metrics we are interested in. You can add a new custom dashboard and new panels manually (the UI is intuitive) or you can skip the manual configuration with the following simple provided dashboard:
-
click plus sign on the left side →
Import
-
paste the following JSON - grafana.json
-
set the Prometheus (Prometheus = Prometheus) data source on the next screen and click
Import
. You will see four simple panels displaying some of the application metrics that we exposed in our {productName} server.
Note
|
In production you typically do not run these service yourself but they are provided for you by operations or platform directly. So you just need to pass the location of your services to allow these services to collect metrics for you. |
You can again make several requests for prime numbers
(e.g., http://localhost:8080/microprofile-metrics/prime/7
) to see how the metrics
change.
MicroProfile Metrics provide a way for your application to expose metrics about your application/service to the outside world. They expose the metrics in a well-known Prometheus format which is directly consumable in the cloud environment. The more information can be found in the MicroProfile Metrics specification.