From cbc868a523e9c74824110edc503bb65fe1c1f5a1 Mon Sep 17 00:00:00 2001 From: Maksym Ochenashko Date: Sat, 11 Apr 2026 12:42:37 +0100 Subject: [PATCH 1/5] Update otel4s to 0.16.0, enable Scala Native --- build.sbt | 22 +++--- .../otel4s/Otel4sMetricsBackend.scala | 1 - .../otel4s/UrlExperimentalAttributes.scala | 9 +++ .../otel4s/Otel4sMetricsBackendTest.scala | 55 +++++++-------- .../otel4s/Otel4sTracingBackendTest.scala | 69 ++++++++++++++----- 5 files changed, 98 insertions(+), 58 deletions(-) create mode 100644 observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/UrlExperimentalAttributes.scala diff --git a/build.sbt b/build.sbt index bcad07008..c58d00058 100644 --- a/build.sbt +++ b/build.sbt @@ -129,9 +129,6 @@ val playJsonVersion = "3.0.6" val catsEffect_3_version = "3.7.0" val fs2_3_version = "3.13.0" -// This version provides Scala Native 0.5.x support. Drop this when 3.7.0 is released. -val catsEffect_3_RC_version = "3.7.0-RC1" - val catsEffect_2_version = "2.5.5" val fs2_2_version = "2.5.13" @@ -170,8 +167,8 @@ val osLibVersion = "0.11.4" val tethysVersion = "0.29.8" val openTelemetryVersion = "1.59.0" val openTelemetrySemconvVersion = "1.40.0" -val otel4s = "0.15.2" -val otel4sSdk = "0.17.0" +val otel4s = "0.16.0" +val otel4sSdk = "0.18.0" val slf4jVersion = "1.7.36" val compileAndTest = "compile->compile;test->test" @@ -397,13 +394,10 @@ lazy val catsCe2 = (projectMatrix in file("effects/cats-ce2")) ) lazy val catsEffect = Def.setting { - val ceVersion = - if (virtualAxes.value.contains(VirtualAxis.native)) catsEffect_3_RC_version - else catsEffect_3_version Seq( - "org.typelevel" %%% "cats-effect-kernel" % ceVersion, - "org.typelevel" %%% "cats-effect-std" % ceVersion, - "org.typelevel" %%% "cats-effect" % ceVersion % Test + "org.typelevel" %%% "cats-effect-kernel" % catsEffect_3_version, + "org.typelevel" %%% "cats-effect-std" % catsEffect_3_version, + "org.typelevel" %%% "cats-effect" % catsEffect_3_version % Test ) } @@ -424,7 +418,7 @@ lazy val cats = (projectMatrix in file("effects/cats")) settings = commonJsSettings ++ commonJsBackendSettings ++ browserChromeTestSettings ++ testServerSettings ) .nativePlatform( - scalaVersions = List(scala3), + scalaVersions = scala2And3, settings = commonNativeSettings ++ testServerSettings ) @@ -975,13 +969,14 @@ lazy val otel4sMetricsBackend = (projectMatrix in file("observability/otel4s-met libraryDependencies ++= Seq( "org.typelevel" %%% "otel4s-core-metrics" % otel4s, "org.typelevel" %%% "otel4s-semconv" % otel4s, - "org.typelevel" %%% "otel4s-semconv-experimental" % otel4s, + "org.typelevel" %%% "otel4s-semconv-experimental" % otel4s % Test, "org.typelevel" %%% "otel4s-semconv-metrics-experimental" % otel4s % Test, "org.typelevel" %%% "otel4s-sdk-metrics-testkit" % otel4sSdk % Test ) ) .jvmPlatform(scalaVersions = scala2_13And3, settings = commonJvmSettings) .jsPlatform(scalaVersions = scala2_13And3, settings = commonJsSettings) + .nativePlatform(scalaVersions = scala2_13And3, settings = commonNativeSettings) .dependsOn(cats % Test) .dependsOn(core % compileAndTest) @@ -997,6 +992,7 @@ lazy val otel4sTracingBackend = (projectMatrix in file("observability/otel4s-tra ) .jvmPlatform(scalaVersions = scala2_13And3, settings = commonJvmSettings) .jsPlatform(scalaVersions = scala2_13And3, settings = commonJsSettings) + .nativePlatform(scalaVersions = scala2_13And3, settings = commonNativeSettings) .dependsOn(cats % Test) .dependsOn(core % compileAndTest) diff --git a/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackend.scala b/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackend.scala index b5adb5b65..00139f062 100644 --- a/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackend.scala +++ b/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackend.scala @@ -18,7 +18,6 @@ import org.typelevel.otel4s.semconv.attributes.{ ServerAttributes, UrlAttributes } -import org.typelevel.otel4s.semconv.experimental.attributes.UrlExperimentalAttributes import sttp.client4.listener.{ListenerBackend, RequestListener} import sttp.client4._ import sttp.model.{HttpVersion, ResponseMetadata, StatusCode} diff --git a/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/UrlExperimentalAttributes.scala b/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/UrlExperimentalAttributes.scala new file mode 100644 index 000000000..80cef3da3 --- /dev/null +++ b/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/UrlExperimentalAttributes.scala @@ -0,0 +1,9 @@ +package sttp.client4.opentelemetry.otel4s + +import org.typelevel.otel4s.AttributeKey + +private object UrlExperimentalAttributes { + // url.template is still experimental, so we need to wait for it to be stable before pulling it from the otel4s semconv + val UrlTemplate: AttributeKey[String] = + AttributeKey("url.template") +} diff --git a/observability/otel4s-metrics-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackendTest.scala b/observability/otel4s-metrics-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackendTest.scala index a944194a3..3658db950 100644 --- a/observability/otel4s-metrics-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackendTest.scala +++ b/observability/otel4s-metrics-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackendTest.scala @@ -1,14 +1,14 @@ package sttp.client4.opentelemetry.otel4s import cats.effect.IO -import cats.effect.unsafe.IORuntime import cats.effect.unsafe.implicits.global -import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.freespec.AsyncFreeSpec import org.scalatest.matchers.should.Matchers import org.typelevel.otel4s.metrics.MeterProvider import org.typelevel.otel4s.sdk.metrics.data.MetricData +import org.typelevel.otel4s.sdk.testkit.metrics.{MetricExpectation, MetricExpectations} import org.typelevel.otel4s.sdk.testkit.metrics.MetricsTestkit +import org.typelevel.otel4s.semconv.metrics.HttpMetrics import org.typelevel.otel4s.semconv.experimental.metrics.HttpExperimentalMetrics import org.typelevel.otel4s.semconv.{MetricSpec, Requirement} import sttp.model.{Header, StatusCode} @@ -26,7 +26,7 @@ class Otel4sMetricsBackendTest extends AsyncFreeSpec with Matchers { "Otel4sMetricsBackend" - { "should pass the client semantic test" in { val specs = List( - HttpExperimentalMetrics.ClientRequestDuration, + HttpMetrics.ClientRequestDuration, HttpExperimentalMetrics.ClientRequestBodySize, HttpExperimentalMetrics.ClientResponseBodySize, HttpExperimentalMetrics.ClientActiveRequests @@ -50,11 +50,11 @@ class Otel4sMetricsBackendTest extends AsyncFreeSpec with Matchers { makeBackend.use { backend => for { - r <- backend.send(basicRequest.post(uri"http://localhost:8080/success").body("payload")) + _ <- backend.send(basicRequest.post(uri"http://localhost:8080/success").body("payload")) // we use `.unsafeRunAndForget()` in the backend and JS could be slow _ <- IO.sleep(1.second) metrics <- testkit.collectMetrics - _ = specs.foreach(spec => specTest(metrics, spec)) + _ = assertMetricsMatch(metrics, specs.map(metricExpectation)) } yield succeed } } @@ -62,29 +62,30 @@ class Otel4sMetricsBackendTest extends AsyncFreeSpec with Matchers { } } - 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(", ")}]" - ) + private def metricExpectation(spec: MetricSpec): MetricExpectation = { + val required = spec.attributeSpecs + .filter(_.requirement.level == Requirement.Level.Required) + .map(_.key) + .toSet - metric.foreach { md => - md.name shouldBe spec.name - md.description shouldBe Some(spec.description) - md.unit shouldBe Some(spec.unit) - - 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 + MetricExpectation + .name(spec.name) + .description(spec.description) + .unit(spec.unit) + .clue(spec.name) + .where("required semantic-convention attributes are present") { metric => + metric.data.points.iterator + .flatMap(_.attributes.iterator.map(_.key)) + .filter(required.contains) + .toSet == required + } + } - current shouldBe required + private def assertMetricsMatch(metrics: List[MetricData], expectations: List[MetricExpectation]): Unit = + MetricExpectations.checkAllDistinct(metrics, expectations) match { + case Right(_) => + () + case Left(mismatches) => + fail(MetricExpectations.format(mismatches)) } - } } diff --git a/observability/otel4s-tracing-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackendTest.scala b/observability/otel4s-tracing-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackendTest.scala index 3e354250b..df3094035 100644 --- a/observability/otel4s-tracing-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackendTest.scala +++ b/observability/otel4s-tracing-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackendTest.scala @@ -22,10 +22,11 @@ import cats.effect.unsafe.implicits.global import org.scalatest.freespec.AsyncFreeSpec import org.scalatest.matchers.should.Matchers import org.typelevel.otel4s.sdk.data.LimitedData +import org.typelevel.otel4s.sdk.testkit.trace._ import org.typelevel.otel4s.sdk.testkit.trace.TracesTestkit import org.typelevel.otel4s.sdk.trace.context.propagation.W3CTraceContextPropagator -import org.typelevel.otel4s.sdk.trace.data.{EventData, StatusData} -import org.typelevel.otel4s.trace.{StatusCode, TracerProvider} +import org.typelevel.otel4s.sdk.trace.data.{EventData, SpanData} +import org.typelevel.otel4s.trace.TracerProvider import org.typelevel.otel4s.{Attribute, Attributes} import sttp.client4._ import sttp.client4.impl.cats.CatsMonadAsyncError @@ -86,8 +87,6 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers { response <- backend.send(basicRequest.get(uri"http://user:pwd@localhost:8080/success?q=v")) spans <- testkit.finishedSpans } yield { - val status = StatusData(StatusCode.Unset) - val attributes = Attributes( Attribute("http.request.method", "GET"), Attribute("http.response.status_code", 200L), @@ -99,9 +98,19 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers { response.code shouldBe HttpStatusCode.Ok - spans.map(_.attributes.elements) shouldBe List(attributes) - spans.map(_.events.elements) shouldBe List(Vector.empty) - spans.map(_.status) shouldBe List(status) + assertSpansMatch( + spans, + TraceForestExpectation.ordered( + TraceExpectation.leaf( + SpanExpectation + .client("GET") + .noParentSpanContext + .attributesExact(attributes) + .status(StatusExpectation.unset) + .eventCount(0) + ) + ) + ) succeed } @@ -130,8 +139,6 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers { response <- backend.send(basicRequest.get(uri"http://user@localhost:8080/bad-request?q=v")) spans <- testkit.finishedSpans } yield { - val status = StatusData(StatusCode.Error) - val attributes = Attributes( Attribute("http.request.method", "GET"), Attribute("http.response.status_code", 400L), @@ -144,9 +151,19 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers { response.code shouldBe HttpStatusCode.BadRequest - spans.map(_.attributes.elements) shouldBe List(attributes) - spans.map(_.events.elements) shouldBe List(Vector.empty) - spans.map(_.status) shouldBe List(status) + assertSpansMatch( + spans, + TraceForestExpectation.ordered( + TraceExpectation.leaf( + SpanExpectation + .client("GET") + .noParentSpanContext + .attributesExact(attributes) + .status(StatusExpectation.error) + .eventCount(0) + ) + ) + ) succeed } @@ -179,8 +196,6 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers { response <- backend.send(basicRequest.get(uri"http://localhost/error")).attempt spans <- testkit.finishedSpans } yield { - val status = StatusData(StatusCode.Error) - val attributes = Attributes( Attribute("http.request.method", "GET"), Attribute("server.address", "localhost"), @@ -197,9 +212,21 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers { response shouldBe Left(Err) - spans.map(_.attributes.elements) shouldBe List(attributes) - spans.map(_.events.elements) shouldBe List(Vector(event)) - spans.map(_.status) shouldBe List(status) + assertSpansMatch( + spans, + TraceForestExpectation.ordered( + TraceExpectation.leaf( + SpanExpectation + .client("GET") + .noParentSpanContext + .attributesExact(attributes) + .status(StatusExpectation.error) + .exactlyEvents( + EventExpectation.any.where("matches the recorded exception event")(_ == event) + ) + ) + ) + ) succeed } @@ -209,4 +236,12 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers { } } + private def assertSpansMatch(spans: List[SpanData], expectation: TraceForestExpectation): Unit = + TraceExpectations.check(spans, expectation) match { + case Right(_) => + () + case Left(mismatches) => + fail(TraceExpectations.format(mismatches)) + } + } From e77c05e9a3fdc92bf5ab86353d760e38ef1427aa Mon Sep 17 00:00:00 2001 From: Maksym Ochenashko Date: Sat, 11 Apr 2026 12:51:16 +0100 Subject: [PATCH 2/5] CurlCatsBackend: do not override R type --- .../scalanative/sttp/client4/curl/cats/CurlCatsBackend.scala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/effects/cats/src/main/scalanative/sttp/client4/curl/cats/CurlCatsBackend.scala b/effects/cats/src/main/scalanative/sttp/client4/curl/cats/CurlCatsBackend.scala index f5dbf1d3a..ce5203c3d 100644 --- a/effects/cats/src/main/scalanative/sttp/client4/curl/cats/CurlCatsBackend.scala +++ b/effects/cats/src/main/scalanative/sttp/client4/curl/cats/CurlCatsBackend.scala @@ -1,7 +1,6 @@ package sttp.client4.curl.cats import cats.effect.kernel.Sync -import sttp.capabilities.Effect import sttp.client4.curl.AbstractSyncCurlBackend import sttp.client4.impl.cats.CatsMonadError import sttp.client4.wrappers.FollowRedirectsBackend @@ -9,9 +8,7 @@ import sttp.client4.Backend class CurlCatsBackend[F[_]: Sync] private (verbose: Boolean) extends AbstractSyncCurlBackend[F](new CatsMonadError[F], verbose) - with Backend[F] { - override type R = Effect[F] -} + with Backend[F] object CurlCatsBackend { From c3787762d6c7396f867b89594d2ee2b0926a54ee Mon Sep 17 00:00:00 2001 From: Maksym Ochenashko Date: Sat, 11 Apr 2026 19:13:11 +0100 Subject: [PATCH 3/5] Scala Native: add ExecutionContext to the AsyncFreeSpec --- .../scalanative/org/scalatest/freespec/AsyncFreeSpec.scala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/test/scalanative/org/scalatest/freespec/AsyncFreeSpec.scala b/core/src/test/scalanative/org/scalatest/freespec/AsyncFreeSpec.scala index e06880879..19b80ca33 100644 --- a/core/src/test/scalanative/org/scalatest/freespec/AsyncFreeSpec.scala +++ b/core/src/test/scalanative/org/scalatest/freespec/AsyncFreeSpec.scala @@ -1,4 +1,8 @@ package org.scalatest.freespec +import scala.concurrent.ExecutionContext + // added only to make the tests compile, since it's used in shared tests -trait AsyncFreeSpec extends AnyFreeSpec +trait AsyncFreeSpec extends AnyFreeSpec { + def executionContext: ExecutionContext = ExecutionContext.global +} From 34800be36eac140266f254170b386d0eb09a4c29 Mon Sep 17 00:00:00 2001 From: Maksym Ochenashko Date: Sat, 11 Apr 2026 19:17:31 +0100 Subject: [PATCH 4/5] Return assertion --- .../otel4s/Otel4sMetricsBackendTest.scala | 7 +++---- .../otel4s/Otel4sTracingBackendTest.scala | 10 ++-------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/observability/otel4s-metrics-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackendTest.scala b/observability/otel4s-metrics-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackendTest.scala index 3658db950..4489b4052 100644 --- a/observability/otel4s-metrics-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackendTest.scala +++ b/observability/otel4s-metrics-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackendTest.scala @@ -54,8 +54,7 @@ class Otel4sMetricsBackendTest extends AsyncFreeSpec with Matchers { // we use `.unsafeRunAndForget()` in the backend and JS could be slow _ <- IO.sleep(1.second) metrics <- testkit.collectMetrics - _ = assertMetricsMatch(metrics, specs.map(metricExpectation)) - } yield succeed + } yield assertMetricsMatch(metrics, specs.map(metricExpectation)) } } .unsafeToFuture() @@ -81,10 +80,10 @@ class Otel4sMetricsBackendTest extends AsyncFreeSpec with Matchers { } } - private def assertMetricsMatch(metrics: List[MetricData], expectations: List[MetricExpectation]): Unit = + private def assertMetricsMatch(metrics: List[MetricData], expectations: List[MetricExpectation]) = MetricExpectations.checkAllDistinct(metrics, expectations) match { case Right(_) => - () + succeed case Left(mismatches) => fail(MetricExpectations.format(mismatches)) } diff --git a/observability/otel4s-tracing-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackendTest.scala b/observability/otel4s-tracing-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackendTest.scala index df3094035..43f2fa22e 100644 --- a/observability/otel4s-tracing-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackendTest.scala +++ b/observability/otel4s-tracing-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackendTest.scala @@ -111,8 +111,6 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers { ) ) ) - - succeed } } .unsafeToFuture() @@ -164,8 +162,6 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers { ) ) ) - - succeed } } .unsafeToFuture() @@ -227,8 +223,6 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers { ) ) ) - - succeed } } } @@ -236,10 +230,10 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers { } } - private def assertSpansMatch(spans: List[SpanData], expectation: TraceForestExpectation): Unit = + private def assertSpansMatch(spans: List[SpanData], expectation: TraceForestExpectation) = TraceExpectations.check(spans, expectation) match { case Right(_) => - () + succeed case Left(mismatches) => fail(TraceExpectations.format(mismatches)) } From 9db773ec58d40c11cfe75ea75cdab0e83b4f2fb8 Mon Sep 17 00:00:00 2001 From: Maksym Ochenashko Date: Sat, 11 Apr 2026 19:34:46 +0100 Subject: [PATCH 5/5] Add AsyncExecutionContext for every platform --- .../org/scalatest/freespec/AsyncFreeSpec.scala | 6 +----- .../opentelemetry/otel4s/Otel4sMetricsBackendTest.scala | 5 +---- .../opentelemetry/otel4s/AsyncExecutionContext.scala | 9 +++++++++ .../opentelemetry/otel4s/AsyncExecutionContext.scala | 3 +++ .../opentelemetry/otel4s/AsyncExecutionContext.scala | 3 +++ .../opentelemetry/otel4s/Otel4sTracingBackendTest.scala | 6 +----- .../opentelemetry/otel4s/AsyncExecutionContext.scala | 9 +++++++++ .../opentelemetry/otel4s/AsyncExecutionContext.scala | 3 +++ .../opentelemetry/otel4s/AsyncExecutionContext.scala | 3 +++ 9 files changed, 33 insertions(+), 14 deletions(-) create mode 100644 observability/otel4s-metrics-backend/src/test/scalajs/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala create mode 100644 observability/otel4s-metrics-backend/src/test/scalajvm/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala create mode 100644 observability/otel4s-metrics-backend/src/test/scalanative/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala create mode 100644 observability/otel4s-tracing-backend/src/test/scalajs/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala create mode 100644 observability/otel4s-tracing-backend/src/test/scalajvm/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala create mode 100644 observability/otel4s-tracing-backend/src/test/scalanative/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala diff --git a/core/src/test/scalanative/org/scalatest/freespec/AsyncFreeSpec.scala b/core/src/test/scalanative/org/scalatest/freespec/AsyncFreeSpec.scala index 19b80ca33..e06880879 100644 --- a/core/src/test/scalanative/org/scalatest/freespec/AsyncFreeSpec.scala +++ b/core/src/test/scalanative/org/scalatest/freespec/AsyncFreeSpec.scala @@ -1,8 +1,4 @@ package org.scalatest.freespec -import scala.concurrent.ExecutionContext - // added only to make the tests compile, since it's used in shared tests -trait AsyncFreeSpec extends AnyFreeSpec { - def executionContext: ExecutionContext = ExecutionContext.global -} +trait AsyncFreeSpec extends AnyFreeSpec diff --git a/observability/otel4s-metrics-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackendTest.scala b/observability/otel4s-metrics-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackendTest.scala index 4489b4052..466afbded 100644 --- a/observability/otel4s-metrics-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackendTest.scala +++ b/observability/otel4s-metrics-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackendTest.scala @@ -16,12 +16,9 @@ import sttp.client4._ import sttp.client4.impl.cats.CatsMonadAsyncError import sttp.client4.testing.{BackendStub, ResponseStub, StubBody} -import scala.concurrent.ExecutionContext import scala.concurrent.duration._ -class Otel4sMetricsBackendTest extends AsyncFreeSpec with Matchers { - - override def executionContext: ExecutionContext = ExecutionContext.global +class Otel4sMetricsBackendTest extends AsyncFreeSpec with Matchers with AsyncExecutionContext { "Otel4sMetricsBackend" - { "should pass the client semantic test" in { diff --git a/observability/otel4s-metrics-backend/src/test/scalajs/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala b/observability/otel4s-metrics-backend/src/test/scalajs/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala new file mode 100644 index 000000000..5c7557c66 --- /dev/null +++ b/observability/otel4s-metrics-backend/src/test/scalajs/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala @@ -0,0 +1,9 @@ +package sttp.client4.opentelemetry.otel4s + +import org.scalatest.AsyncTestSuite + +import scala.concurrent.ExecutionContext + +trait AsyncExecutionContext { self: AsyncTestSuite => + override def executionContext: ExecutionContext = ExecutionContext.global +} diff --git a/observability/otel4s-metrics-backend/src/test/scalajvm/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala b/observability/otel4s-metrics-backend/src/test/scalajvm/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala new file mode 100644 index 000000000..141199e53 --- /dev/null +++ b/observability/otel4s-metrics-backend/src/test/scalajvm/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala @@ -0,0 +1,3 @@ +package sttp.client4.opentelemetry.otel4s + +trait AsyncExecutionContext {} diff --git a/observability/otel4s-metrics-backend/src/test/scalanative/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala b/observability/otel4s-metrics-backend/src/test/scalanative/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala new file mode 100644 index 000000000..141199e53 --- /dev/null +++ b/observability/otel4s-metrics-backend/src/test/scalanative/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala @@ -0,0 +1,3 @@ +package sttp.client4.opentelemetry.otel4s + +trait AsyncExecutionContext {} diff --git a/observability/otel4s-tracing-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackendTest.scala b/observability/otel4s-tracing-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackendTest.scala index 43f2fa22e..9ff008c7e 100644 --- a/observability/otel4s-tracing-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackendTest.scala +++ b/observability/otel4s-tracing-backend/src/test/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackendTest.scala @@ -23,7 +23,6 @@ import org.scalatest.freespec.AsyncFreeSpec import org.scalatest.matchers.should.Matchers import org.typelevel.otel4s.sdk.data.LimitedData import org.typelevel.otel4s.sdk.testkit.trace._ -import org.typelevel.otel4s.sdk.testkit.trace.TracesTestkit import org.typelevel.otel4s.sdk.trace.context.propagation.W3CTraceContextPropagator import org.typelevel.otel4s.sdk.trace.data.{EventData, SpanData} import org.typelevel.otel4s.trace.TracerProvider @@ -33,13 +32,10 @@ import sttp.client4.impl.cats.CatsMonadAsyncError import sttp.client4.testing.{BackendStub, ResponseStub, StubBody} import sttp.model.{StatusCode => HttpStatusCode} -import scala.concurrent.ExecutionContext import scala.concurrent.duration.Duration import scala.util.control.NoStackTrace -class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers { - - override def executionContext: ExecutionContext = ExecutionContext.global +class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers with AsyncExecutionContext { "Otel4sTracingBackend" - { "should add tracing headers to the request" in { diff --git a/observability/otel4s-tracing-backend/src/test/scalajs/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala b/observability/otel4s-tracing-backend/src/test/scalajs/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala new file mode 100644 index 000000000..5c7557c66 --- /dev/null +++ b/observability/otel4s-tracing-backend/src/test/scalajs/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala @@ -0,0 +1,9 @@ +package sttp.client4.opentelemetry.otel4s + +import org.scalatest.AsyncTestSuite + +import scala.concurrent.ExecutionContext + +trait AsyncExecutionContext { self: AsyncTestSuite => + override def executionContext: ExecutionContext = ExecutionContext.global +} diff --git a/observability/otel4s-tracing-backend/src/test/scalajvm/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala b/observability/otel4s-tracing-backend/src/test/scalajvm/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala new file mode 100644 index 000000000..141199e53 --- /dev/null +++ b/observability/otel4s-tracing-backend/src/test/scalajvm/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala @@ -0,0 +1,3 @@ +package sttp.client4.opentelemetry.otel4s + +trait AsyncExecutionContext {} diff --git a/observability/otel4s-tracing-backend/src/test/scalanative/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala b/observability/otel4s-tracing-backend/src/test/scalanative/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala new file mode 100644 index 000000000..141199e53 --- /dev/null +++ b/observability/otel4s-tracing-backend/src/test/scalanative/sttp/client4/opentelemetry/otel4s/AsyncExecutionContext.scala @@ -0,0 +1,3 @@ +package sttp.client4.opentelemetry.otel4s + +trait AsyncExecutionContext {}