diff --git a/build.sbt b/build.sbt index 9ef8a2b61..fcc66cced 100644 --- a/build.sbt +++ b/build.sbt @@ -513,7 +513,12 @@ lazy val micrometerPrometheus = project .settings(BuildSettings.common) .settings( name := "sst-micrometer-prometheus", - libraryDependencies += Dependencies.micrometerPrometheus + libraryDependencies ++= Seq( + Dependencies.micrometerPrometheus, + Dependencies.monixEval % Test, + Dependencies.monixExecution % Test, + Dependencies.http4sPrometheus % Test + ) ) lazy val micrometerPrometheusPureConfig = project diff --git a/micrometer-prometheus/src/main/scala/com/avast/sst/micrometer/prometheus/MicrometerPrometheusConfig.scala b/micrometer-prometheus/src/main/scala/com/avast/sst/micrometer/prometheus/MicrometerPrometheusConfig.scala index 6f87c4341..acf610971 100644 --- a/micrometer-prometheus/src/main/scala/com/avast/sst/micrometer/prometheus/MicrometerPrometheusConfig.scala +++ b/micrometer-prometheus/src/main/scala/com/avast/sst/micrometer/prometheus/MicrometerPrometheusConfig.scala @@ -1,5 +1,7 @@ package com.avast.sst.micrometer.prometheus +import io.micrometer.prometheus.HistogramFlavor + import java.util.concurrent.TimeUnit import scala.concurrent.duration.Duration @@ -7,5 +9,6 @@ final case class MicrometerPrometheusConfig( step: Duration = Duration(1, TimeUnit.MINUTES), prefix: String = "", descriptions: Boolean = true, + histogramFlavor: HistogramFlavor = HistogramFlavor.Prometheus, commonTags: Map[String, String] = Map.empty ) diff --git a/micrometer-prometheus/src/main/scala/com/avast/sst/micrometer/prometheus/MicrometerPrometheusModule.scala b/micrometer-prometheus/src/main/scala/com/avast/sst/micrometer/prometheus/MicrometerPrometheusModule.scala index 5e58ec2e8..9030c0f8a 100644 --- a/micrometer-prometheus/src/main/scala/com/avast/sst/micrometer/prometheus/MicrometerPrometheusModule.scala +++ b/micrometer-prometheus/src/main/scala/com/avast/sst/micrometer/prometheus/MicrometerPrometheusModule.scala @@ -3,7 +3,7 @@ package com.avast.sst.micrometer.prometheus import cats.effect.{Blocker, ContextShift, Resource, Sync} import com.avast.sst.micrometer.PrefixMeterFilter import io.micrometer.core.instrument.config.{MeterFilter, NamingConvention} -import io.micrometer.prometheusmetrics.{PrometheusConfig, PrometheusMeterRegistry} +import io.micrometer.prometheus.{HistogramFlavor, PrometheusConfig, PrometheusMeterRegistry} import java.time.Duration @@ -44,6 +44,7 @@ object MicrometerPrometheusModule { override val step: Duration = java.time.Duration.ofMillis(c.step.toMillis) override val prefix: String = c.prefix override val descriptions: Boolean = c.descriptions + override val histogramFlavor: HistogramFlavor = c.histogramFlavor // the method is @Nullable and we don't need to implement it here @SuppressWarnings(Array("scalafix:DisableSyntax.null")) diff --git a/micrometer-prometheus/src/test/scala/com/avast/sst/micrometer/prometheus/Http4sPrometheusCompatibilityTest.scala b/micrometer-prometheus/src/test/scala/com/avast/sst/micrometer/prometheus/Http4sPrometheusCompatibilityTest.scala new file mode 100644 index 000000000..ca3f05344 --- /dev/null +++ b/micrometer-prometheus/src/test/scala/com/avast/sst/micrometer/prometheus/Http4sPrometheusCompatibilityTest.scala @@ -0,0 +1,39 @@ +package com.avast.sst.micrometer.prometheus + +import cats.effect.* +import monix.eval.Task +import monix.eval.instances.CatsConcurrentEffectForTask +import monix.execution.Scheduler +import org.http4s.metrics.prometheus.PrometheusExportService +import org.scalatest.funsuite.AnyFunSuite + +import java.util.concurrent.{SynchronousQueue, ThreadPoolExecutor, TimeUnit} +import scala.concurrent.ExecutionContext + +class Http4sPrometheusCompatibilityTest extends AnyFunSuite { + + implicit def scheduler: Scheduler = Scheduler.global + + protected def options: Task.Options = Task.defaultOptions.withSchedulerFeatures(scheduler) + + protected implicit lazy val catsEffect: ConcurrentEffect[Task] = + new CatsConcurrentEffectForTask()(scheduler, options) + + test("Http4s Prometheus compatibility test") { + + val config = MicrometerPrometheusConfig() + + val blockingExecutor = new ThreadPoolExecutor(1, 1, 10, TimeUnit.SECONDS, new SynchronousQueue()) + val blocker = Blocker.liftExecutionContext(ExecutionContext.fromExecutor(blockingExecutor)) + + val test = for { + + prometheusMeterRegistry <- MicrometerPrometheusModule.make(config, blocker) + _ = PrometheusExportService(prometheusMeterRegistry.getPrometheusRegistry) + _ <- PrometheusExportService.addDefaults(prometheusMeterRegistry.getPrometheusRegistry) + } yield () + + test.use(_ => Task.unit).runSyncUnsafe() + + } +} diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 929349d28..eef2d3bf2 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -17,6 +17,7 @@ object Dependencies { val http4sEmberServer = "org.http4s" %% "http4s-ember-server" % Versions.http4s val http4sClient = "org.http4s" %% "http4s-client" % Versions.http4s val http4sDsl = "org.http4s" %% "http4s-dsl" % Versions.http4s + val http4sPrometheus = "org.http4s" %% "http4s-prometheus-metrics" % Versions.http4s val http4sServer = "org.http4s" %% "http4s-server" % Versions.http4s val jacksonDatabind = "com.fasterxml.jackson.core" % "jackson-databind" % "2.17.1" val jetbrainsAnnotations = "org.jetbrains" % "annotations" % "24.1.0" @@ -30,6 +31,7 @@ object Dependencies { val micrometerPrometheus = "io.micrometer" % "micrometer-registry-prometheus" % Versions.micrometerPrometheus val monixCatnap = "io.monix" %% "monix-catnap" % Versions.monix val monixEval = "io.monix" %% "monix-eval" % Versions.monix + val monixExecution = "io.monix" %% "monix-execution" % Versions.monix val postgresql = "org.postgresql" % "postgresql" % "42.7.3" val pureConfigCore = "com.github.pureconfig" %% "pureconfig-core" % Versions.pureConfig val pureConfigGeneric = "com.github.pureconfig" %% "pureconfig-generic" % Versions.pureConfig @@ -51,10 +53,10 @@ object Dependencies { val doobie = "0.13.4" val grpc = "1.64.0" val http4s = "0.22.15" - val micrometerCore = "1.13.1" - val micrometerJmx = "1.13.1" - val micrometerStatsD = "1.13.1" - val micrometerPrometheus = "1.13.1" + val micrometerCore = "1.12.7" + val micrometerJmx = "1.12.7" + val micrometerStatsD = "1.12.7" + val micrometerPrometheus = "1.12.7" val monix = "3.4.1" val pureConfig = "0.17.1"