diff --git a/build.sbt b/build.sbt index 799ec48b..a02c8ff8 100644 --- a/build.sbt +++ b/build.sbt @@ -54,7 +54,7 @@ lazy val prometheus = project .settings( name := "prometheus", stdSettings("metrics-prometheus") ++ settings, - libraryDependencies ++= commonDependencies ++ prometheusDependencies + libraryDependencies ++= commonDependencies ++ prometheusDependencies ++ dropwizardDependencies ) .dependsOn(common) diff --git a/docs/essentials/index.md b/docs/essentials/index.md index 1ffe36b9..f45a6861 100644 --- a/docs/essentials/index.md +++ b/docs/essentials/index.md @@ -24,7 +24,7 @@ both Prometheus and Dropwizard library. `ZIO-Metrics` is available via maven repo so import in `build.sbt` is sufficient: ```scala -libraryDependencies += "dev.zio" %% "zio-metrics" % "0.0.4" +libraryDependencies += "dev.zio" %% "zio-metrics" % "0.0.5" ``` ## References diff --git a/docs/essentials/prometheus.md b/docs/essentials/prometheus.md index 35ea5ca2..073e587b 100644 --- a/docs/essentials/prometheus.md +++ b/docs/essentials/prometheus.md @@ -4,7 +4,7 @@ title: "Prometheus ZIO Wrapper" --- ZIO Metrics Prometheus provides Prometheus' 5 metrics plus a number of -exporters all connected through the `CollectorRegstyr`. +exporters all connected through the `CollectorRegstry`. Required imports for presented snippets: @@ -12,8 +12,9 @@ Required imports for presented snippets: import zio.{ RIO, Runtime } import io.prometheus.client.CollectorRegistry import zio.internal.PlatformLive -import zio.metrics.{ Label => PLabel, _ } -import zio.metrics.prometheus.{ counter => counterHelper, _} +import zio.metrics.{ Label => ZLabel, Show, DefaultBuckets, LinearBuckets, ExponentialBuckets } +import zio.metrics.prometheus._ +import zio.metrics.prometheus.helpers._ // also for printing debug messages to the console import zio.console.{ Console, putStrLn } @@ -29,17 +30,16 @@ We will also provide our own `Runtime`: ```scala mdoc:silent val rt = Runtime( - new PrometheusRegistry with PrometheusCounter with PrometheusGauge with PrometheusHistogram - with PrometheusSummary with PrometheusExporters with Console.Live with Clock.Live, + new PrometheusRegistry with PrometheusExporters with Console.Live with Clock.Live, PlatformLive.Default ) ``` -We include ALL 5 metrics since we will see an example for each one, normally you +We include ALL 5 metrics in the `runtime` since we will see examples for each, normally you just need to include the ones you will actually use. -We will assume the reader knows has working knowledge for Prometheus already, if +We will assume the reader has working knowledge for Prometheus already, if not then head over to [Prometheus Java Client](https://github.com/prometheus/client_java). ## Registry @@ -55,134 +55,131 @@ zio-metrics methods. We'll start using environmental effects until the `Helper` methods are introduced: ```scala mdoc:silent - val testRegistry: RIO[PrometheusRegistry with PrometheusCounter, CollectorRegistry] = for { + val testRegistry: RIO[PrometheusRegistry, CollectorRegistry] = for { pr <- RIO.environment[PrometheusRegistry] - _ <- pr.registry.registerCounter(PLabel("simple_counter", Array("method"))) + _ <- pr.registry.registerCounter(ZLabel("simple_counter", Array("method"))) r <- pr.registry.getCurrent() } yield r ``` -All `register*` methods require `Label` object (some require some more -parameters). A label is composed of a name and an array of labels which may be -empty in the case of no labels. +All `register*` methods in `PrometheusRegistry` require a `Label` object (some +may require more parameters). A label is composed of a name and an array of +labels which may be empty in the case where no labels are required. ```scala mdoc:silent case class Label[A: Show](name: A, labels: Array[String]) ``` -Note that zio-metrics does not depend on either cats or scalaz so this `Show` is -defined on -[typeclasses](https://github.com/zio/zio-metrics/blob/master/common/src/main/scala/zio/metrics/typeclasses.scala) -with instances for `String` and `Class[A]`. +Note that zio-metrics does not depend on either cats or scalaz so this Show is defined on typeclasses with instances for String and Class[A]. +Besides the `register*` functions, we also have `getCurrent()` that simply +returns the `CollectorRegistry` which is needed by all `Exporters`. -Then we also have `getCurrent()` that simply returns the `CollectorRegistry` and -is needed by all `Exporters`. +Using the registry helper the above becomes: +```scala mdoc:silent + val testRegistryHelper: RIO[PrometheusRegistry, CollectorRegistry] = for { + _ <- registry.registerCounter("simple_counter", Array("method")) + r <- registry.getCurrent() + } yield r +``` ## Counter Counter has methods to increase a counter by 1 or by an arbitrary double passed as a parameter along with optional labels. ```scala mdoc:silent - val testCounter: RIO[PrometheusRegistry with PrometheusCounter, CollectorRegistry] = for { - pr <- RIO.environment[PrometheusRegistry] - c <- pr.registry.registerCounter(PLabel("simple_counter", Array.empty[String])) - pc <- RIO.environment[PrometheusCounter] - _ <- pc.counter.inc(c, Array.empty[String]) - _ <- pc.counter.inc(c, 2.0, Array.empty[String]) - r <- pr.registry.getCurrent() + val testCounter: RIO[PrometheusRegistry, CollectorRegistry] = for { + c <- Counter("simple_counter", Array.empty[String]) + _ <- c.inc() + _ <- c.inc(2.0) + r <- registry.getCurrent() } yield r ``` If the counter is registered with labels, then you need to increase the counter passing the same number of labels when registered. + ```scala mdoc:silent - val testLabeledCounter: RIO[PrometheusRegistry with PrometheusCounter, CollectorRegistry] = for { - pr <- RIO.environment[PrometheusRegistry] - c <- pr.registry.registerCounter(PLabel("simple_counter", Array("method", "resource"))) - pc <- RIO.environment[PrometheusCounter] - _ <- pc.counter.inc(c, Array("get", "users")) - _ <- pc.counter.inc(c, 2.0, Array("get", "users")) - r <- pr.registry.getCurrent() + val testLabeledCounter: RIO[PrometheusRegistry, CollectorRegistry] = for { + c <- Counter("simple_counter_labeled", Array("method", "resource")) + _ <- c.inc(Array("get", "users")) + _ <- c.inc(2.0, Array("get", "users")) + r <- registry.getCurrent() } yield r ``` You can run and verify the results so: + ```scala mdoc:silent val set: util.Set[String] = new util.HashSet[String]() set.add("simple_counter") val r = rt.unsafeRun(testCounter) - val counter = r + val count = r .filteredMetricFamilySamples(set) .nextElement() .samples .get(0) .value - assert(counter == 3.0) + assert(count == 3.0) ``` There's an easier way to observe the state of the `CollectorRegistry` using the `write004` Exporter covered later. -Also notice that `counter` here is a [helper method](https://github.com/zio/zio-metrics/blob/master/prometheus/src/main/scala/zio/metrics/prometheus/Helpers.scala) that makes it easier to call -the actual methods from `Counter`. - ## Helpers -Environmental effects gives us access direct access to zio-metrics' modules -which means we have to create `Label` objects for the name, empty arrays when -we do not use any labels, etc. Helper methods take care of all the boilerplate +Environmental effects gives us access direct access to zio-metrics' `Metrics` +which means we have to pass empty arrays and other `Default` parameters when +we do not use any labels or special configuration. Helper methods take care of all the boilerplate and gives us easy-to-use functions. Using them out `testCounter` example above becomes: ```scala mdoc:silent - val testCounterHelper: RIO[PrometheusRegistry with PrometheusCounter, CollectorRegistry] = for { - c <- registry.registerCounter("simple_counter") - _ <- counterHelper.inc(c) - _ <- counterHelper.inc(c, 2.0) - r <- registry.getCurrent() + val testCounterHelper: RIO[PrometheusRegistry, CollectorRegistry] = for { + c <- counter.register("PrometheusTestHelper") + _ <- c.inc() + _ <- c.inc(2.0) + r <- registry.getCurrent() } yield r ``` -This version accepts directly either a `String` or a `Class` for a name, the -helper method creates the `Label` for us as well as the empty array for the -labels. There are also helper methods that supports an array for labels: +This version accepts directly either a `String` for a name, the +helper method creates the empty array the labels parameter needs. There are also +helper methods that supports an array for labels: -```scala mdoc:silent - val testCounterHelperLabels: RIO[PrometheusRegistry with PrometheusCounter, CollectorRegistry] = for { - c <- registry.registerCounter("simple_counter", Array("method", "resource")) - _ <- counterHelper.inc(c, Array("get", "users")) - _ <- counterHelper.inc(c, 2.0, Array("get", "users")) - r <- registry.getCurrent() - } yield r +``` + c <- counter.register("PrometheusTestHelper, Array("method", "resource")") ``` -From here on. we will use environmental efects, helper methods and a mix of both. +From here on. we will use environmental efects, helper methods or a mix of both. ## Gauge Besides increasing, a gauge may also decrease and has methods to `set` and `get` values as well as to `setToTime` and `setToCurrentTime`. ```scala mdoc:silent - val testGauge: RIO[PrometheusRegistry with PrometheusGauge, (CollectorRegistry, Double)] = for { + val testGauge: RIO[PrometheusRegistry, (CollectorRegistry, Double)] = for { + g <- gauge.register("simple_gauge") + _ <- g.inc() + _ <- g.inc(2.0) + _ <- g.dec(1.0) + d <- g.getValue() r <- registry.getCurrent() - g <- registry.registerGauge("simple_gauge", Array.empty[String]) - _ <- gauge.inc(g) - _ <- gauge.inc(g, 2.0) - d <- gauge.getValue(g) } yield (r, d) ``` Here I chose to return both the `CollectorRegistry` and the latest value from the gauge as a tuple. `gauge` refers to the [helper method](https://github.com/zio/zio-metrics/blob/master/prometheus/src/main/scala/zio/metrics/prometheus/Helpers.scala). + With labels it looks like this: ```scala mdoc:silent - val testLabeledGauge: RIO[PrometheusRegistry with PrometheusGauge, (CollectorRegistry, Double)] = for { + val testLabeledGauge: RIO[PrometheusRegistry, (CollectorRegistry, Double)] = for { + g <- Gauge("simple_gauge", Array("method")) + _ <- g.inc(Array("get")) + _ <- g.inc(2.0, Array("get")) + _ <- g.dec(1.0, Array("get")) + d <- g.getValue(Array("get")) r <- registry.getCurrent() - g <- registry.registerGauge("simple_gauge", Array("method")) - _ <- gauge.inc(g, Array("get")) - _ <- gauge.inc(g, 2.0, Array("get")) - d <- gauge.getValue(g, Array("get")) } yield (r, d) ``` @@ -199,7 +196,7 @@ And to run and verify the result: .value assert(a1 == rG._2) - assert(a1 == 3.0) + assert(a1 == 2.0) ``` This way to verify our metrics is awkward and cumbersome, let's look at what @@ -224,21 +221,20 @@ given registry. Let's look at an example of how all this works. ```scala mdoc:silent import io.prometheus.client.exporter.HTTPServer - + val exporterTest: RIO[ - PrometheusRegistry with PrometheusCounter with PrometheusHistogram - with PrometheusExporters with Console, + PrometheusRegistry with PrometheusExporters with Console, HTTPServer ] = for { r <- registry.getCurrent() _ <- exporters.initializeDefaultExports(r) hs <- exporters.http(r, 9090) - c <- registry.registerCounter("ExportersTest", Array("exporter")) - _ <- counterHelper.inc(c, Array("counter")) - _ <- counterHelper.inc(c, 2.0, Array("counter")) - h <- registry.registerHistogram("export_histogram", Array("exporter", "method")) - _ <- histogram.time(h, () => Thread.sleep(2000), Array("histogram", "get")) + c <- Counter("ExportersTest", Array("exporter")) + _ <- c.inc(Array("counter")) + _ <- c.inc(2.0, Array("counter")) + h <- histogram.register("export_histogram", Array("exporter", "method")) + _ <- h.time(() => Thread.sleep(2000), Array("histogram", "get")) s <- exporters.write004(r) _ <- putStrLn(s) } yield hs @@ -266,11 +262,10 @@ Using a histogram to `time` a function is pretty much what was shown on the want to time: ```scala mdoc:silent - val testHistogramTimer: RIO[PrometheusRegistry with PrometheusHistogram, CollectorRegistry] = for { - pr <- RIO.environment[PrometheusRegistry] - h <- pr.registry.registerHistogram(PLabel("simple_histogram_timer", Array("method")), DefaultBuckets(Seq.empty[Double])) - _ <- histogram.time(h, () => Thread.sleep(2000), Array("post").reverse ) - r <- pr.registry.getCurrent() + val testHistogramTimer: RIO[PrometheusRegistry, CollectorRegistry] = for { + h <- histogram.register("simple_histogram_timer", Array("method")) + _ <- h.time(() => Thread.sleep(2000), Array("post")) + r <- registry.getCurrent() } yield r ``` @@ -279,10 +274,10 @@ buckets](https://prometheus.github.io/client_java/io/prometheus/client/Histogram , for instance, we can use `Linear Buckets` with the function above: ```scala mdoc:silent - val testHistogramTimerHelper: RIO[PrometheusRegistry with PrometheusHistogram, CollectorRegistry] = for { - h <- registry.registerHistogram("simple_histogram_thelper", Array("method"), LinearBuckets(1, 2, 5)) - _ <- histogram.time(h, () => Thread.sleep(2000), Array("post")) - r <- registry.getCurrent() + val testHistogramTimerHelper: RIO[PrometheusRegistry, CollectorRegistry] = for { + h <- Histogram("simple_histogram_time_custom", Array("method"), LinearBuckets(1, 2, 5)) + _ <- h.time(() => Thread.sleep(2000), Array("post")) + r <- registry.getCurrent() } yield r ``` @@ -292,8 +287,8 @@ You can, of course, verify the usual way: setHT.add("simple_histogram_timer_count") setHT.add("simple_histogram_timer_sum") - val rht = rt.unsafeRun(testHistogramTimer) - val count = rht.filteredMetricFamilySamples(setHT).nextElement().samples.get(0).value + val rht = rt.unsafeRun(testHistogramTimer) + val cnt = rht.filteredMetricFamilySamples(setHT).nextElement().samples.get(0).value val sum = rht.filteredMetricFamilySamples(setHT).nextElement().samples.get(1).value ``` @@ -305,27 +300,25 @@ or simpler using our `exporters` helper: If, instead, we want to measure arbitrary values: ```scala mdoc:silent - val testHistogram: RIO[PrometheusRegistry with PrometheusHistogram, CollectorRegistry] = for { - h <- registry.registerHistogram("simple_histogram", Array("method")) - _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(histogram.observe(h, _, Array("get"))) - r <- registry.getCurrent() + val testHistogram: RIO[PrometheusRegistry, CollectorRegistry] = for { + h <- histogram.register("simple_histogram", Array("method")) + _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(h.observe(_, Array("get"))) + r <- registry.getCurrent() } yield r - ``` `RIO.foreach` will take each value of the list `List(10.5, 25.0, 50.7, 57.3, -19.8)` and apply the function `histogram.observe(h, _, Array("get"))` to each -value in a synchronous manner, where `h` is the histogram we registered as -`simple_histogram` with a `method` label, `_` refers to the value (10.5, 25.0, -etc.) and `Array("get")` is the specif label for the current observation. +19.8)` and apply the function `h.observe(_, Array("get"))` to each +value in a synchronous manner, where `_` refers to the value (10.5, 25.0, +etc.) and `Array("get")` is the specic label for the current observation. We can override the `DefaultBuckets` so: ```scala mdoc:silent - val testHistogramBuckets: RIO[PrometheusRegistry with PrometheusHistogram, CollectorRegistry] = for { - h <- registry.registerHistogram("simple_histogram", Array("method"), DefaultBuckets(Seq(10,20,30,40,50))) - _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(histogram.observe(h, _, Array("get"))) - r <- registry.getCurrent() + val testHistogramBuckets: RIO[PrometheusRegistry, CollectorRegistry] = for { + h <- histogram.register("simple_histogram", Array("method"), DefaultBuckets(Seq(10, 20, 30, 40, 50))) + _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(h.observe(_, Array("get"))) + r <- registry.getCurrent() } yield r ``` @@ -336,27 +329,28 @@ mark every point we want observed (measure) thus giving us the duration between when `startTimer` was called and each time we `observeDuration`. ```scala mdoc:silent - val f = (n: Long) => { + val f = (n: Long) => { RIO.sleep(Duration.fromScala(n.millis)) *> putStrLn(s"n = $n") } - val testHistogramDuration: RIO[PrometheusRegistry with PrometheusHistogram - with Console with Clock, CollectorRegistry] = for { - h <- registry.registerHistogram("duration_histogram", Array("method")) - t <- histogram.startTimer(h, Array("time")) - dl <- RIO.foreach(List(75L, 150L, 200L))(n => for { - _ <- f(n) - d <- histogram.observeDuration(t) - } yield d - ) - _ <- RIO.foreach(dl)(d => putStrLn(d.toString())) - r <- registry.getCurrent() + val testHistogramDuration: RIO[PrometheusRegistry with Console with Clock, CollectorRegistry] = for { + h <- Histogram("duration_histogram", Array("method"), ExponentialBuckets(0.25, 2, 5)) + t <- h.startTimer(Array("time")) + dl <- RIO.foreach(List(75L, 750L, 2000L))( + n => + for { + _ <- f(n) + d <- h.observeDuration(t) + } yield d + ) + _ <- RIO.foreach(dl)(d => putStrLn(d.toString())) + r <- registry.getCurrent() } yield r ``` We could define `ExponentialBuckets` substituting the following line: -`h <- registry.registerHistogram("duration_histogram", Array("method"), ExponentialBuckets(0.25,2,5))` +`h <- histogram.register("duration_histogram", Array("method"), ExponentialBuckets(0.25,2,5))` Now lets inspect our values by `tap`ping our `RIO`. Add ` with Clock.Live` to the runtime `rt` before executing the following code. @@ -387,11 +381,10 @@ Percentile](https://prometheus.io/docs/practices/histograms/#quantiles) documentation for more information. ```scala mdoc:silent - val testSummary: RIO[PrometheusRegistry with PrometheusSummary, CollectorRegistry] = for { - pr <- RIO.environment[PrometheusRegistry] - s <- pr.registry.registerSummary(PLabel("simple_summary", Array("method")), List((0.5, 0.05), (0.9, 0.01))) - _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(summary.observe(s, _, Array("put"))) - r <- pr.registry.getCurrent() + val testSummary: RIO[PrometheusRegistry, CollectorRegistry] = for { + s <- Summary("simple_summary", Array("method"), List((0.5, 0.05), (0.9, 0.01))) + _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(s.observe(_, Array("put"))) + r <- registry.getCurrent() } yield r ``` diff --git a/prometheus/src/main/scala/zio/metrics/Counter.scala b/prometheus/src/main/scala/zio/metrics/Counter.scala deleted file mode 100644 index e51cc11a..00000000 --- a/prometheus/src/main/scala/zio/metrics/Counter.scala +++ /dev/null @@ -1,15 +0,0 @@ -package zio.metrics - -import zio.Task - -trait Counter { - val counter: Counter.Service[Nothing] -} - -object Counter { - trait Service[-C] { - def inc(counter: C, labelNames: Array[String]): Task[Unit] - - def inc(counter: C, amount: Double, labelNames: Array[String]): Task[Unit] - } -} diff --git a/prometheus/src/main/scala/zio/metrics/Gauge.scala b/prometheus/src/main/scala/zio/metrics/Gauge.scala deleted file mode 100644 index 442cd1fa..00000000 --- a/prometheus/src/main/scala/zio/metrics/Gauge.scala +++ /dev/null @@ -1,28 +0,0 @@ -package zio.metrics - -import zio.Task - -trait Gauge { - val gauge: Gauge.Service[_] -} - -object Gauge { - trait Service[G] { - - def getValue(g: G, labelNames: Array[String]): Task[Double] - - def inc(g: G, labelNames: Array[String]): Task[Unit] - - def inc(g: G, amount: Double, labelNames: Array[String]): Task[Unit] - - def dec(g: G, labelNames: Array[String]): Task[Unit] - - def dec(g: G, amount: Double, labelNames: Array[String]): Task[Unit] - - def set(g: G, amount: Double, labelNames: Array[String]): Task[Unit] - - def setToCurrentTime(g: G, labelNames: Array[String]): Task[Unit] - - def setToTime(g: G, f: () => Unit, labelNames: Array[String]): Task[Unit] - } -} diff --git a/prometheus/src/main/scala/zio/metrics/Histogram.scala b/prometheus/src/main/scala/zio/metrics/Histogram.scala deleted file mode 100644 index 59f2102e..00000000 --- a/prometheus/src/main/scala/zio/metrics/Histogram.scala +++ /dev/null @@ -1,19 +0,0 @@ -package zio.metrics - -import zio.Task - -trait Histogram { - val histogram: Histogram.Service[Nothing, _] -} - -object Histogram { - trait Service[-R, T] { - def observe(h: R, amount: Double, labelNames: Array[String]): Task[Unit] - - def startTimer(h: R, labelNames: Array[String]): Task[T] - - def observeDuration(timer: T): Task[Double] - - def time(h: R, f: () => Unit, labelNames: Array[String]): Task[Double] - } -} diff --git a/prometheus/src/main/scala/zio/metrics/Summary.scala b/prometheus/src/main/scala/zio/metrics/Summary.scala deleted file mode 100644 index ad5efeac..00000000 --- a/prometheus/src/main/scala/zio/metrics/Summary.scala +++ /dev/null @@ -1,19 +0,0 @@ -package zio.metrics - -import zio.Task - -trait Summary { - val summary: Summary.Service[Nothing, _] -} - -object Summary { - trait Service[-R, T] { - def observe(s: R, amount: Double, labelNames: Array[String]): Task[Unit] - - def startTimer(s: R, labelNames: Array[String]): Task[T] - - def observeDuration(timer: T): Task[Double] - - def time(s: R, f: () => Unit, labelNames: Array[String]): Task[Double] - } -} diff --git a/prometheus/src/main/scala/zio/metrics/prometheus/Helpers.scala b/prometheus/src/main/scala/zio/metrics/prometheus/Helpers.scala index ec893359..d98d3a0e 100644 --- a/prometheus/src/main/scala/zio/metrics/prometheus/Helpers.scala +++ b/prometheus/src/main/scala/zio/metrics/prometheus/Helpers.scala @@ -1,4 +1,4 @@ -package zio.metrics.prometheus +package zio.metrics.prometheus.helpers import zio.RIO @@ -8,6 +8,7 @@ import io.prometheus.client.CollectorRegistry import io.prometheus.client.exporter.HTTPServer import io.prometheus.client.exporter.HttpConnectionFactory import zio.metrics.{ Buckets, DefaultBuckets, Label } +import zio.metrics.prometheus._ import zio.metrics.prometheus.PrometheusRegistry.{ Percentile, Tolerance } object registry { @@ -96,112 +97,47 @@ object registry { } object counter { - def inc(pCounter: PCounter): RIO[PrometheusCounter, Unit] = RIO.accessM(_.counter.inc(pCounter, Array.empty[String])) + def register(name: String) = + Counter(name, Array.empty[String]) - def inc(pCounter: PCounter, amount: Double): RIO[PrometheusCounter, Unit] = - RIO.accessM(_.counter.inc(pCounter, amount, Array.empty[String])) - - def inc(pCounter: PCounter, labelNames: Array[String]): RIO[PrometheusCounter, Unit] = - RIO.accessM(_.counter.inc(pCounter, labelNames)) - - def inc(pCounter: PCounter, amount: Double, labelNames: Array[String]): RIO[PrometheusCounter, Unit] = - RIO.accessM(_.counter.inc(pCounter, amount, labelNames)) + def register(name: String, labels: Array[String]) = + Counter(name, labels) } object gauge { - def getValue(g: PGauge): RIO[PrometheusGauge, Double] = - RIO.accessM(_.gauge.getValue(g, Array.empty[String])) - - def inc(g: PGauge): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.inc(g, Array.empty[String])) - - def dec(g: PGauge): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.dec(g, Array.empty[String])) - - def inc(g: PGauge, amount: Double): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.inc(g, amount, Array.empty[String])) - - def dec(g: PGauge, amount: Double): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.inc(g, amount, Array.empty[String])) - - def set(g: PGauge, amount: Double): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.inc(g, amount, Array.empty[String])) - - def setToCurrentTime(g: PGauge): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.setToCurrentTime(g, Array.empty[String])) - - def setToTime(g: PGauge, f: () => Unit): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.setToTime(g, f, Array.empty[String])) - - def getValue(g: PGauge, labelNames: Array[String]): RIO[PrometheusGauge, Double] = - RIO.accessM(_.gauge.getValue(g, labelNames)) - - def inc(g: PGauge, labelNames: Array[String]): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.inc(g, labelNames)) + def register(name: String) = + Gauge(name, Array.empty[String]) - def dec(g: PGauge, labelNames: Array[String]): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.dec(g, labelNames)) - - def inc(g: PGauge, amount: Double, labelNames: Array[String]): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.inc(g, amount, labelNames)) - - def dec(g: PGauge, amount: Double, labelNames: Array[String]): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.inc(g, amount, labelNames)) - - def set(g: PGauge, amount: Double, labelNames: Array[String]): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.inc(g, amount, labelNames)) - - def setToCurrentTime(g: PGauge, labelNames: Array[String]): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.setToCurrentTime(g, labelNames)) - - def setToTime(g: PGauge, labelNames: Array[String]): RIO[PrometheusGauge, Unit] = - RIO.accessM(_.gauge.setToTime(g, () => Thread.sleep(1000), labelNames)) + def register(name: String, labels: Array[String]) = + Gauge(name, labels) } object histogram { - def observe(h: PHistogram, amount: Double): RIO[PrometheusHistogram, Unit] = - RIO.accessM(_.histogram.observe(h, amount, Array.empty[String])) - - def startTimer(h: PHistogram): RIO[PrometheusHistogram, PHistogram.Timer] = - RIO.accessM(_.histogram.startTimer(h, Array.empty[String])) + def register(name: String) = + Histogram(name, Array.empty[String], DefaultBuckets(Seq.empty[Double])) - def observeDuration(timer: PHistogram.Timer): RIO[PrometheusHistogram, Double] = - RIO.accessM(_.histogram.observeDuration(timer)) + def register(name: String, labels: Array[String]) = + Histogram(name, labels, DefaultBuckets(Seq.empty[Double])) - def time(h: PHistogram, f: () => Unit): RIO[PrometheusHistogram, Double] = - RIO.accessM(_.histogram.time(h, f, Array.empty[String])) + def register(name: String, buckets: Buckets) = + Histogram(name, Array.empty[String], buckets) - def observe(h: PHistogram, amount: Double, labelNames: Array[String]): RIO[PrometheusHistogram, Unit] = - RIO.accessM(_.histogram.observe(h, amount, labelNames)) - - def startTimer(h: PHistogram, labelNames: Array[String]): RIO[PrometheusHistogram, PHistogram.Timer] = - RIO.accessM(_.histogram.startTimer(h, labelNames)) - - def time(h: PHistogram, f: () => Unit, labelNames: Array[String]): RIO[PrometheusHistogram, Double] = - RIO.accessM(_.histogram.time(h, f, labelNames)) + def register(name: String, labels: Array[String], buckets: Buckets) = + Histogram(name, labels, buckets) } object summary { - def observe(s: PSummary, amount: Double): RIO[PrometheusSummary, Unit] = - RIO.accessM(_.summary.observe(s, amount, Array.empty[String])) - - def startTimer(s: PSummary): RIO[PrometheusSummary, PSummary.Timer] = - RIO.accessM(_.summary.startTimer(s, Array.empty[String])) - - def observeDuration(timer: PSummary.Timer): RIO[PrometheusSummary, Double] = - RIO.accessM(_.summary.observeDuration(timer)) - - def time(s: PSummary, f: () => Unit): RIO[PrometheusSummary, Double] = - RIO.accessM(_.summary.time(s, f, Array.empty[String])) + def register(name: String) = + Summary(name, Array.empty[String], List.empty[(Double, Double)]) - def observe(s: PSummary, amount: Double, labelNames: Array[String]): RIO[PrometheusSummary, Unit] = - RIO.accessM(_.summary.observe(s, amount, labelNames)) + def register(name: String, labels: Array[String]) = + Summary(name, labels, List.empty[(Percentile, Tolerance)]) - def startTimer(s: PSummary, labelNames: Array[String]): RIO[PrometheusSummary, PSummary.Timer] = - RIO.accessM(_.summary.startTimer(s, labelNames)) + def register(name: String, percentiles: List[(Percentile, Tolerance)]) = + Summary(name, Array.empty[String], percentiles) - def time(s: PSummary, f: () => Unit, labelNames: Array[String]): RIO[PrometheusSummary, Double] = - RIO.accessM(_.summary.time(s, f, labelNames)) + def register(name: String, labels: Array[String], percentiles: List[(Percentile, Tolerance)]) = + Summary(name, labels, percentiles) } object exporters { diff --git a/prometheus/src/main/scala/zio/metrics/prometheus/Metrics.scala b/prometheus/src/main/scala/zio/metrics/prometheus/Metrics.scala new file mode 100644 index 00000000..c4219633 --- /dev/null +++ b/prometheus/src/main/scala/zio/metrics/prometheus/Metrics.scala @@ -0,0 +1,163 @@ +package zio.metrics.prometheus + +import zio.{ RIO, Task } +import zio.metrics.prometheus.PrometheusRegistry.{ Percentile, Tolerance } +import io.prometheus.client.{ Counter => PCounter, Gauge => PGauge } +import io.prometheus.client.{ Histogram => PHistogram, Summary => PSummary } +import zio.metrics.Buckets +import zio.metrics.prometheus.helpers.registry + +sealed trait Metric {} + +class Counter(private val pCounter: PCounter) extends Metric { + def inc(): Task[Unit] = inc(Array.empty[String]) + + def inc(amount: Double): Task[Unit] = inc(amount, Array.empty[String]) + + def inc(labelNames: Array[String]): Task[Unit] = + Task(if (labelNames.isEmpty) pCounter.inc() else pCounter.labels(labelNames: _*).inc()) + + def inc(amount: Double, labelNames: Array[String]): Task[Unit] = + Task(if (labelNames.isEmpty) pCounter.inc(amount) else pCounter.labels(labelNames: _*).inc(amount)) +} + +object Counter { + def apply(name: String, labels: Array[String]): RIO[PrometheusRegistry, Counter] = + for { + c <- registry.registerCounter(name, labels) + } yield new Counter(c) +} + +class Gauge(private val pGauge: PGauge) extends Metric { + def getValue(): Task[Double] = + getValue(Array.empty[String]) + + def getValue(labelNames: Array[String]): Task[Double] = + Task(if (labelNames.isEmpty) pGauge.get() else pGauge.labels(labelNames: _*).get()) + + def inc(): Task[Unit] = + inc(Array.empty[String]) + + def inc(labelNames: Array[String]): Task[Unit] = + Task { + if (labelNames.isEmpty) pGauge.inc() + else pGauge.labels(labelNames: _*).inc() + } + + def dec(): Task[Unit] = + dec(Array.empty[String]) + + def dec(labelNames: Array[String]): Task[Unit] = + Task(if (labelNames.isEmpty) pGauge.dec() else pGauge.labels(labelNames: _*).dec()) + + def inc(amount: Double): Task[Unit] = + inc(amount, Array.empty[String]) + + def inc(amount: Double, labelNames: Array[String]): Task[Unit] = + Task(if (labelNames.isEmpty) pGauge.inc(amount) else pGauge.labels(labelNames: _*).inc(amount)) + + def dec(amount: Double): Task[Unit] = + dec(amount, Array.empty[String]) + + def dec(amount: Double, labelNames: Array[String]): Task[Unit] = + Task(if (labelNames.isEmpty) pGauge.dec(amount) else pGauge.labels(labelNames: _*).dec(amount)) + + def set(amount: Double): Task[Unit] = + set(amount, Array.empty[String]) + + def set(amount: Double, labelNames: Array[String]): Task[Unit] = + Task(if (labelNames.isEmpty) pGauge.set(amount) else pGauge.labels(labelNames: _*).set(amount)) + + def setToCurrentTime(): Task[Unit] = + setToCurrentTime(Array.empty[String]) + + def setToCurrentTime(labelNames: Array[String]): Task[Unit] = + Task(if (labelNames.isEmpty) pGauge.setToCurrentTime() else pGauge.labels(labelNames: _*).setToCurrentTime()) + + def setToTime(f: () => Unit): Task[Unit] = + setToTime(f) + + def setToTime(f: () => Unit, labelNames: Array[String]): Task[Unit] = + Task { + val t = if (labelNames.isEmpty) pGauge.startTimer() else pGauge.labels(labelNames: _*).startTimer() + f() + pGauge.set(t.setDuration) + } +} + +object Gauge { + def apply(name: String, labels: Array[String]): RIO[PrometheusRegistry, Gauge] = + for { + g <- registry.registerGauge(name, labels) + } yield new Gauge(g) +} + +class Histogram(private val pHistogram: PHistogram) extends Metric { + type HistogramTimer = PHistogram.Timer + + def observe(amount: Double): Task[Unit] = + observe(amount, Array.empty[String]) + + def observe(amount: Double, labelNames: Array[String]): Task[Unit] = + Task(if (labelNames.isEmpty) pHistogram.observe(amount) else pHistogram.labels(labelNames: _*).observe(amount)) + + def startTimer(): Task[HistogramTimer] = + startTimer(Array.empty[String]) + + def startTimer(labelNames: Array[String]): Task[HistogramTimer] = + Task(if (labelNames.isEmpty) pHistogram.startTimer() else pHistogram.labels(labelNames: _*).startTimer()) + + def observeDuration(timer: HistogramTimer): Task[Double] = + Task(timer.observeDuration()) + + def time(f: () => Unit): Task[Double] = + time(f, Array.empty[String]) + + def time(f: () => Unit, labelNames: Array[String]): Task[Double] = + Task { + val t = if (labelNames.isEmpty) pHistogram.startTimer() else pHistogram.labels(labelNames: _*).startTimer() + f() + t.observeDuration() + } +} + +object Histogram { + def apply(name: String, labels: Array[String], buckets: Buckets): RIO[PrometheusRegistry, Histogram] = + for { + h <- registry.registerHistogram(name, labels, buckets) + } yield new Histogram(h) +} + +class Summary(private val pSummary: PSummary) extends Metric { + type SummaryTimer = PSummary.Timer + + def observe(amount: Double): Task[Unit] = + observe(amount, Array.empty[String]) + + def observe(amount: Double, labelNames: Array[String]): Task[Unit] = + Task(if (labelNames.isEmpty) pSummary.observe(amount) else pSummary.labels(labelNames: _*).observe(amount)) + + def startTimer(labelNames: Array[String]): Task[SummaryTimer] = + Task(if (labelNames.isEmpty) pSummary.startTimer() else pSummary.labels(labelNames: _*).startTimer) + + def observeDuration(timer: SummaryTimer): Task[Double] = + Task(timer.observeDuration()) + + def time(f: () => Unit, labelNames: Array[String]): Task[Double] = + Task { + val t = if (labelNames.isEmpty) pSummary.startTimer() else pSummary.labels(labelNames: _*).startTimer() + f() + t.observeDuration() + } +} + +object Summary { + def apply( + name: String, + labels: Array[String], + percentiles: List[(Percentile, Tolerance)] + ): RIO[PrometheusRegistry, Summary] = + for { + s <- registry.registerSummary(name, labels, percentiles) + } yield new Summary(s) +} diff --git a/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusCounter.scala b/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusCounter.scala deleted file mode 100644 index 1de58a41..00000000 --- a/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusCounter.scala +++ /dev/null @@ -1,18 +0,0 @@ -package zio.metrics.prometheus - -import zio.Task -import zio.metrics.Counter -import io.prometheus.client.{ Counter => PCounter } - -trait PrometheusCounter extends Counter { - - val counter = new Counter.Service[PCounter] { - override def inc(pCounter: PCounter, labelNames: Array[String]): Task[Unit] = - Task(if (labelNames.isEmpty) pCounter.inc() else pCounter.labels(labelNames: _*).inc()) - - override def inc(pCounter: PCounter, amount: Double, labelNames: Array[String]): Task[Unit] = - Task(if (labelNames.isEmpty) pCounter.inc(amount) else pCounter.labels(labelNames: _*).inc(amount)) - } -} - -object PrometheusCounter extends PrometheusCounter diff --git a/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusGauge.scala b/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusGauge.scala deleted file mode 100644 index 241b9304..00000000 --- a/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusGauge.scala +++ /dev/null @@ -1,42 +0,0 @@ -package zio.metrics.prometheus - -import zio.Task -import zio.metrics.Gauge -import io.prometheus.client.{ Gauge => PGauge } - -trait PrometheusGauge extends Gauge { - val gauge = new Gauge.Service[PGauge] { - override def getValue(g: PGauge, labelNames: Array[String]): Task[Double] = - Task(if (labelNames.isEmpty) g.get() else g.labels(labelNames: _*).get()) - - override def inc(g: PGauge, labelNames: Array[String]): Task[Unit] = - Task { - if (labelNames.isEmpty) g.inc() - else g.labels(labelNames: _*).inc() - } - - override def dec(g: PGauge, labelNames: Array[String]): Task[Unit] = - Task(if (labelNames.isEmpty) g.dec() else g.labels(labelNames: _*).dec()) - - override def inc(g: PGauge, amount: Double, labelNames: Array[String]): Task[Unit] = - Task(if (labelNames.isEmpty) g.inc(amount) else g.labels(labelNames: _*).inc(amount)) - - override def dec(g: PGauge, amount: Double, labelNames: Array[String]): Task[Unit] = - Task(if (labelNames.isEmpty) g.dec(amount) else g.labels(labelNames: _*).dec(amount)) - - override def set(g: PGauge, amount: Double, labelNames: Array[String]): Task[Unit] = - Task(if (labelNames.isEmpty) g.set(amount) else g.labels(labelNames: _*).set(amount)) - - override def setToCurrentTime(g: PGauge, labelNames: Array[String]): Task[Unit] = - Task(if (labelNames.isEmpty) g.setToCurrentTime() else g.labels(labelNames: _*).setToCurrentTime()) - - override def setToTime(g: PGauge, f: () => Unit, labelNames: Array[String]): Task[Unit] = - Task { - val t = if (labelNames.isEmpty) g.startTimer() else g.labels(labelNames: _*).startTimer() - f() - g.set(t.setDuration) - } - } -} - -object PrometheusGauge extends PrometheusGauge diff --git a/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusHistogram.scala b/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusHistogram.scala deleted file mode 100644 index 9139dbcb..00000000 --- a/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusHistogram.scala +++ /dev/null @@ -1,30 +0,0 @@ -package zio.metrics.prometheus - -import zio.metrics.Histogram -import zio.Task -import io.prometheus.client.{ Histogram => PHistogram } - -trait PrometheusHistogram extends Histogram { - - type HistogramTimer = PHistogram.Timer - - val histogram = new Histogram.Service[PHistogram, HistogramTimer] { - override def observe(h: PHistogram, amount: Double, labelNames: Array[String]): Task[Unit] = - Task(if (labelNames.isEmpty) h.observe(amount) else h.labels(labelNames: _*).observe(amount)) - - override def startTimer(h: PHistogram, labelNames: Array[String]): Task[HistogramTimer] = - Task(if (labelNames.isEmpty) h.startTimer() else h.labels(labelNames: _*).startTimer()) - - override def observeDuration(timer: HistogramTimer): Task[Double] = - Task(timer.observeDuration()) - - override def time(h: PHistogram, f: () => Unit, labelNames: Array[String]): Task[Double] = - Task { - val t = if (labelNames.isEmpty) h.startTimer() else h.labels(labelNames: _*).startTimer() - f() - t.observeDuration() - } - } -} - -object PrometheusHistogram extends PrometheusHistogram diff --git a/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusRegistry.scala b/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusRegistry.scala index d517cba9..c8176137 100644 --- a/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusRegistry.scala +++ b/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusRegistry.scala @@ -4,7 +4,7 @@ import io.prometheus.client.{ Counter => PCounter } import io.prometheus.client.{ Gauge => PGauge } import io.prometheus.client.{ Histogram => PHistogram } import io.prometheus.client.{ Collector, CollectorRegistry } -import io.prometheus.client.Summary +import io.prometheus.client.{ Summary => PSummary } import zio.metrics._ import zio.metrics.{ Label, Registry, Show } @@ -12,7 +12,7 @@ import zio.{ Ref, Task, UIO } trait PrometheusRegistry extends Registry { - type PTimer = Summary.Timer + type PTimer = PSummary.Timer type Percentile = Double type Tolerance = Double @@ -62,10 +62,10 @@ trait PrometheusRegistry extends Registry { (h.register(r), r) })) - override def registerSummary[L: Show](label: Label[L], quantiles: List[(Percentile, Tolerance)]): Task[Summary] = + override def registerSummary[L: Show](label: Label[L], quantiles: List[(Percentile, Tolerance)]): Task[PSummary] = registryRef >>= (_.modify(r => { val name = Show[L].show(label.name) - val sb = Summary + val sb = PSummary .build() .name(name) .labelNames(label.labels: _*) diff --git a/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusSummary.scala b/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusSummary.scala deleted file mode 100644 index d91dd4e7..00000000 --- a/prometheus/src/main/scala/zio/metrics/prometheus/PrometheusSummary.scala +++ /dev/null @@ -1,30 +0,0 @@ -package zio.metrics.prometheus - -import zio.metrics.Summary -import zio.Task -import io.prometheus.client.{ Summary => PSummary } - -trait PrometheusSummary extends Summary { - - type SummaryTimer = PSummary.Timer - - val summary = new Summary.Service[PSummary, SummaryTimer] { - override def observe(s: PSummary, amount: Double, labelNames: Array[String]): Task[Unit] = - Task(if (labelNames.isEmpty) s.observe(amount) else s.labels(labelNames: _*).observe(amount)) - - override def startTimer(s: PSummary, labelNames: Array[String]): Task[SummaryTimer] = - Task(if (labelNames.isEmpty) s.startTimer() else s.labels(labelNames: _*).startTimer) - - override def observeDuration(timer: SummaryTimer): Task[Double] = - Task(timer.observeDuration()) - - override def time(s: PSummary, f: () => Unit, labelNames: Array[String]): Task[Double] = - Task { - val t = if (labelNames.isEmpty) s.startTimer() else s.labels(labelNames: _*).startTimer() - f() - t.observeDuration() - } - } -} - -object PrometheusSummary extends PrometheusSummary diff --git a/prometheus/src/test/scala/zio/metrics/ExportersTest.scala b/prometheus/src/test/scala/zio/metrics/ExportersTest.scala index 28843255..e4804242 100644 --- a/prometheus/src/test/scala/zio/metrics/ExportersTest.scala +++ b/prometheus/src/test/scala/zio/metrics/ExportersTest.scala @@ -4,29 +4,30 @@ import zio.{ RIO, Runtime } import zio.console.putStrLn import zio.internal.PlatformLive import zio.metrics.prometheus._ +import zio.metrics.prometheus.helpers._ import io.prometheus.client.exporter.HTTPServer import zio.console.Console object ExportersTest { val rt = Runtime( - new PrometheusRegistry with PrometheusCounter with PrometheusHistogram with PrometheusExporters with Console.Live, + new PrometheusRegistry with PrometheusExporters with Console.Live, PlatformLive.Default ) val exporterTest: RIO[ - PrometheusRegistry with PrometheusCounter with PrometheusHistogram with PrometheusExporters with Console, + PrometheusRegistry with PrometheusExporters with Console, HTTPServer ] = for { r <- registry.getCurrent() _ <- exporters.initializeDefaultExports(r) hs <- exporters.http(r, 9090) - c <- registry.registerCounter(ExportersTest.getClass(), Array("exporter")) - _ <- counter.inc(c, Array("counter")) - _ <- counter.inc(c, 2.0, Array("counter")) - h <- registry.registerHistogram("export_histogram", Array("exporter", "method")) - _ <- histogram.time(h, () => Thread.sleep(2000), Array("histogram", "get")) + c <- Counter("ExportersTest", Array("exporter")) + _ <- c.inc(Array("counter")) + _ <- c.inc(2.0, Array("counter")) + h <- histogram.register("export_histogram", Array("exporter", "method")) + _ <- h.time(() => Thread.sleep(2000), Array("histogram", "get")) s <- exporters.write004(r) _ <- putStrLn(s) } yield hs diff --git a/prometheus/src/test/scala/zio/metrics/PrometheusLabelsTest.scala b/prometheus/src/test/scala/zio/metrics/PrometheusLabelsTest.scala index 6c9a35fe..03f43c90 100644 --- a/prometheus/src/test/scala/zio/metrics/PrometheusLabelsTest.scala +++ b/prometheus/src/test/scala/zio/metrics/PrometheusLabelsTest.scala @@ -7,6 +7,7 @@ import testz.{ assert, Harness, PureHarness, Result } import io.prometheus.client.{ CollectorRegistry } import zio.internal.PlatformLive import zio.metrics.prometheus._ +import zio.metrics.prometheus.helpers._ import zio.console.putStrLn import zio.console.Console import zio.duration.Duration @@ -16,45 +17,35 @@ import zio.clock.Clock object PrometheusLabelsTest { val rt = Runtime( - new PrometheusRegistry with PrometheusCounter with PrometheusGauge with PrometheusHistogram with PrometheusSummary - with PrometheusExporters with Console.Live with Clock.Live, + new PrometheusRegistry with PrometheusExporters with Console.Live with Clock.Live, PlatformLive.Default ) - val testCounter: RIO[PrometheusRegistry with PrometheusCounter, CollectorRegistry] = for { - pr <- RIO.environment[PrometheusRegistry] - c <- pr.registry.registerCounter(Label("simple_counter", Array("method", "resource"))) - pc <- RIO.environment[PrometheusCounter] - _ <- pc.counter.inc(c, Array("get", "users")) - _ <- pc.counter.inc(c, 2.0, Array("get", "users")) - r <- pr.registry.getCurrent() - } yield r - - val testCounterHelper: RIO[PrometheusRegistry with PrometheusCounter, CollectorRegistry] = for { - c <- registry.registerCounter("PrometheusTestHelper", Array("method", "resource")) - _ <- counter.inc(c, Array("get", "users")) - _ <- counter.inc(c, 2.0, Array("get", "users")) + val testCounter: RIO[PrometheusRegistry, CollectorRegistry] = for { + c <- Counter("simple_counter", Array("method", "resource")) + _ <- c.inc(Array("get", "users")) + _ <- c.inc(2.0, Array("get", "users")) r <- registry.getCurrent() } yield r - val testGauge: RIO[PrometheusRegistry with PrometheusGauge, (CollectorRegistry, Double)] = for { - pr <- RIO.environment[PrometheusRegistry] - r <- pr.registry.getCurrent() - g <- pr.registry.registerGauge(Label("simple_gauge", Array("method"))) - _ <- gauge.inc(g, Array("get")) - _ <- gauge.inc(g, 2.0, Array("get")) - d <- gauge.getValue(g, Array("get")) + val testGauge: RIO[PrometheusRegistry, (CollectorRegistry, Double)] = for { + g <- Gauge("simple_gauge", Array("method")) + _ <- g.inc(Array("get")) + _ <- g.inc(2.0, Array("get")) + _ <- g.dec(1.0, Array("get")) + d <- g.getValue(Array("get")) + r <- registry.getCurrent() } yield (r, d) - val testHistogram: RIO[PrometheusRegistry with PrometheusHistogram, CollectorRegistry] = for { - h <- registry.registerHistogram("simple_histogram", Array("method"), DefaultBuckets(Seq(10, 20, 30, 40, 50))) - _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(histogram.observe(h, _, Array("get"))) + val testHistogram: RIO[PrometheusRegistry, CollectorRegistry] = for { + h <- Histogram("simple_histogram", Array("method"), DefaultBuckets(Seq(10, 20, 30, 40, 50))) + _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(h.observe(_, Array("get"))) r <- registry.getCurrent() } yield r - val testHistogramTimer: RIO[PrometheusRegistry with PrometheusHistogram, CollectorRegistry] = for { - h <- registry.registerHistogram("simple_histogram_timer", Array("method"), LinearBuckets(1, 2, 5)) - _ <- histogram.time(h, () => Thread.sleep(2000), Array("post")) + val testHistogramTimer: RIO[PrometheusRegistry, CollectorRegistry] = for { + h <- Histogram("simple_histogram_timer", Array("method"), LinearBuckets(1, 2, 5)) + _ <- h.time(() => Thread.sleep(2000), Array("post")) r <- registry.getCurrent() } yield r @@ -62,26 +53,24 @@ object PrometheusLabelsTest { RIO.sleep(Duration.fromScala(n.millis)) *> putStrLn(s"n = $n") } - val testHistogramDuration - : RIO[PrometheusRegistry with PrometheusHistogram with Console with Clock, CollectorRegistry] = for { - h <- registry.registerHistogram("duration_histogram", Array("method"), ExponentialBuckets(0.25, 2, 5)) - t <- histogram.startTimer(h, Array("time")) + val testHistogramDuration: RIO[PrometheusRegistry with Console with Clock, CollectorRegistry] = for { + h <- Histogram("duration_histogram", Array("method"), ExponentialBuckets(0.25, 2, 5)) + t <- h.startTimer(Array("time")) dl <- RIO.foreach(List(75L, 750L, 2000L))( n => for { _ <- f(n) - d <- histogram.observeDuration(t) + d <- h.observeDuration(t) } yield d ) _ <- RIO.foreach(dl)(d => putStrLn(d.toString())) r <- registry.getCurrent() } yield r - val testSummary: RIO[PrometheusRegistry with PrometheusSummary, CollectorRegistry] = for { - pr <- RIO.environment[PrometheusRegistry] - s <- pr.registry.registerSummary(Label("simple_summary", Array("method")), List((0.5, 0.05), (0.9, 0.01))) - _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(summary.observe(s, _, Array("put"))) - r <- pr.registry.getCurrent() + val testSummary: RIO[PrometheusRegistry, CollectorRegistry] = for { + s <- Summary("simple_summary", Array("method"), List((0.5, 0.05), (0.9, 0.01))) + _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(s.observe(_, Array("put"))) + r <- registry.getCurrent() } yield r def tests[T](harness: Harness[T]): T = { @@ -99,18 +88,6 @@ object PrometheusLabelsTest { .value assert(counter == 3.0) }, - test("counter increases by `inc` amount on helper method") { () => - val set: util.Set[String] = new util.HashSet[String]() - set.add("simple_counter") - val r = rt.unsafeRun(testCounterHelper) - val counter = r - .filteredMetricFamilySamples(set) - .nextElement() - .samples - .get(0) - .value - assert(counter == 3.0) - }, test("gauge returns latest value") { () => val set: util.Set[String] = new util.HashSet[String]() set.add("simple_gauge") @@ -123,7 +100,7 @@ object PrometheusLabelsTest { .value assert(a1 == r._2) - assert(a1 == 3.0) + assert(a1 == 2.0) }, test("histogram count and sum are as expected") { () => val set: util.Set[String] = new util.HashSet[String]() diff --git a/prometheus/src/test/scala/zio/metrics/PrometheusTest.scala b/prometheus/src/test/scala/zio/metrics/PrometheusTest.scala index 8ff1a953..12b95413 100644 --- a/prometheus/src/test/scala/zio/metrics/PrometheusTest.scala +++ b/prometheus/src/test/scala/zio/metrics/PrometheusTest.scala @@ -8,57 +8,55 @@ import testz.{ assert, Harness, PureHarness, Result } import io.prometheus.client.CollectorRegistry import zio.internal.PlatformLive import zio.metrics.prometheus._ +import zio.metrics.prometheus.helpers._ object PrometheusTest { val rt = Runtime( - new PrometheusRegistry with PrometheusCounter with PrometheusGauge with PrometheusHistogram with PrometheusSummary - with PrometheusExporters with Console.Live, + new PrometheusRegistry with PrometheusExporters with Console.Live, PlatformLive.Default ) val tester = () => System.nanoTime() - val testCounter: RIO[PrometheusRegistry with PrometheusCounter, CollectorRegistry] = for { - pr <- RIO.environment[PrometheusRegistry] - c <- pr.registry.registerCounter(Label(PrometheusTest.getClass(), Array.empty[String])) - pc <- RIO.environment[PrometheusCounter] - _ <- pc.counter.inc(c, Array.empty[String]) - _ <- pc.counter.inc(c, 2.0, Array.empty[String]) - r <- pr.registry.getCurrent() + val testCounter: RIO[PrometheusRegistry, CollectorRegistry] = for { + c <- Counter("PrometheusTest", Array.empty[String]) + _ <- c.inc() + _ <- c.inc(2.0) + r <- registry.getCurrent() } yield r - val testCounterHelper: RIO[PrometheusRegistry with PrometheusCounter, CollectorRegistry] = for { - c <- registry.registerCounter("PrometheusTestHelper") - _ <- counter.inc(c) - _ <- counter.inc(c, 2.0) + val testCounterHelper: RIO[PrometheusRegistry, CollectorRegistry] = for { + c <- counter.register("PrometheusTestHelper") + _ <- c.inc() + _ <- c.inc(2.0) r <- registry.getCurrent() } yield r - val testGauge: RIO[PrometheusRegistry with PrometheusGauge, (CollectorRegistry, Double)] = for { - pr <- RIO.environment[PrometheusRegistry] - r <- pr.registry.getCurrent() - g <- pr.registry.registerGauge(Label("simple_gauge", Array.empty[String])) - _ <- gauge.inc(g) - _ <- gauge.inc(g, 2.0) - d <- gauge.getValue(g) + val testGauge: RIO[PrometheusRegistry, (CollectorRegistry, Double)] = for { + g <- gauge.register("simple_gauge") + _ <- g.inc() + _ <- g.inc(2.0) + _ <- g.dec(1.0) + d <- g.getValue() + r <- registry.getCurrent() } yield (r, d) - val testHistogram: RIO[PrometheusRegistry with PrometheusHistogram, CollectorRegistry] = for { - h <- registry.registerHistogram("simple_histogram") - _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(histogram.observe(h, _)) + val testHistogram: RIO[PrometheusRegistry, CollectorRegistry] = for { + h <- Histogram("simple_histogram", Array.empty[String], DefaultBuckets(Seq.empty[Double])) + _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(h.observe(_)) r <- registry.getCurrent() } yield r - val testHistogramTimer: RIO[PrometheusRegistry with PrometheusHistogram, CollectorRegistry] = for { - h <- registry.registerHistogram("simple_histogram_timer") - _ <- histogram.time(h, () => Thread.sleep(2000)) + val testHistogramTimer: RIO[PrometheusRegistry, CollectorRegistry] = for { + h <- Histogram("simple_histogram_timer", Array.empty[String], DefaultBuckets(Seq.empty[Double])) + _ <- h.time(() => Thread.sleep(2000)) r <- registry.getCurrent() } yield r - val testSummary: RIO[PrometheusRegistry with PrometheusSummary, CollectorRegistry] = for { - s <- registry.registerSummary("simple_summary") - _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(summary.observe(s, _)) + val testSummary: RIO[PrometheusRegistry, CollectorRegistry] = for { + s <- Summary("simple_summary", Array.empty[String], List.empty[(Double, Double)]) + _ <- RIO.foreach(List(10.5, 25.0, 50.7, 57.3, 19.8))(s.observe(_)) r <- registry.getCurrent() } yield r @@ -67,7 +65,7 @@ object PrometheusTest { section( test("counter increases by `inc` amount") { () => val set: util.Set[String] = new util.HashSet[String]() - set.add(Show.fixClassName(PrometheusTest.getClass())) + set.add("PrometheusTest") val r = rt.unsafeRun(testCounter) val counter = r .filteredMetricFamilySamples(set) @@ -77,9 +75,9 @@ object PrometheusTest { .value assert(counter == 3.0) }, - test("counter increases by `inc` amount on helper method") { () => + test("counter helper increases by `inc` amount") { () => val set: util.Set[String] = new util.HashSet[String]() - set.add(Show.fixClassName(PrometheusTest.getClass())) + set.add("PrometheusTestHelper") val r = rt.unsafeRun(testCounterHelper) val counter = r .filteredMetricFamilySamples(set) @@ -101,7 +99,7 @@ object PrometheusTest { .value assert(a1 == r._2) - assert(a1 == 3.0) + assert(a1 == 2.0) }, test("histogram count and sum are as expected") { () => val set: util.Set[String] = new util.HashSet[String]()