Skip to content

Commit 9361233

Browse files
committed
Use otel4s-testkit
1 parent 734fedf commit 9361233

2 files changed

Lines changed: 83 additions & 120 deletions

File tree

build.sbt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ lazy val core = crossProject(JVMPlatform, JSPlatform)
2525
)
2626
.jvmSettings(
2727
libraryDependencies ++= Seq(
28-
"org.typelevel" %% "otel4s-java" % otel4sV % Test,
29-
"io.opentelemetry" % "opentelemetry-sdk" % "1.15.0" % Test,
30-
"io.opentelemetry" % "opentelemetry-sdk-testing" % "1.15.0" % Test
28+
"org.typelevel" %% "otel4s-java" % otel4sV % Test,
29+
"org.typelevel" %% "otel4s-testkit" % otel4sV % Test
3130
)
3231
)
3332
.settings(
@@ -59,7 +58,7 @@ lazy val docs = project
5958
val catsV = "2.7.0"
6059
val catsEffectV = "3.3.12"
6160

62-
val otel4sV = "0.0-7f89139-20220613T071957Z-SNAPSHOT"
61+
val otel4sV = "0.0-e63fe8a-20220618T140401Z-SNAPSHOT"
6362

6463
val munitV = "0.7.29"
6564
val munitCatsEffectV = "1.0.7"
Lines changed: 80 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
package org.typelevel.keypool
22

3-
import java.util.concurrent.TimeUnit
4-
5-
import cats.syntax.all._
63
import cats.effect._
7-
import io.opentelemetry.sdk.OpenTelemetrySdk
84
import io.opentelemetry.sdk.metrics.{
95
Aggregation,
106
InstrumentSelector,
117
InstrumentType,
12-
SdkMeterProvider,
8+
SdkMeterProviderBuilder,
139
View
1410
}
15-
import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader
1611
import munit.CatsEffectSuite
1712
import org.typelevel.otel4s.{MeterProvider, Otel4s}
1813
import org.typelevel.otel4s.java.OtelJava
14+
import org.typelevel.otel4s.testkit.{HistogramPointData, Metric, MetricData, Sdk}
1915
import scala.concurrent.duration._
2016
import scala.jdk.CollectionConverters._
2117
import scala.util.control.NoStackTrace
@@ -24,10 +20,12 @@ class PoolMetricsSpec extends CatsEffectSuite {
2420
import PoolMetricsSpec._
2521

2622
test("Metrics should be empty for unused pool") {
27-
val expectedSnapshot = MetricsSnapshot(0, 0, Nil, 0, Nil)
23+
val sdk = createSdk
24+
val expectedSnapshot =
25+
MetricsSnapshot(0, 0, Nil, 0, Nil)
2826

2927
for {
30-
snapshot <- setupSdk.use(sdk => mkPool(sdk.otel.meterProvider).use(_ => sdk.snapshot))
28+
snapshot <- mkPool(sdk.otel.meterProvider).use(_ => sdk.snapshot)
3129
} yield assertEquals(snapshot, expectedSnapshot)
3230
}
3331

@@ -100,45 +98,46 @@ class PoolMetricsSpec extends CatsEffectSuite {
10098
}
10199

102100
test("Generate valid metric snapshots") {
103-
setupSdk.use { sdk =>
104-
mkPool(sdk.otel.meterProvider)
105-
.use(pool => pool.take.use(_ => sdk.snapshot.delayBy(500.millis)).product(sdk.snapshot))
106-
.map { case (inUse, afterUse) =>
107-
val acquireDuration =
108-
List(HistogramSnapshot(0, 1, HistogramBuckets, List(0, 1, 0, 0, 0)))
109-
110-
val expectedInUse = MetricsSnapshot(
111-
idle = 0,
112-
inUse = 1,
113-
inUseDuration = Nil,
114-
acquiredTotal = 1,
115-
acquireDuration = acquireDuration
116-
)
101+
val sdk = createSdk
102+
103+
mkPool(sdk.otel.meterProvider)
104+
.use(pool => pool.take.use(_ => sdk.snapshot.delayBy(500.millis)).product(sdk.snapshot))
105+
.map { case (inUse, afterUse) =>
106+
val acquireDuration =
107+
List(HistogramPointData(0, 1, HistogramBuckets, List(0, 1, 0, 0, 0)))
108+
109+
val expectedInUse = MetricsSnapshot(
110+
idle = 0,
111+
inUse = 1,
112+
inUseDuration = Nil,
113+
acquiredTotal = 1,
114+
acquireDuration = acquireDuration
115+
)
117116

118-
val expectedAfterUser = MetricsSnapshot(
119-
idle = 1,
120-
inUse = 0,
121-
inUseDuration = List(HistogramSnapshot(0, 1, HistogramBuckets, List(0, 0, 0, 1, 0))),
122-
acquiredTotal = 1,
123-
acquireDuration = acquireDuration
124-
)
117+
val expectedAfterUser = MetricsSnapshot(
118+
idle = 1,
119+
inUse = 0,
120+
inUseDuration = List(HistogramPointData(0, 1, HistogramBuckets, List(0, 0, 0, 1, 0))),
121+
acquiredTotal = 1,
122+
acquireDuration = acquireDuration
123+
)
125124

126-
assertEquals(inUse.zeroSumHistogram, expectedInUse)
127-
assertEquals(afterUse.zeroSumHistogram, expectedAfterUser)
128-
assert(afterUse.inUseDuration.forall(r => r.sum >= 500 && r.sum <= 700))
129-
}
130-
}
125+
assertEquals(inUse.zeroSumHistogram, expectedInUse)
126+
assertEquals(afterUse.zeroSumHistogram, expectedAfterUser)
127+
assert(afterUse.inUseDuration.forall(r => r.sum >= 500 && r.sum <= 700))
128+
}
131129
}
132130

133131
private def poolTest(
134132
customize: Pool.Builder[IO, Ref[IO, Int]] => Pool.Builder[IO, Ref[IO, Int]] = identity
135-
)(scenario: (OtelSdk[IO], Pool[IO, Ref[IO, Int]]) => IO[Unit]): IO[Unit] =
136-
setupSdk.use { sdk =>
137-
val builder =
138-
Pool.Builder(Ref.of[IO, Int](1), nothing).withMeterProvider(sdk.otel.meterProvider)
133+
)(scenario: (OtelSdk[IO], Pool[IO, Ref[IO, Int]]) => IO[Unit]): IO[Unit] = {
134+
val sdk = createSdk
139135

140-
customize(builder).build.use(pool => scenario(sdk, pool))
141-
}
136+
val builder =
137+
Pool.Builder(Ref.of[IO, Int](1), nothing).withMeterProvider(sdk.otel.meterProvider)
138+
139+
customize(builder).build.use(pool => scenario(sdk, pool))
140+
}
142141

143142
private def mkPool(meterProvider: MeterProvider[IO]) =
144143
Pool
@@ -150,13 +149,9 @@ class PoolMetricsSpec extends CatsEffectSuite {
150149
.withMaxTotal(10)
151150
.build
152151

153-
private def setupSdk: Resource[IO, OtelSdk[IO]] = {
154-
val acquire = IO.delay {
155-
val mr = InMemoryMetricReader.create()
156-
157-
val mp = SdkMeterProvider
158-
.builder()
159-
.registerMetricReader(mr)
152+
private def createSdk: OtelSdk[IO] = {
153+
def customize(builder: SdkMeterProviderBuilder) =
154+
builder
160155
.registerView(
161156
InstrumentSelector.builder().setType(InstrumentType.HISTOGRAM).build(),
162157
View
@@ -166,63 +161,43 @@ class PoolMetricsSpec extends CatsEffectSuite {
166161
)
167162
.build()
168163
)
169-
.build()
170-
171-
val sdk = OpenTelemetrySdk
172-
.builder()
173-
.setMeterProvider(mp)
174-
.build()
175-
176-
new OtelSdk[IO] {
177-
def metricReader: InMemoryMetricReader = mr
178-
def otel: Otel4s[IO] = OtelJava.forSync[IO](sdk)
179-
def flush: IO[Unit] = IO.blocking {
180-
val _ = mp.forceFlush().join(5, TimeUnit.SECONDS)
181-
()
182-
}
183164

184-
def snapshot: IO[MetricsSnapshot] = {
185-
IO.delay {
186-
val items = metricReader.collectAllMetrics().asScala.toList
187-
188-
def counterValue(name: String): Long =
189-
items
190-
.find(_.getName === name)
191-
.flatMap(_.getLongSumData.getPoints.asScala.headOption.map(_.getValue))
192-
.getOrElse(0L)
193-
194-
def histogramSnapshot(name: String): List[HistogramSnapshot] =
195-
items
196-
.find(_.getName === name)
197-
.map { metric =>
198-
val points = metric.getHistogramData.getPoints.asScala.toList
199-
200-
points.map { hdp =>
201-
HistogramSnapshot(
202-
hdp.getSum,
203-
hdp.getCount,
204-
hdp.getBoundaries.asScala.toList.map(Double.unbox),
205-
hdp.getCounts.asScala.toList.map(Long.unbox)
206-
)
207-
}
208-
}
209-
.getOrElse(Nil)
210-
211-
MetricsSnapshot(
212-
counterValue("idle"),
213-
counterValue("in_use"),
214-
histogramSnapshot("in_use_duration"),
215-
counterValue("acquired_total"),
216-
histogramSnapshot("acquire_duration")
217-
)
218-
}
165+
val sdk = Sdk.create[IO](customize)
166+
167+
new OtelSdk[IO] {
168+
val otel: Otel4s[IO] = OtelJava.forSync[IO](sdk.sdk)
169+
170+
def snapshot: IO[MetricsSnapshot] =
171+
for {
172+
metrics <- sdk.metrics
173+
} yield {
174+
def counterValue(name: String): Long =
175+
metrics
176+
.collectFirst {
177+
case Metric(metricName, _, _, _, _, MetricData.LongSum(points))
178+
if metricName == name =>
179+
points.headOption.map(_.value).getOrElse(0L)
180+
}
181+
.getOrElse(0L)
182+
183+
def histogramSnapshot(name: String): List[HistogramPointData] =
184+
metrics
185+
.collectFirst {
186+
case Metric(metricName, _, _, _, _, h: MetricData.Histogram)
187+
if metricName == name =>
188+
h.points.map(_.value)
189+
}
190+
.getOrElse(Nil)
191+
192+
MetricsSnapshot(
193+
counterValue("idle"),
194+
counterValue("in_use"),
195+
histogramSnapshot("in_use_duration"),
196+
counterValue("acquired_total"),
197+
histogramSnapshot("acquire_duration")
198+
)
219199
}
220-
}
221200
}
222-
223-
def release(sdk: OtelSdk[IO]) = sdk.flush
224-
225-
Resource.make(acquire)(release)
226201
}
227202

228203
private val HistogramBuckets: List[Double] =
@@ -236,34 +211,23 @@ class PoolMetricsSpec extends CatsEffectSuite {
236211
object PoolMetricsSpec {
237212

238213
trait OtelSdk[F[_]] {
239-
def metricReader: InMemoryMetricReader
240214
def otel: Otel4s[F]
241-
def flush: F[Unit]
242215
def snapshot: F[MetricsSnapshot]
243216
}
244217

245218
final case class MetricsSnapshot(
246219
idle: Long,
247220
inUse: Long,
248-
inUseDuration: List[HistogramSnapshot],
221+
inUseDuration: List[HistogramPointData],
249222
acquiredTotal: Long,
250-
acquireDuration: List[HistogramSnapshot]
223+
acquireDuration: List[HistogramPointData]
251224
) {
252225
// use 0 for `histogram#sum` to simplify the comparison
253226
def zeroSumHistogram: MetricsSnapshot =
254227
copy(
255-
inUseDuration = inUseDuration.map(_.zeroSum),
256-
acquireDuration = acquireDuration.map(_.zeroSum)
228+
inUseDuration = inUseDuration.map(_.copy(sum = 0)),
229+
acquireDuration = acquireDuration.map(_.copy(sum = 0))
257230
)
258231
}
259232

260-
final case class HistogramSnapshot(
261-
sum: Double,
262-
count: Long,
263-
boundaries: List[Double],
264-
counts: List[Long]
265-
) {
266-
def zeroSum: HistogramSnapshot = copy(sum = 0)
267-
}
268-
269233
}

0 commit comments

Comments
 (0)