Histogram

Histogram metric, to track distributions of events.

Note: Each bucket is one timeseries. Many buckets and/or many dimensions with labels can produce large amount of time series, that may cause performance problems.

The default buckets are intended to cover a typical web/rpc request from milliseconds to seconds. Defaults are .005, .01, .025, .05, .075, .1, .25, .5, .75, 1, 2.5, 5, 7.5, 10

A Histogram samples observations (usually things like request durations or response sizes) and counts them in configurable buckets. It also provides a sum of all observed values.

A histogram with a base metric name of <basename> exposes multiple time series during a scrape:

Use the histogram_quantile() function to calculate quantiles from histograms or even aggregations of histograms.

See https://prometheus.io/docs/practices/histograms/ for more information on Histogram and Summary similarities and differences.

Imports

import io.chrisdavenport.epimetheus._
import io.chrisdavenport.epimetheus.implicits._
import cats.effect._

import scala.concurrent.duration._

import cats.effect.unsafe.implicits.global

And Example of a Histogram with no labels:

val noLabelsHistogramExample = {
  for {
    pr <- PrometheusRegistry.build[IO]
    h <- Histogram.noLabels(pr, Name("example_histogram"), "Example Histogram")
    _ <- h.observe(0.2)
    _ <- h.timed(Temporal[IO].sleep(1.second), SECONDS)
    currentMetrics <- pr.write004
    _ <- IO(println(currentMetrics))
  } yield ()
}
// noLabelsHistogramExample: IO[Unit] = FlatMap(
//   ioe = Delay(
//     thunk = io.chrisdavenport.epimetheus.PrometheusRegistry$$$Lambda$11197/0x00007fa08dea8210@3d9426bf,
//     event = cats.effect.tracing.TracingEvent$StackTrace
//   ),
//   f = <function1>,
//   event = cats.effect.tracing.TracingEvent$StackTrace
// )

noLabelsHistogramExample.unsafeRunSync()
// # HELP example_histogram Example Histogram
// # TYPE example_histogram histogram
// example_histogram_bucket{le="0.005"} 0
// example_histogram_bucket{le="0.01"} 0
// example_histogram_bucket{le="0.025"} 0
// example_histogram_bucket{le="0.05"} 0
// example_histogram_bucket{le="0.075"} 0
// example_histogram_bucket{le="0.1"} 0
// example_histogram_bucket{le="0.25"} 1
// example_histogram_bucket{le="0.5"} 1
// example_histogram_bucket{le="0.75"} 1
// example_histogram_bucket{le="1.0"} 1
// example_histogram_bucket{le="2.5"} 2
// example_histogram_bucket{le="5.0"} 2
// example_histogram_bucket{le="7.5"} 2
// example_histogram_bucket{le="10.0"} 2
// example_histogram_bucket{le="+Inf"} 2
// example_histogram_count 2
// example_histogram_sum 1.2062474619999999
//

An Example of a Histogram with labels:

val labelledHistogramExample = {
  for {
    pr <- PrometheusRegistry.build[IO]
    h <- Histogram.labelled(
      pr,
      Name("example_histogram"),
      "Example Histogram",
      Sized(Label("foo")),
      {s: String => Sized(s)}
    )
    _ <- h.label("bar").observe(0.2)
    _ <- h.label("baz").timed(Temporal[IO].sleep(1.second), SECONDS)
    currentMetrics <- pr.write004
    _ <- IO(println(currentMetrics))
  } yield ()
}
// labelledHistogramExample: IO[Unit] = FlatMap(
//   ioe = Delay(
//     thunk = io.chrisdavenport.epimetheus.PrometheusRegistry$$$Lambda$11197/0x00007fa08dea8210@8b5561c,
//     event = cats.effect.tracing.TracingEvent$StackTrace
//   ),
//   f = <function1>,
//   event = cats.effect.tracing.TracingEvent$StackTrace
// )

labelledHistogramExample.unsafeRunSync()
// # HELP example_histogram Example Histogram
// # TYPE example_histogram histogram
// example_histogram_bucket{foo="bar",le="0.005"} 0
// example_histogram_bucket{foo="bar",le="0.01"} 0
// example_histogram_bucket{foo="bar",le="0.025"} 0
// example_histogram_bucket{foo="bar",le="0.05"} 0
// example_histogram_bucket{foo="bar",le="0.075"} 0
// example_histogram_bucket{foo="bar",le="0.1"} 0
// example_histogram_bucket{foo="bar",le="0.25"} 1
// example_histogram_bucket{foo="bar",le="0.5"} 1
// example_histogram_bucket{foo="bar",le="0.75"} 1
// example_histogram_bucket{foo="bar",le="1.0"} 1
// example_histogram_bucket{foo="bar",le="2.5"} 1
// example_histogram_bucket{foo="bar",le="5.0"} 1
// example_histogram_bucket{foo="bar",le="7.5"} 1
// example_histogram_bucket{foo="bar",le="10.0"} 1
// example_histogram_bucket{foo="bar",le="+Inf"} 1
// example_histogram_count{foo="bar"} 1
// example_histogram_sum{foo="bar"} 0.2
// example_histogram_bucket{foo="baz",le="0.005"} 0
// example_histogram_bucket{foo="baz",le="0.01"} 0
// example_histogram_bucket{foo="baz",le="0.025"} 0
// example_histogram_bucket{foo="baz",le="0.05"} 0
// example_histogram_bucket{foo="baz",le="0.075"} 0
// example_histogram_bucket{foo="baz",le="0.1"} 0
// example_histogram_bucket{foo="baz",le="0.25"} 0
// example_histogram_bucket{foo="baz",le="0.5"} 0
// example_histogram_bucket{foo="baz",le="0.75"} 0
// example_histogram_bucket{foo="baz",le="1.0"} 0
// example_histogram_bucket{foo="baz",le="2.5"} 1
// example_histogram_bucket{foo="baz",le="5.0"} 1
// example_histogram_bucket{foo="baz",le="7.5"} 1
// example_histogram_bucket{foo="baz",le="10.0"} 1
// example_histogram_bucket{foo="baz",le="+Inf"} 1
// example_histogram_count{foo="baz"} 1
// example_histogram_sum{foo="baz"} 1.000401628
//