Skip to content

Commit

Permalink
Selective exemplars with bincompat
Browse files Browse the repository at this point in the history
  • Loading branch information
janstenpickle committed Jul 25, 2023
1 parent 70da1b9 commit 97476e9
Show file tree
Hide file tree
Showing 14 changed files with 1,274 additions and 221 deletions.
126 changes: 122 additions & 4 deletions core/src/main/scala/prometheus4cats/Counter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,22 @@ object Counter {

sealed abstract class Exemplar[F[_], -A] { self =>
def inc: F[Unit]

def incWithExemplar: F[Unit]
def inc(n: A): F[Unit]
def incWithExemplar(n: A): F[Unit]

def contramap[B](f: B => A): Exemplar[F, B] = new Exemplar[F, B] {
override def inc: F[Unit] = self.inc

override def incWithExemplar: F[Unit] = self.incWithExemplar
override def inc(n: B): F[Unit] = self.inc(f(n))
override def incWithExemplar(n: B): F[Unit] = self.incWithExemplar(f(n))
}

final def mapK[G[_]](fk: F ~> G): Exemplar[G, A] = new Exemplar[G, A] {
override def inc: G[Unit] = fk(self.inc)

override def incWithExemplar: G[Unit] = fk(self.incWithExemplar)
override def inc(n: A): G[Unit] = fk(self.inc(n))
override def incWithExemplar(n: A): G[Unit] = fk(self.incWithExemplar(n))
}
}

Expand All @@ -94,17 +97,31 @@ object Counter {
_inc: (A, Option[prometheus4cats.Exemplar.Labels]) => F[Unit]
): Exemplar[F, A] = new Exemplar[F, A] {
override def inc: F[Unit] = inc(default)
override def inc(n: A): F[Unit] = prometheus4cats.Exemplar[F].get.flatMap(_inc(n, _))
override def inc(n: A): F[Unit] = _inc(n, None)
override def incWithExemplar: F[Unit] = incWithExemplar(default)
override def incWithExemplar(n: A): F[Unit] = prometheus4cats.Exemplar[F].get.flatMap(_inc(n, _))
}

def make[F[_]: FlatMap: prometheus4cats.Exemplar, A](_inc: (A, Option[prometheus4cats.Exemplar.Labels]) => F[Unit])(
implicit A: Numeric[A]
): Exemplar[F, A] =
make(A.one, _inc)

private[prometheus4cats] def fromCounter[F[_], A](counter: Counter[F, A]) = new Exemplar[F, A] {
override def inc: F[Unit] = counter.inc

override def inc(n: A): F[Unit] = counter.inc(n)

override def incWithExemplar: F[Unit] = inc

override def incWithExemplar(n: A): F[Unit] = inc(n)
}

def noop[F[_]: Applicative, A]: Exemplar[F, A] = new Exemplar[F, A] {
override def inc: F[Unit] = Applicative[F].unit
override def inc(n: A): F[Unit] = Applicative[F].unit
override def incWithExemplar: F[Unit] = Applicative[F].unit
override def incWithExemplar(n: A): F[Unit] = Applicative[F].unit
}
}

Expand Down Expand Up @@ -137,6 +154,107 @@ object Counter {
}

object Labelled {
sealed abstract class Exemplar[F[_], -A, -B] extends Metric[A] with Metric.Labelled[B] {
self =>
def inc(labels: B): F[Unit]

def incWithExemplar(labels: B): F[Unit]

def inc(n: A, labels: B): F[Unit]

def incWithExemplar(n: A, labels: B): F[Unit]

def contramap[C](f: C => A): Exemplar[F, C, B] = new Exemplar[F, C, B] {
override def inc(labels: B): F[Unit] = self.inc(labels)

override def inc(n: C, labels: B): F[Unit] = self.inc(f(n), labels)

override def incWithExemplar(labels: B): F[Unit] = self.incWithExemplar(labels)

override def incWithExemplar(n: C, labels: B): F[Unit] = self.incWithExemplar(f(n), labels)
}

def contramapLabels[C](f: C => B): Exemplar[F, A, C] = new Exemplar[F, A, C] {
override def inc(labels: C): F[Unit] = self.inc(f(labels))

override def inc(n: A, labels: C): F[Unit] = self.inc(n, f(labels))

override def incWithExemplar(labels: C): F[Unit] = self.incWithExemplar(f(labels))

override def incWithExemplar(n: A, labels: C): F[Unit] = self.incWithExemplar(n, f(labels))
}

final def mapK[G[_]](fk: F ~> G): Counter.Labelled.Exemplar[G, A, B] =
new Exemplar[G, A, B] {
override def inc(labels: B): G[Unit] = fk(self.inc(labels))

override def inc(n: A, labels: B): G[Unit] = fk(
self.inc(n, labels)
)

override def incWithExemplar(labels: B): G[Unit] = fk(self.incWithExemplar(labels))

override def incWithExemplar(n: A, labels: B): G[Unit] = fk(
self.incWithExemplar(n, labels)
)
}
}

object Exemplar {
implicit def catsInstances[F[_], C]: Contravariant[Exemplar[F, *, C]] =
new Contravariant[Exemplar[F, *, C]] {
override def contramap[A, B](fa: Exemplar[F, A, C])(f: B => A): Exemplar[F, B, C] = fa.contramap(f)
}

implicit def labelsContravariant[F[_], C]: LabelsContravariant[Exemplar[F, C, *]] =
new LabelsContravariant[Exemplar[F, C, *]] {
override def contramapLabels[A, B](fa: Exemplar[F, C, A])(f: B => A): Exemplar[F, C, B] =
fa.contramapLabels(f)
}

def make[F[_]: FlatMap: prometheus4cats.Exemplar, A, B](
default: A,
_inc: (A, B, Option[prometheus4cats.Exemplar.Labels]) => F[Unit]
): Exemplar[F, A, B] =
new Exemplar[F, A, B] {
override def inc(labels: B): F[Unit] = inc(default, labels)

override def inc(n: A, labels: B): F[Unit] = _inc(n, labels, None)

override def incWithExemplar(labels: B): F[Unit] = incWithExemplar(default, labels)

override def incWithExemplar(n: A, labels: B): F[Unit] =
prometheus4cats.Exemplar[F].get.flatMap(_inc(n, labels, _))
}

def make[F[_]: FlatMap: prometheus4cats.Exemplar, A, B](
_inc: (A, B, Option[prometheus4cats.Exemplar.Labels]) => F[Unit]
)(implicit
A: Numeric[A]
): Exemplar[F, A, B] = make(A.one, _inc)

private[prometheus4cats] def fromCounter[F[_], A, B](counter: Counter.Labelled[F, A, B]): Exemplar[F, A, B] =
new Exemplar[F, A, B] {
override def inc(labels: B): F[Unit] = counter.inc(labels)

override def inc(n: A, labels: B): F[Unit] = counter.inc(n, labels)

override def incWithExemplar(labels: B): F[Unit] = counter.inc(labels)

override def incWithExemplar(n: A, labels: B): F[Unit] = counter.inc(n, labels)
}

def noop[F[_]: Applicative, A, B]: Exemplar[F, A, B] = new Exemplar[F, A, B] {
override def inc(labels: B): F[Unit] = Applicative[F].unit

override def inc(n: A, labels: B): F[Unit] = Applicative[F].unit

override def incWithExemplar(labels: B): F[Unit] = Applicative[F].unit

override def incWithExemplar(n: A, labels: B): F[Unit] = Applicative[F].unit
}
}

implicit def catsInstances[F[_], C]: Contravariant[Labelled[F, *, C]] =
new Contravariant[Labelled[F, *, C]] {
override def contramap[A, B](fa: Labelled[F, A, C])(f: B => A): Labelled[F, B, C] = fa.contramap(f)
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/scala/prometheus4cats/Exemplar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ object Exemplar {
}

object Labels extends internal.Refined[SortedMap[LabelName, String], Labels] {
def of(first: (LabelName, String), rest: (LabelName, String)*): Either[String, Labels] =
from(rest.foldLeft(SortedMap.empty[LabelName, String].updated(first._1, first._2)) { case (acc, (k, v)) =>
acc.updated(k, v)
})

def fromMap(a: Map[LabelName, String]): Either[String, Labels] = from(
a.foldLeft(SortedMap.empty[LabelName, String]) { case (acc, (k, v)) => acc.updated(k, v) }
)
Expand Down
126 changes: 123 additions & 3 deletions core/src/main/scala/prometheus4cats/Histogram.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@

package prometheus4cats

import java.util.regex.Pattern

import cats.data.NonEmptySeq
import cats.{Applicative, Contravariant, ~>}
import cats.syntax.flatMap._
import cats.{Applicative, Contravariant, FlatMap, ~>}

import java.util.regex.Pattern

sealed abstract class Histogram[F[_], -A] extends Metric[A] { self =>

Expand Down Expand Up @@ -81,6 +82,51 @@ object Histogram {
override def observe(n: A): F[Unit] = Applicative[F].unit
}

sealed abstract class Exemplar[F[_], -A] extends Metric[A] {
self =>

def observe(n: A): F[Unit]

def observeWithExemplar(n: A): F[Unit]

def contramap[B](f: B => A): Exemplar[F, B] = new Exemplar[F, B] {
override def observe(n: B): F[Unit] = self.observe(f(n))

override def observeWithExemplar(n: B): F[Unit] = self.observeWithExemplar(f(n))
}

final def mapK[G[_]](fk: F ~> G): Exemplar[G, A] = new Exemplar[G, A] {
override def observe(n: A): G[Unit] = fk(self.observe(n))

override def observeWithExemplar(n: A): G[Unit] = fk(self.observeWithExemplar(n))
}
}

object Exemplar {
def make[F[_]: FlatMap: prometheus4cats.Exemplar, A](
_observe: (A, Option[prometheus4cats.Exemplar.Labels]) => F[Unit]
): Exemplar[F, A] =
new Exemplar[F, A] {
override def observe(n: A): F[Unit] = _observe(n, None)

override def observeWithExemplar(n: A): F[Unit] = prometheus4cats.Exemplar[F].get.flatMap(_observe(n, _))
}

private[prometheus4cats] def fromHistogram[F[_], A](histogram: Histogram[F, A]): Exemplar[F, A] =
new Exemplar[F, A] {
override def observe(n: A): F[Unit] = histogram.observe(n)

override def observeWithExemplar(n: A): F[Unit] = histogram.observe(n)
}

def noop[F[_]: Applicative, A]: Exemplar[F, A] =
new Exemplar[F, A] {
override def observe(n: A): F[Unit] = Applicative[F].unit

override def observeWithExemplar(n: A): F[Unit] = Applicative[F].unit
}
}

sealed abstract class Labelled[F[_], -A, -B] extends Metric[A] with Metric.Labelled[B] {
self =>

Expand Down Expand Up @@ -127,5 +173,79 @@ object Histogram {
override def observe(n: A, labels: B): F[Unit] =
Applicative[F].unit
}

sealed abstract class Exemplar[F[_], -A, -B] extends Metric[A] with Metric.Labelled[B] {
self =>

def observe(n: A, labels: B): F[Unit]

def observeWithExemplar(n: A, labels: B): F[Unit]

def contramap[C](f: C => A): Exemplar[F, C, B] = new Exemplar[F, C, B] {
override def observe(n: C, labels: B): F[Unit] = self.observe(f(n), labels)

override def observeWithExemplar(n: C, labels: B): F[Unit] = self.observeWithExemplar(f(n), labels)
}

def contramapLabels[C](f: C => B): Exemplar[F, A, C] = new Exemplar[F, A, C] {
override def observe(n: A, labels: C): F[Unit] = self.observe(n, f(labels))

override def observeWithExemplar(n: A, labels: C): F[Unit] = self.observeWithExemplar(n, f(labels))
}

final def mapK[G[_]](fk: F ~> G): Exemplar[G, A, B] =
new Exemplar[G, A, B] {
override def observe(n: A, labels: B): G[Unit] = fk(
self.observe(n, labels)
)

override def observeWithExemplar(n: A, labels: B): G[Unit] = fk(
self.observeWithExemplar(n, labels)
)
}

}

object Exemplar {
implicit def catsInstances[F[_], C]: Contravariant[Exemplar[F, *, C]] =
new Contravariant[Exemplar[F, *, C]] {
override def contramap[A, B](fa: Exemplar[F, A, C])(f: B => A): Exemplar[F, B, C] = fa.contramap(f)
}

implicit def labelsContravariant[F[_], C]: LabelsContravariant[Exemplar[F, C, *]] =
new LabelsContravariant[Exemplar[F, C, *]] {
override def contramapLabels[A, B](fa: Exemplar[F, C, A])(f: B => A): Exemplar[F, C, B] =
fa.contramapLabels(f)
}

def make[F[_]: FlatMap: prometheus4cats.Exemplar, A, B](
_observe: (A, B, Option[prometheus4cats.Exemplar.Labels]) => F[Unit]
): Exemplar[F, A, B] =
new Exemplar[F, A, B] {
override def observe(n: A, labels: B): F[Unit] = _observe(n, labels, None)

override def observeWithExemplar(n: A, labels: B): F[Unit] =
prometheus4cats.Exemplar[F].get.flatMap(_observe(n, labels, _))

}

private[prometheus4cats] def fromHistogram[F[_], A, B](
histogram: Histogram.Labelled[F, A, B]
): Exemplar[F, A, B] =
new Exemplar[F, A, B] {
override def observe(n: A, labels: B): F[Unit] = histogram.observe(n, labels)

override def observeWithExemplar(n: A, labels: B): F[Unit] = histogram.observe(n, labels)
}

def noop[F[_]: Applicative, A, B]: Exemplar[F, A, B] =
new Exemplar[F, A, B] {
override def observe(n: A, labels: B): F[Unit] = Applicative[F].unit

override def observeWithExemplar(n: A, labels: B): F[Unit] = Applicative[F].unit

}
}

}
}
Loading

0 comments on commit 97476e9

Please sign in to comment.