Expose Prometheus metrics for an Akka HTTP application

Reading Time: 2 minutes

Application monitoring is an essential thing to keep the application available every time. We can do application monitoring through multiple ways such as through healthcheck endpoint, exposing metrics etc. Here, in this blog, we will see, how we can expose the metrics in Prometheus format for an Akka HTTP application.

First, we need to add below maven dependency in pom.xml:

pom.xml:

    <dependency>
            <groupId>fr.davit</groupId>
            <artifactId>akka-http-metrics-prometheus_2.12</artifactId>
            <version>1.1.1</version>
    </dependency>

Then, we need to create a MetricController where we need to create a registry and the route for the metrics:

MetricsController:

import akka.http.scaladsl.server.Directives.{path, _}
import akka.http.scaladsl.server.Route
import fr.davit.akka.http.metrics.core.scaladsl.server.HttpMetricsDirectives.metrics
import fr.davit.akka.http.metrics.prometheus.marshalling.PrometheusMarshallers._
import fr.davit.akka.http.metrics.prometheus.{Buckets, PrometheusRegistry, PrometheusSettings, Quantiles}
import io.prometheus.client.CollectorRegistry


class MetricsController {

  import MetricsController._

  val route: Route = (get & path("admin" / "prometheus" / "metrics")) (metrics(registry))
}

object MetricsController {
  val routes: Route = new MetricsController().route

  private val settings: PrometheusSettings = PrometheusSettings
    .default
    .withIncludePathDimension(true)
    .withIncludeMethodDimension(true)
    .withIncludeStatusDimension(true)
    .withDurationConfig(Buckets(1, 2, 3, 5, 8, 13, 21, 34))
    .withReceivedBytesConfig(Quantiles(0.5, 0.75, 0.9, 0.95, 0.99))
    .withSentBytesConfig(PrometheusSettings.DefaultQuantiles)
    .withDefineError(_.status.isFailure)

  private val collector: CollectorRegistry = CollectorRegistry.defaultRegistry

  val registry: PrometheusRegistry = PrometheusRegistry(collector, settings)
}

After this, we need to make the change in the main application file:

Application:

val routes = ApiController.routes ~ MetricsController.routes
val routesWithMetrics = HttpMetricsRoute(routes).recordMetrics(MetricsController.registry)
val bindingFuture = Http().bindAndHandle(routesWithMetrics, "0.0.0.0", 9000)

That’s it. We are done.

Now run the application and hit the below url:

http://localhost:9000/admin/prometheus/metrics

and you will see the metrics as below:

You can see that we are getting metrics as unlabelled for the path. If we have multiple APIs in our service then we would like to label the metrics so that we can easily differentiate the metrics. For that you need to use pathLabeled directive as follows:

pathLabeled("message", "message") {
      complete(StatusCodes.OK, "This is an application to show the way to expose the Prometheus metrics")
    }

First parameter is the label and second parameter is the path.

Now you will get the metrics as follows:

I have used the Prometheus format for the metrics, there are some more formats available in which we can expose the metrics. For more details see here.

I hope, this will be helpful for you guys. Feel free to give your suggestions as the comment to this blog.

References:

https://github.com/RustedBones/akka-http-metrics

Written by 

Rishi is a Lead Consultant, with experience of more than 7 years. Rishi is product focused developer who loves developing both front-end user interfaces and scalable back-end infrastructure. He is a good team player, quick learner and a humble person. He has good time management skills, aimed to give best results and fully dedicated towards his work & responsibilities. He is able to work as individual and as well as in team. He loves to share his knowledge, therefore he often writes technical blogs.