Skip to content

Commit

Permalink
Add labels encoder
Browse files Browse the repository at this point in the history
  • Loading branch information
janstenpickle committed Aug 18, 2023
1 parent dd0db4d commit 7620129
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 3 deletions.
13 changes: 11 additions & 2 deletions core/src/main/scala/prometheus4cats/Label.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,21 @@ object Label {

object Value extends ValueLowPriority0 {

implicit def fromString(a: String): Value = new Value(a)
def apply(a: String) = new Value(a)
implicit def fromString(a: String): Value = apply(a)

}

trait ValueLowPriority0 {
implicit def fromShow[A: Show](a: A): Value = Value.fromString(a.show)
implicit def fromShow[A: Show](a: A): Value = Value(a.show)
}

trait Encoder[A] {
def toLabels: IndexedSeq[(Label.Name, A => Label.Value)]
}

object Encoder {
def apply[A: Encoder]: Encoder[A] = implicitly
}

}
54 changes: 54 additions & 0 deletions core/src/main/scala/prometheus4cats/internal/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import cats.syntax.all._
import cats.{Contravariant, FlatMap, Functor, Show}
import prometheus4cats.OutcomeRecorder.Status
import prometheus4cats._
import prometheus4cats.internal.InitLast.Aux

import scala.concurrent.duration.FiniteDuration

Expand Down Expand Up @@ -237,6 +238,8 @@ class MetricDsl[F[_], A, L[_[_], _, _]] private[prometheus4cats] (
new LabelledMetricDsl(makeMetric, labelNames, b => labelValues.map(_(b).value))
}

def labelsFrom[B](implicit encoder: Label.Encoder[B]): LabelledMetricDsl[F, A, B, L] = labels(encoder.toLabels: _*)

}

object MetricDsl {
Expand Down Expand Up @@ -272,6 +275,9 @@ object MetricDsl {
new LabelledMetricDsl.WithCallbacks(makeMetric, makeCallback, labelNames, b => labelValues.map(_(b).value))
}

override def labelsFrom[B](implicit encoder: Label.Encoder[B]): LabelledMetricDsl.WithCallbacks[F, A, A0, B, L] =
labels(encoder.toLabels: _*)

override def label[B]: FirstLabelApply.WithCallbacks[F, A, A0, B, L] =
new FirstLabelApply.WithCallbacks[F, A, A0, B, L] {
override def apply(
Expand Down Expand Up @@ -458,6 +464,18 @@ class LabelledMetricDsl[F[_], A, T, L[_[_], _, _]] private[internal] (

}

def labelsFrom[B]: LabelsFromApply[F, A, T, B, L] = new LabelsFromApply[F, A, T, B, L] {
override def apply[C](implicit encoder: Label.Encoder[B], initLast: Aux[T, B, C]): LabelledMetricDsl[F, A, C, L] = {
val labels = encoder.toLabels

new LabelledMetricDsl(
makeMetric,
labelNames ++ labels.map(_._1),
c => f(initLast.init(c)) ++ labels.map(_._2(initLast.last(c)).value)
)
}
}

override def contramapLabels[B](f0: B => T): LabelledMetricDsl[F, A, B, L] = new LabelledMetricDsl(
makeMetric,
labelNames,
Expand Down Expand Up @@ -509,6 +527,23 @@ object LabelledMetricDsl {

}

override def labelsFrom[B]: LabelsFromApply.WithCallbacks[F, A, A0, T, B, L] =
new LabelsFromApply.WithCallbacks[F, A, A0, T, B, L] {
override def apply[C](implicit
encoder: Label.Encoder[B],
initLast: Aux[T, B, C]
): LabelledMetricDsl.WithCallbacks[F, A, A0, C, L] = {
val labels = encoder.toLabels

new LabelledMetricDsl.WithCallbacks(
makeMetric,
makeCallback,
labelNames ++ labels.map(_._1),
c => f(initLast.init(c)) ++ labels.map(_._2(initLast.last(c)).value)
)
}
}

override def contramapLabels[B](f0: B => T): WithCallbacks[F, A, A0, B, L] =
new WithCallbacks(makeMetric, makeCallback, labelNames, b => f(f0(b)))
}
Expand Down Expand Up @@ -602,6 +637,25 @@ object LabelsApply {

}

abstract class LabelsFromApply[F[_], A, T, B, L[_[_], _, _]] {

def apply[C](implicit encoder: Label.Encoder[B], initLast: InitLast.Aux[T, B, C]): LabelledMetricDsl[F, A, C, L]

}

object LabelsFromApply {

abstract class WithCallbacks[F[_], A, A0, T, B, L[_[_], _, _]] extends LabelsFromApply[F, A, T, B, L] {

override def apply[C](implicit
encoder: Label.Encoder[B],
initLast: InitLast.Aux[T, B, C]
): LabelledMetricDsl.WithCallbacks[F, A, A0, C, L]

}

}

trait LabelledMetricPartiallyApplied[F[_], A, L[_[_], _, _]] {
def apply[B](labels: IndexedSeq[Label.Name])(f: B => IndexedSeq[String]): Resource[F, L[F, A, B]]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ object SummaryDsl {
): BuildStep[F, Summary[F, A, Map[Label.Name, String]]]

def labels[B](labels: (Label.Name, B => Label.Value)*): LabelledMetricDsl[F, A, B, Summary]

def labelsFrom[B](implicit encoder: Label.Encoder[B]): LabelledMetricDsl[F, A, B, Summary]
}

private val defaultQuantiles: Seq[Summary.QuantileDefinition] = Seq.empty
Expand Down
14 changes: 13 additions & 1 deletion core/src/test/scala/test/MetricsFactoryDslTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,25 @@ object MetricsFactoryDslTest {
doubleLabelledCounterBuilder.contramap[Int](_.toDouble).build
doubleLabelledCounterBuilder.asOutcomeRecorder.build

case class LabelsClass(a: String, b: Long)
object LabelsClass {
implicit val encoder: Label.Encoder[LabelsClass] = new Label.Encoder[LabelsClass] {
override val toLabels: IndexedSeq[(Label.Name, LabelsClass => Label.Value)] =
IndexedSeq(
Label.Name("a") -> ((lc: LabelsClass) => Label.Value(lc.a)),
Label.Name("b") -> ((lc: LabelsClass) => Label.Value.fromShow(lc.b))
)
}
}

val longCounterBuilder = counterBuilder.ofLong.help("help")
longCounterBuilder.build
longCounterBuilder
.labelsFrom[LabelsClass]
.label[String]("label1")
.labels[(Int, BigInteger)](("label2", _._1), ("label3", _._2.toString()))
.build
.map(_.inc(("dsfsf", (1, BigInteger.ONE))))
.map(_.inc((LabelsClass("sdfds", 22), "dsfsf", (1, BigInteger.ONE))))
longCounterBuilder.unsafeLabels(Label.Name("label1"), Label.Name("label2")).build

val histogramBuilder = factory.histogram("test2")
Expand Down

0 comments on commit 7620129

Please sign in to comment.