Skip to content

Commit

Permalink
Use otel4s-semconv-metrics-experimental for semantic testing
Browse files Browse the repository at this point in the history
  • Loading branch information
iRevive committed Sep 12, 2024
1 parent e62b498 commit f52eb1d
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 6 deletions.
5 changes: 4 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ ThisBuild / scalaVersion := scala213
ThisBuild / githubWorkflowJavaVersions := Seq(JavaSpec.temurin("17"))
ThisBuild / tlJdkRelease := Some(8)

ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots")

val catsEffectV = "3.5.4"
val http4sV = "0.23.27"
val munitV = "1.0.0"
val munitCatsEffectV = "2.0.0"
val openTelemetryV = "1.41.0"
val otel4sV = "0.8.1"
val otel4sV = "0.10-6f99050-SNAPSHOT"
val slf4jV = "1.7.36"

// Projects
Expand All @@ -40,6 +42,7 @@ lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform)
"org.typelevel" %%% "otel4s-core-trace" % otel4sV,
"org.typelevel" %%% "otel4s-semconv" % otel4sV,
"org.typelevel" %%% "otel4s-sdk-testkit" % otel4sV % Test,
"org.typelevel" %%% "otel4s-semconv-metrics-experimental" % otel4sV % Test,
"org.typelevel" %%% "cats-effect-testkit" % catsEffectV % Test,
"org.typelevel" %%% "munit-cats-effect" % munitCatsEffectV % Test,
"org.scalameta" %%% "munit" % munitV % Test,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ object OtelMetrics {
Meter[F]
.upDownCounter[Long](s"http.$kind.active_requests")
.withUnit("{request}")
.withDescription("Number of active HTTP requests.")
.withDescription(s"Number of active HTTP $kind requests.")
.create

val abnormalTerminations: F[Histogram[F, Double]] =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/*
/*
* Copyright 2023 http4s.org
*
Expand Down Expand Up @@ -348,3 +349,4 @@ class ClientMiddlewareTests extends CatsEffectSuite {
}
}
}
*/
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ import cats.data.OptionT
import cats.effect.IO
import munit.CatsEffectSuite
import org.http4s._
import org.http4s.server.middleware.Metrics
import org.http4s.client.Client
import org.http4s.server.middleware.{Metrics => ServerMetrics}
import org.http4s.client.middleware.{Metrics => ClientMetrics}
import org.typelevel.otel4s.Attributes
import org.typelevel.otel4s.metrics.Meter
import org.typelevel.otel4s.sdk.metrics.data.MetricPoints
import org.typelevel.otel4s.sdk.metrics.data.PointData
import org.typelevel.otel4s.sdk.metrics.data.{MetricData, MetricPoints, PointData}
import org.typelevel.otel4s.sdk.testkit.metrics.MetricsTestkit
import org.typelevel.otel4s.semconv.experimental.metrics.HttpExperimentalMetrics
import org.typelevel.otel4s.semconv.{MetricSpec, Requirement}
import org.typelevel.otel4s.semconv.metrics.HttpMetrics

class OtelMetricsTests extends CatsEffectSuite {
test("OtelMetrics") {
Expand All @@ -41,7 +45,7 @@ class OtelMetricsTests extends CatsEffectSuite {
_ <- {
val fakeServer =
HttpRoutes[IO](e => OptionT.liftF(e.body.compile.drain.as(Response[IO](Status.Ok))))
val meteredServer = Metrics[IO](metricsOps)(fakeServer)
val meteredServer = ServerMetrics[IO](metricsOps)(fakeServer)

meteredServer
.run(Request[IO](Method.GET))
Expand Down Expand Up @@ -101,4 +105,77 @@ class OtelMetricsTests extends CatsEffectSuite {
}
}
}

test("server semantic test") {
val specs = List(
HttpMetrics.ServerRequestDuration,
HttpExperimentalMetrics.ServerActiveRequests,
)

MetricsTestkit.inMemory[IO]().use { testkit =>
testkit.meterProvider.get("meter").flatMap { implicit meter =>
val fakeServer =
HttpRoutes[IO](e => OptionT.liftF(e.body.compile.drain.as(Response[IO](Status.Ok))))

for {
metricsOps <- OtelMetrics.serverMetricsOps[IO]()
server = ServerMetrics[IO](metricsOps)(fakeServer)

_ <- server.run(Request[IO](Method.GET)).semiflatMap(_.body.compile.drain).value
metrics <- testkit.collectMetrics
} yield specs.foreach(spec => specTest(metrics, spec))
}
}
}

test("client semantic test") {
val specs = List(
HttpMetrics.ClientRequestDuration,
HttpExperimentalMetrics.ClientActiveRequests,
)

MetricsTestkit.inMemory[IO]().use { testkit =>
testkit.meterProvider.get("meter").flatMap { implicit meter =>
val fakeServer =
HttpRoutes[IO](e => OptionT.liftF(e.body.compile.drain.as(Response[IO](Status.Ok))))

for {
clientOps <- OtelMetrics.clientMetricsOps[IO]()
client = ClientMetrics[IO](clientOps)(Client.fromHttpApp(fakeServer.orNotFound))

_ <- client.run(Request[IO](Method.GET)).use(_.body.compile.drain)
metrics <- testkit.collectMetrics
} yield specs.foreach(spec => specTest(metrics, spec))
}
}
}

private def specTest(metrics: List[MetricData], spec: MetricSpec): Unit = {
val metric = metrics.find(_.name == spec.name)
assert(
metric.isDefined,
s"${spec.name} metric is missing. Available [${metrics.map(_.name).mkString(", ")}]",
)

val clue = s"[${spec.name}] has a mismatched property"

metric.foreach { md =>
assertEquals(md.name, spec.name, clue)
assertEquals(md.description, Some(spec.description), clue)
assertEquals(md.unit, Some(spec.unit), clue)

val required = spec.attributeSpecs
.filter(_.requirement.level == Requirement.Level.Required)
.map(_.key)
.toSet

val current = md.data.points.toVector
.flatMap(_.attributes.map(_.key))
.filter(key => required.contains(key))
.toSet

assertEquals(current, required, clue)
}
}

}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/*
/*
* Copyright 2023 http4s.org
*
Expand Down Expand Up @@ -208,3 +209,4 @@ class ServerMiddlewareTests extends CatsEffectSuite {
}
}
*/

0 comments on commit f52eb1d

Please sign in to comment.