Ensure tilde$1 onExit is run in correct order (#13360)

This commit is contained in:
Mason Lazalier Edmison 2025-02-25 19:07:00 -06:00 committed by GitHub
parent f5a0d2f771
commit f0d80b2e55
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 66 additions and 6 deletions

View File

@ -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" \

View File

@ -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")
}
}
}

View File

@ -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<Try<RouteResult>, Unit> {
@Override
public boolean isDefinedAt(Try<RouteResult> x) {
return true;
}
@Override
public Unit apply(Try<RouteResult> v1) {
PekkoRouteHolder.restore();
return null;
}
}

View File

@ -12,6 +12,9 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
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 class RouteConcatenationInstrumentation implements TypeInstrumentation {
}
@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<RouteResult> future,
@Advice.Thrown Throwable throwable) {
if (throwable != null) {
PekkoRouteHolder.restore();
} else {
future = future.andThen(new RestoreOnExit(), ctx.executionContext());
}
}
}

View File

@ -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)