Skip to main content

Derived Metric Types

For more detailed information on building metrics see the Metrics DSL section.

Derived metric types are types of metrics that add extra functionality to an underlying primitive metric.

These metrics exist for the following reasons:

  • Separation of concerns between recording a value and performing some additional higher level operation or side effect
  • Making the addition of future MetricRegistry instances easier as higher level functionality isn't implemented by the primitive metrics
  • Provides a pattern for adding functionality that will not break binary compatibility

The examples in this section assume you have imported the following and have created a MetricFactory:

import cats.effect._
import prometheus4cats._

val factory: MetricFactory[IO] = MetricFactory.noop[IO]

Timer

A Timer can be derived from either a Gauge, Histogram or [Summary] that record Double values. It uses Clock from Cats-Effect to time a given operation.

The underlying metric type should be carefully considered; a Histogram or [Summary] can be used to measure many operations at differing runtime costs, where a Gauge will only record the last value so is best for singular operations.

Obtaining from a Histogram

val simpleTimerHistogram: Resource[IO, Timer.Aux[IO, Unit, Histogram]] = factory
.histogram("time")
.ofDouble
.help("Records the how long an opertation took")
.buckets(1.0, 2.0)
.asTimer
.build
val labelledTimerHistogram: Resource[IO, Timer.Aux[IO, String, Histogram]] = factory
.histogram("time")
.ofDouble
.help("Records the how long an opertation took")
.buckets(1.0, 2.0)
.label[String]("some_label")
.asTimer
.build

Obtaining from a Summary

val simpleTimerSummary: Resource[IO, Timer.Aux[IO, Unit, Summary]] = factory
.summary("time")
.ofDouble
.help("Records the how long an opertation took")
.asTimer
.build
val labelledTimerSummary: Resource[IO, Timer.Aux[IO, String, Summary]] = factory
.summary("time")
.ofDouble
.help("Records the how long an opertation took")
.label[String]("some_label")
.asTimer
.build

Obtaining from a Gauge

val simpleTimerGauge: Resource[IO, Timer.Aux[IO, Unit, Gauge]] = factory
.gauge("time")
.ofDouble
.help("Records the how long an opertation took")
.asTimer
.build
val labelledTimerGauge: Resource[IO, Timer.Aux[IO, String, Gauge]] = factory
.gauge("time")
.ofDouble
.help("Records the how long an opertation took")
.label[String]("some_label")
.asTimer
.build

CurrentTimeRecorder

A CurrentTimeRecorder can be derived from any Gauge. It uses Clock from Cats-Effect to get the current system time.

Obtaining from a Gauge

val simpleCurrentTimeRecorderGauge: Resource[IO, CurrentTimeRecorder[IO, Unit]] = factory
.gauge("current_time")
.ofDouble
.help("Records the how long an opertation took")
.asCurrentTimeRecorder
.build
val labelledCurrentTimeRecorderGauge:
Resource[IO, CurrentTimeRecorder[IO, String]] =
factory
.gauge("current_time")
.ofDouble
.help("Records the how long an opertation took")
.label[String]("some_label")
.asCurrentTimeRecorder
.build

OutcomeRecorder

A Timer can be derived from either a Counter or Gauge. It uses Outcome from Cats-Effect to record the status of a given operation via a outcome_status label, the value of which will either be succeeded, canceled or errored.

The underlying metric type should be carefully considered based on the behaviour covered below: a Counter can be used to measure repeated operations, where a Gauge will only record the last value so is best for singular operations.

When using a with a Counter, each Outcome will increment its corresponding label value, but when using a Gauge the last invocation will set the corresponding label value to 1, with each of the other label values set to 0.

To help disambiguate the difference in behaviour the OutcomeRecorder type will be tagged with the underlying primitive metric type. This is just a type alias and is not required when passing around instances of OutcomeRecorder.

Obtaining from a Counter

val simpleOutcomeCounter: Resource[IO, OutcomeRecorder.Aux[IO, Long, Unit, Counter]] = factory
.counter("outcome_total")
.ofLong
.help("Records the outcome of some operation")
.asOutcomeRecorder
.build
val labelledOutcomeCounter:
Resource[IO, OutcomeRecorder.Aux[IO, Long, String, Counter]] = factory
.counter("outcome_total")
.ofLong
.help("Records the outcome of some operation")
.label[String]("some_label")
.asOutcomeRecorder
.build

Obtaining from a Gauge

val simpleOutcomeGauge: Resource[IO, OutcomeRecorder.Aux[IO, Long, Unit, Gauge]] = factory
.gauge("outcome")
.ofLong
.help("Records the outcome of some operation")
.asOutcomeRecorder
.build
val labelledOutcomeGauge:
Resource[IO, OutcomeRecorder.Aux[IO, Long, String, Gauge]] = factory
.gauge("outcome")
.ofLong
.help("Records the outcome of some operation")
.label[String]("some_label")
.asOutcomeRecorder
.build