Add global labels to the OpenTelemetry metrics implementation [PLEN-5] (#15407)

This commit is contained in:
Nicu Reut 2022-11-01 16:28:53 +01:00 committed by GitHub
parent 7ab367b0e3
commit 7077a4dce1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 6 deletions

View File

@ -24,6 +24,7 @@ da_scala_library(
runtime_deps = [], runtime_deps = [],
deps = [ deps = [
"//ledger/ledger-resources", "//ledger/ledger-resources",
"//libs-scala/build-info",
"//libs-scala/concurrent", "//libs-scala/concurrent",
"//libs-scala/resources", "//libs-scala/resources",
"//libs-scala/resources-akka", "//libs-scala/resources-akka",

View File

@ -15,6 +15,8 @@ case class MetricsContext(labels: Map[String, String]) {
.build() .build()
} }
def merge(context: MetricsContext): MetricsContext = this.copy(labels = labels ++ context.labels)
} }
object MetricsContext { object MetricsContext {

View File

@ -6,6 +6,7 @@ package com.daml.metrics.api.opentelemetry
import java.time.Duration import java.time.Duration
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import com.daml.buildinfo.BuildInfo
import com.daml.metrics.api.Gauges.VarGauge import com.daml.metrics.api.Gauges.VarGauge
import com.daml.metrics.api.MetricHandle.Timer.TimerHandle import com.daml.metrics.api.MetricHandle.Timer.TimerHandle
import com.daml.metrics.api.MetricHandle.{Counter, Factory, Gauge, Histogram, Meter, Timer} import com.daml.metrics.api.MetricHandle.{Counter, Factory, Gauge, Histogram, Meter, Timer}
@ -20,7 +21,12 @@ import io.opentelemetry.api.metrics.{
trait OpenTelemetryFactory extends Factory { trait OpenTelemetryFactory extends Factory {
val globalMetricsContext: MetricsContext = MetricsContext(
Map("daml_version" -> BuildInfo.Version)
)
def otelMeter: OtelMeter def otelMeter: OtelMeter
override def timer( override def timer(
name: MetricName name: MetricName
)(implicit )(implicit
@ -29,12 +35,12 @@ trait OpenTelemetryFactory extends Factory {
OpentelemetryTimer( OpentelemetryTimer(
name, name,
otelMeter.histogramBuilder(name).ofLongs().setUnit("ms").build(), otelMeter.histogramBuilder(name).ofLongs().setUnit("ms").build(),
context, globalMetricsContext.merge(context),
) )
override def gauge[T](name: MetricName, initial: T)(implicit override def gauge[T](name: MetricName, initial: T)(implicit
context: MetricsContext = MetricsContext.Empty context: MetricsContext = MetricsContext.Empty
): MetricHandle.Gauge[T] = { ): MetricHandle.Gauge[T] = {
val attributes = context.asAttributes val attributes = globalMetricsContext.merge(context).asAttributes
initial match { initial match {
case longInitial: Int => case longInitial: Int =>
val varGauge = new VarGauge[Int](longInitial) val varGauge = new VarGauge[Int](longInitial)
@ -67,7 +73,7 @@ trait OpenTelemetryFactory extends Factory {
context: MetricsContext = MetricsContext.Empty context: MetricsContext = MetricsContext.Empty
): Unit = { ): Unit = {
val value = valueSupplier() val value = valueSupplier()
val attributes = context.asAttributes val attributes = globalMetricsContext.merge(context).asAttributes
value match { value match {
case _: Int => case _: Int =>
otelMeter otelMeter
@ -104,21 +110,21 @@ trait OpenTelemetryFactory extends Factory {
): Meter = OpentelemetryMeter( ): Meter = OpentelemetryMeter(
name, name,
otelMeter.counterBuilder(name).build(), otelMeter.counterBuilder(name).build(),
context, globalMetricsContext.merge(context),
) )
override def counter(name: MetricName)(implicit override def counter(name: MetricName)(implicit
context: MetricsContext = MetricsContext.Empty context: MetricsContext = MetricsContext.Empty
): MetricHandle.Counter = OpentelemetryCounter( ): MetricHandle.Counter = OpentelemetryCounter(
name, name,
otelMeter.upDownCounterBuilder(name).build(), otelMeter.upDownCounterBuilder(name).build(),
context, globalMetricsContext.merge(context),
) )
override def histogram(name: MetricName)(implicit override def histogram(name: MetricName)(implicit
context: MetricsContext = MetricsContext.Empty context: MetricsContext = MetricsContext.Empty
): MetricHandle.Histogram = OpentelemetryHistogram( ): MetricHandle.Histogram = OpentelemetryHistogram(
name, name,
otelMeter.histogramBuilder(name).ofLongs().build(), otelMeter.histogramBuilder(name).ofLongs().build(),
context, globalMetricsContext.merge(context),
) )
} }

View File

@ -0,0 +1,47 @@
// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.metrics.api
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
class MetricsContextSpec extends AnyWordSpec with Matchers {
"merging metrics contexts" should {
"merge all labels" in {
MetricsContext(
Map("key" -> "value")
).merge(
MetricsContext(
Map("key2" -> "value")
)
) should equal(
MetricsContext(
Map(
"key" -> "value",
"key2" -> "value",
)
)
)
}
"handle duplicate labels" in {
MetricsContext(
Map("key" -> "value1")
).merge(
MetricsContext(
Map("key" -> "value2")
)
) should equal(
MetricsContext(
Map(
"key" -> "value2"
)
)
)
}
}
}