Skip to content

Commit

Permalink
Merge pull request #71 from permutive-engineering/labels-improvements
Browse files Browse the repository at this point in the history
Allow using `labels` the same way we use `label`
  • Loading branch information
alejandrohdezma authored Aug 18, 2023
2 parents 45031ee + d2e44c7 commit 4aeab3f
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 13 deletions.
76 changes: 68 additions & 8 deletions core/src/main/scala/prometheus4cats/internal/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,10 @@ class MetricDsl[F[_], A, L[_[_], _, _]] private[prometheus4cats] (
labelNames: Label.Name*
): BuildStep[F, L[F, A, Map[Label.Name, String]]] = unsafeLabels(labelNames.toIndexedSeq)

/** Creates a metric whose labels comes from a single type. Takes a collection of label name and a function converting
* some label object `B` to a string pairs.
/** Sets the first labels for a metric coming from a single type. Takes a collection of label name and a function
* converting some label object `B` to a string pairs.
*
* This is useful where a single type `B` translates to multiple labels. Once invoked, this cannot be used with the
* singular `.label` syntax.
* This is useful where a single type `B` translates to multiple labels.
*
* @tparam B
* type to convert into labels
Expand All @@ -231,11 +230,11 @@ class MetricDsl[F[_], A, L[_[_], _, _]] private[prometheus4cats] (
* @param labelNames
* collection of labels name & function to convert `B` in to a label value pairs
*/
def labels[B](labels: (Label.Name, B => String)*): LabelsBuildStep[F, A, B, L] = {
def labels[B](labels: (Label.Name, B => String)*): LabelledMetricDsl[F, A, B, L] = {
val labelNames = labels.toIndexedSeq.map(_._1)
val labelValues = labels.toIndexedSeq.map(_._2)

new LabelsBuildStep(makeMetric, labelNames, b => labelValues.map(_(b)))
new LabelledMetricDsl(makeMetric, labelNames, b => labelValues.map(_(b)))
}

}
Expand Down Expand Up @@ -266,11 +265,11 @@ object MetricDsl {
labelNames.toIndexedSeq
)

override def labels[B](labels: (Label.Name, B => String)*): LabelsBuildStep.WithCallbacks[F, A, A0, B, L] = {
override def labels[B](labels: (Label.Name, B => String)*): LabelledMetricDsl.WithCallbacks[F, A, A0, B, L] = {
val labelNames = labels.toIndexedSeq.map(_._1)
val labelValues = labels.toIndexedSeq.map(_._2)

new LabelsBuildStep.WithCallbacks(makeMetric, makeCallback, labelNames, b => labelValues.map(_(b)))
new LabelledMetricDsl.WithCallbacks(makeMetric, makeCallback, labelNames, b => labelValues.map(_(b)))
}

override def label[B]: FirstLabelApply.WithCallbacks[F, A, A0, B, L] =
Expand Down Expand Up @@ -434,6 +433,31 @@ class LabelledMetricDsl[F[_], A, T, L[_[_], _, _]] private[internal] (

}

/** Sets a new set of labels for the metric coming from a single type. Takes a collection of label name and a function
* converting some label object `B` to a string pairs.
*
* This is useful where a single type `B` translates to multiple labels.
*
* @tparam B
* type to convert into labels
* @tparam N
* size of the label collection
* @param labelNames
* collection of labels name & function to convert `B` in to a label value pairs
*/
def labels[B]: LabelsApply[F, A, T, B, L] =
new LabelsApply[F, A, T, B, L] {

override def apply[C](
labels: (Label.Name, B => String)*
)(implicit initLast: InitLast.Aux[T, B, C]): LabelledMetricDsl[F, A, C, L] = new LabelledMetricDsl(
makeMetric,
labelNames ++ labels.map(_._1),
c => f(initLast.init(c)) ++ labels.map(_._2(initLast.last(c)))
)

}

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

}

/** @inheritdoc
*/
override def labels[B]: LabelsApply.WithCallbacks[F, A, A0, T, B, L] =
new LabelsApply.WithCallbacks[F, A, A0, T, B, L] {

override def apply[C](labels: (Label.Name, B => String)*)(implicit
initLast: InitLast.Aux[T, B, C]
): WithCallbacks[F, A, A0, C, L] = new WithCallbacks(
makeMetric,
makeCallback,
labelNames ++ labels.map(_._1),
c => f(initLast.init(c)) ++ labels.map(_._2(initLast.last(c)))
)

}

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 @@ -542,6 +582,26 @@ object LabelApply {
}
}

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

def apply[C](labels: (Label.Name, B => String)*)(implicit
initLast: InitLast.Aux[T, B, C]
): LabelledMetricDsl[F, A, C, L]

}

object LabelsApply {

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

def apply[C](labels: (Label.Name, B => String)*)(implicit
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 @@ -62,7 +62,7 @@ object SummaryDsl {
labelNames: Label.Name*
): BuildStep[F, Summary[F, A, Map[Label.Name, String]]]

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

private val defaultQuantiles: Seq[Summary.QuantileDefinition] = Seq.empty
Expand Down
8 changes: 4 additions & 4 deletions core/src/test/scala/test/MetricsFactoryDslTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ object MetricsFactoryDslTest {
doubleLabelledGaugeBuilder.asCurrentTimeRecorder(_.toUnit(TimeUnit.NANOSECONDS))
doubleLabelledGaugeBuilder.asOutcomeRecorder.build

val doubleLabelsGaugeBuilder = doubleGaugeBuilder.labels(Label.Name("test") -> ((s: String) => s)).build
val doubleLabelsGaugeBuilder =
doubleGaugeBuilder.labels(Label.Name("test") -> ((s: String) => s)).label[String]("other_label").build

val longGaugeBuilder = gaugeBuilder.ofLong.help("help")
longGaugeBuilder.build
Expand Down Expand Up @@ -77,10 +78,9 @@ object MetricsFactoryDslTest {
longCounterBuilder.build
longCounterBuilder
.label[String]("label1")
.label[Int]("label2")
.label[BigInteger]("label3", _.toString)
.labels[(Int, BigInteger)](("label2", _._1.toString()), ("label3", _._2.toString()))
.build
.map(_.inc(("dsfsf", 1, BigInteger.ONE)))
.map(_.inc(("dsfsf", (1, BigInteger.ONE))))
longCounterBuilder.unsafeLabels(Label.Name("label1"), Label.Name("label2")).build

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

0 comments on commit 4aeab3f

Please sign in to comment.