Expose Prometheus metrics for an Akka HTTP application

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:

  <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", 8080)

That’s it. We are done.

Now run the application and hit the below url:

http://localhost:8080/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

About Rishi Khandelwal

Rishi is a tech enthusiast with having around 10 years of experience who loves to solve complex problems with pure quality. He is a functional programmer and loves to learn new trending technologies. His leadership skill is well prooven and has delivered multiple distributed applications with high scalability and availability by keeping the Reactive principles in mind. He is well versed with Scala, Akka, Akka HTTP, Akka Streams, Java8, Reactive principles, Microservice architecture, Async programming, functional programming, distributed systems, AWS, docker.
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a comment