All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.http4s.metrics.prometheus.PrometheusExportService.scala Maven / Gradle / Ivy

/*
 * Copyright 2018 http4s.org
 *
 * Licensed 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.
 */

package org.http4s.metrics.prometheus

import cats.effect._
import cats.syntax.all._
import io.prometheus.client.CollectorRegistry
import io.prometheus.client.exporter.common.TextFormat
import io.prometheus.client.hotspot._
import java.io.StringWriter

import org.http4s.Uri.Path
import org.http4s._
import org.http4s.syntax.all._

/*
 * PrometheusExportService Contains an HttpService
 * ready to be scraped by Prometheus, paired
 * with the CollectorRegistry that it is creating
 * metrics for, allowing custom metric registration.
 */
final class PrometheusExportService[F[_]] private (
    val routes: HttpRoutes[F],
    val collectorRegistry: CollectorRegistry
)

object PrometheusExportService {

  private val metricsPath: Path = path"/metrics"

  def apply[F[_]: Sync](collectorRegistry: CollectorRegistry): PrometheusExportService[F] =
    new PrometheusExportService(service(collectorRegistry), collectorRegistry)

  def build[F[_]: Sync]: Resource[F, PrometheusExportService[F]] =
    for {
      cr <- Prometheus.collectorRegistry[F]
      _ <- addDefaults(cr)
    } yield new PrometheusExportService[F](service(cr), cr)

  def generateResponse[F[_]: Sync](collectorRegistry: CollectorRegistry): F[Response[F]] =
    Sync[F]
      .delay {
        val writer = new StringWriter
        TextFormat.write004(writer, collectorRegistry.metricFamilySamples)
        writer.toString
      }
      .map(Response[F](Status.Ok).withEntity(_))

  def service[F[_]: Sync](collectorRegistry: CollectorRegistry): HttpRoutes[F] =
    HttpRoutes.of[F] {
      case req if req.method == Method.GET && req.pathInfo == metricsPath =>
        generateResponse(collectorRegistry)
    }

  def addDefaults[F[_]: Sync](cr: CollectorRegistry): Resource[F, Unit] =
    for {
      _ <- Prometheus.registerCollector(new StandardExports(), cr)
      _ <- Prometheus.registerCollector(new MemoryPoolsExports(), cr)
      _ <- Prometheus.registerCollector(new BufferPoolsExports(), cr)
      _ <- Prometheus.registerCollector(new GarbageCollectorExports(), cr)
      _ <- Prometheus.registerCollector(new ThreadExports(), cr)
      _ <- Prometheus.registerCollector(new ClassLoadingExports(), cr)
      _ <- Prometheus.registerCollector(new VersionInfoExports(), cr)
      _ <- Prometheus.registerCollector(new MemoryAllocationExports(), cr)
    } yield ()
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy