diff --git a/.github/scripts/check-latest-dep-test-overrides.sh b/.github/scripts/check-latest-dep-test-overrides.sh index 1a765540c65a..21d6a6acfe78 100755 --- a/.github/scripts/check-latest-dep-test-overrides.sh +++ b/.github/scripts/check-latest-dep-test-overrides.sh @@ -3,7 +3,7 @@ # all missing version coverage should be documented in supported-libraries.md if grep -r --include build.gradle.kts latestDepTestLibrary instrumentation \ - | grep -v :+\" \ + | grep -v -e :+\" -e :latest.release\" \ | grep -v "// see .* module" \ | grep -v "// see test suite below" \ | grep -v "// no longer applicable" \ diff --git a/instrumentation/pekko/pekko-http-1.0/javaagent/build.gradle.kts b/instrumentation/pekko/pekko-http-1.0/javaagent/build.gradle.kts index ef16fe96e1e2..9567d8641157 100644 --- a/instrumentation/pekko/pekko-http-1.0/javaagent/build.gradle.kts +++ b/instrumentation/pekko/pekko-http-1.0/javaagent/build.gradle.kts @@ -31,11 +31,14 @@ dependencies { library("org.apache.pekko:pekko-http_2.12:1.0.0") library("org.apache.pekko:pekko-stream_2.12:1.0.1") + testImplementation("com.softwaremill.sttp.tapir:tapir-pekko-http-server_2.12:1.7.0") + testInstrumentation(project(":instrumentation:pekko:pekko-actor-1.0:javaagent")) testInstrumentation(project(":instrumentation:executors:javaagent")) - latestDepTestLibrary("org.apache.pekko:pekko-http_2.13:+") - latestDepTestLibrary("org.apache.pekko:pekko-stream_2.13:+") + latestDepTestLibrary("org.apache.pekko:pekko-http_2.13:latest.release") + latestDepTestLibrary("org.apache.pekko:pekko-stream_2.13:latest.release") + latestDepTestLibrary("com.softwaremill.sttp.tapir:tapir-pekko-http-server_2.13:latest.release") } tasks { @@ -56,6 +59,7 @@ if (findProperty("testLatestDeps") as Boolean) { testImplementation { exclude("org.apache.pekko", "pekko-http_2.12") exclude("org.apache.pekko", "pekko-stream_2.12") + exclude("com.softwaremill.sttp.tapir", "tapir-pekko-http-server_2.12") } } } diff --git a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/RestoreOnExit.java b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/RestoreOnExit.java new file mode 100644 index 000000000000..5c540db1da48 --- /dev/null +++ b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/RestoreOnExit.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.pekkohttp.v1_0.server.route; + +import org.apache.pekko.http.scaladsl.server.RouteResult; +import scala.PartialFunction; +import scala.Unit; +import scala.util.Try; + +public class RestoreOnExit implements PartialFunction, Unit> { + @Override + public boolean isDefinedAt(Try x) { + return true; + } + + @Override + public Unit apply(Try v1) { + PekkoRouteHolder.restore(); + return null; + } +} diff --git a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/RouteConcatenationInstrumentation.java b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/RouteConcatenationInstrumentation.java index 9a00975e6b8f..d5cf83d6ab9d 100644 --- a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/RouteConcatenationInstrumentation.java +++ b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/RouteConcatenationInstrumentation.java @@ -12,6 +12,9 @@ import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.apache.pekko.http.scaladsl.server.RequestContext; +import org.apache.pekko.http.scaladsl.server.RouteResult; +import scala.concurrent.Future; public class RouteConcatenationInstrumentation implements TypeInstrumentation { @Override @@ -39,8 +42,15 @@ public static void onEnter() { } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit() { - PekkoRouteHolder.restore(); + public static void onExit( + @Advice.Argument(value = 2) RequestContext ctx, + @Advice.Return(readOnly = false) Future future, + @Advice.Thrown Throwable throwable) { + if (throwable != null) { + PekkoRouteHolder.restore(); + } else { + future = future.andThen(new RestoreOnExit(), ctx.executionContext()); + } } } diff --git a/instrumentation/pekko/pekko-http-1.0/javaagent/src/test/scala/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/PekkoHttpServerRouteTest.scala b/instrumentation/pekko/pekko-http-1.0/javaagent/src/test/scala/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/PekkoHttpServerRouteTest.scala index cbaaa797042e..a1bb40627002 100644 --- a/instrumentation/pekko/pekko-http-1.0/javaagent/src/test/scala/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/PekkoHttpServerRouteTest.scala +++ b/instrumentation/pekko/pekko-http-1.0/javaagent/src/test/scala/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/PekkoHttpServerRouteTest.scala @@ -31,8 +31,10 @@ import org.junit.jupiter.api.{AfterAll, Test, TestInstance} import java.net.{URI, URISyntaxException} import java.util.function.Consumer -import scala.concurrent.Await +import scala.concurrent.{Await, ExecutionContext, Future} import scala.concurrent.duration.DurationInt +import sttp.tapir._ +import sttp.tapir.server.pekkohttp.PekkoHttpServerInterpreter @TestInstance(TestInstance.Lifecycle.PER_CLASS) class PekkoHttpServerRouteTest { @@ -77,6 +79,26 @@ class PekkoHttpServerRouteTest { test(route, "/test/1", "GET /test/*") } + @Test def testTapirRoutes(): Unit = { + val interpreter = PekkoHttpServerInterpreter()(system.dispatcher) + def makeRoute(input: EndpointInput[Unit]) = { + interpreter.toRoute( + endpoint.get + .in(input) + .errorOut(stringBody) + .out(stringBody) + .serverLogicPure[Future](_ => Right("ok")) + ) + } + + val routes = concat( + concat(makeRoute("test" / "1"), makeRoute("test" / "2")), + concat(makeRoute("test" / "3"), makeRoute("test" / "4")) + ) + + test(routes, "/test/4", "GET") + } + def test(route: Route, path: String, spanName: String): Unit = { val port = PortUtils.findOpenPort val address: URI = buildAddress(port)