Convert play-ws groovy to java (#12377)

Co-authored-by: Lauri Tulmin <ltulmin@splunk.com>
This commit is contained in:
Helen 2024-10-30 08:29:10 -07:00 committed by GitHub
parent 00de5e3016
commit 0b9dffaf98
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 1170 additions and 411 deletions

View File

@ -1,12 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
class PlayJavaWsClientTest extends PlayJavaWsClientTestBase {}
class PlayJavaStreamedWsClientTest extends PlayJavaStreamedWsClientTestBase {}
class PlayScalaWsClientTest extends PlayScalaWsClientTestBase {}
class PlayScalaStreamedWsClientTest extends PlayScalaStreamedWsClientTestBase {}

View File

@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v1_0;
import io.opentelemetry.javaagent.instrumentation.playws.PlayJavaStreamedWsClientBaseTest;
class PlayJavaStreamedWsClientTest extends PlayJavaStreamedWsClientBaseTest {}

View File

@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v1_0;
import io.opentelemetry.javaagent.instrumentation.playws.PlayJavaWsClientBaseTest;
class PlayJavaWsClientTest extends PlayJavaWsClientBaseTest {}

View File

@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v1_0;
import io.opentelemetry.javaagent.instrumentation.playws.PlayScalaStreamedWsClientBaseTest;
class PlayScalaStreamedWsClientTest extends PlayScalaStreamedWsClientBaseTest {}

View File

@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v1_0;
import io.opentelemetry.javaagent.instrumentation.playws.PlayScalaWsClientBaseTest;
class PlayScalaWsClientTest extends PlayScalaWsClientBaseTest {}

View File

@ -1,12 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
class PlayJavaWsClientTest extends PlayJavaWsClientTestBase {}
class PlayJavaStreamedWsClientTest extends PlayJavaStreamedWsClientTestBase {}
class PlayScalaWsClientTest extends PlayScalaWsClientTestBase {}
class PlayScalaStreamedWsClientTest extends PlayScalaStreamedWsClientTestBase {}

View File

@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v2_0;
import io.opentelemetry.javaagent.instrumentation.playws.PlayJavaStreamedWsClientBaseTest;
class PlayJavaStreamedWsClientTest extends PlayJavaStreamedWsClientBaseTest {}

View File

@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v2_0;
import io.opentelemetry.javaagent.instrumentation.playws.PlayJavaWsClientBaseTest;
class PlayJavaWsClientTest extends PlayJavaWsClientBaseTest {}

View File

@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v2_0;
import io.opentelemetry.javaagent.instrumentation.playws.PlayScalaStreamedWsClientBaseTest;
class PlayScalaStreamedWsClientTest extends PlayScalaStreamedWsClientBaseTest {}

View File

@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v2_0;
import io.opentelemetry.javaagent.instrumentation.playws.PlayScalaWsClientBaseTest;
class PlayScalaWsClientTest extends PlayScalaWsClientBaseTest {}

View File

@ -41,15 +41,33 @@ dependencies {
testInstrumentation(project(":instrumentation:netty:netty-4.1:javaagent")) testInstrumentation(project(":instrumentation:netty:netty-4.1:javaagent"))
testInstrumentation(project(":instrumentation:akka:akka-http-10.0:javaagent")) testInstrumentation(project(":instrumentation:akka:akka-http-10.0:javaagent"))
testInstrumentation(project(":instrumentation:akka:akka-actor-2.3:javaagent")) testInstrumentation(project(":instrumentation:akka:akka-actor-2.3:javaagent"))
latestDepTestLibrary("com.typesafe.play:play-ahc-ws-standalone_2.13:+")
} }
if (findProperty("testLatestDeps") as Boolean) { val testLatestDeps = findProperty("testLatestDeps") as Boolean
configurations {
// play-ws artifact name is different for regular and latest tests testing {
testImplementation { suites {
exclude("com.typesafe.play", "play-ahc-ws-standalone_$scalaVersion") val latestDepTest by registering(JvmTestSuite::class) {
dependencies {
implementation("com.typesafe.play:play-ahc-ws-standalone_2.13:+")
}
} }
} }
} }
tasks {
if (testLatestDeps) {
// disable regular test running and compiling tasks when latest dep test task is run
named("test") {
enabled = false
}
}
named("latestDepTest") {
enabled = testLatestDeps
}
check {
dependsOn(testing.suites)
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v2_1;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import play.libs.ws.StandaloneWSClient;
import play.libs.ws.StandaloneWSRequest;
import play.libs.ws.StandaloneWSResponse;
import play.libs.ws.ahc.StandaloneAhcWSClient;
class PlayJavaStreamedWsClientTest extends PlayWsClientBaseTest<StandaloneWSRequest> {
private static StandaloneWSClient wsClient;
private static StandaloneWSClient wsClientWithReadTimeout;
@BeforeAll
static void setup() {
wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer);
wsClientWithReadTimeout =
new StandaloneAhcWSClient(asyncHttpClientWithReadTimeout, materializer);
}
@AfterAll
static void cleanup() throws IOException {
wsClient.close();
wsClientWithReadTimeout.close();
}
@Override
public StandaloneWSRequest buildRequest(String method, URI uri, Map<String, String> headers) {
StandaloneWSRequest request = getClient(uri).url(uri.toString()).setFollowRedirects(true);
headers.forEach(request::addHeader);
request.setMethod(method);
return request;
}
@Override
public int sendRequest(
StandaloneWSRequest request, String method, URI uri, Map<String, String> headers)
throws ExecutionException, InterruptedException {
return internalSendRequest(request).toCompletableFuture().get().getStatus();
}
@Override
public void sendRequestWithCallback(
StandaloneWSRequest request,
String method,
URI uri,
Map<String, String> headers,
HttpClientResult requestResult) {
internalSendRequest(request)
.whenComplete(
(response, throwable) -> {
if (throwable != null) {
requestResult.complete(throwable.getCause());
} else {
requestResult.complete(response.getStatus());
}
});
}
private static CompletionStage<StandaloneWSResponse> internalSendRequest(
StandaloneWSRequest request) {
CompletionStage<? extends StandaloneWSResponse> stream = request.stream();
// The status can be ready before the body so explicitly call wait for body to be ready
return stream
.thenCompose(
response -> response.getBodyAsSource().runFold("", (acc, out) -> "", materializer))
.thenCombine(stream, (body, response) -> response);
}
private static StandaloneWSClient getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return wsClientWithReadTimeout;
}
return wsClient;
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v2_1;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import play.libs.ws.StandaloneWSClient;
import play.libs.ws.StandaloneWSRequest;
import play.libs.ws.ahc.StandaloneAhcWSClient;
class PlayJavaWsClientTest extends PlayWsClientBaseTest<StandaloneWSRequest> {
private static StandaloneWSClient wsClient;
private static StandaloneWSClient wsClientWithReadTimeout;
@BeforeAll
static void setup() {
wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer);
wsClientWithReadTimeout =
new StandaloneAhcWSClient(asyncHttpClientWithReadTimeout, materializer);
}
@AfterAll
static void cleanup() throws IOException {
wsClient.close();
wsClientWithReadTimeout.close();
}
@Override
public StandaloneWSRequest buildRequest(String method, URI uri, Map<String, String> headers) {
StandaloneWSRequest request = getClient(uri).url(uri.toString()).setFollowRedirects(true);
headers.forEach(request::addHeader);
return request.setMethod(method);
}
@Override
public int sendRequest(
StandaloneWSRequest request, String method, URI uri, Map<String, String> headers)
throws ExecutionException, InterruptedException {
return request.execute().toCompletableFuture().get().getStatus();
}
@Override
public void sendRequestWithCallback(
StandaloneWSRequest request,
String method,
URI uri,
Map<String, String> headers,
HttpClientResult requestResult) {
request
.execute()
.whenComplete(
(response, throwable) -> {
if (throwable != null) {
requestResult.complete(throwable);
} else {
requestResult.complete(response.getStatus());
}
});
}
private static StandaloneWSClient getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return wsClientWithReadTimeout;
}
return wsClient;
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v2_1;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import play.api.libs.ws.StandaloneWSClient;
import play.api.libs.ws.StandaloneWSRequest;
import play.api.libs.ws.StandaloneWSResponse;
import play.api.libs.ws.ahc.StandaloneAhcWSClient;
import scala.Function1;
import scala.concurrent.Await;
import scala.concurrent.ExecutionContext;
import scala.concurrent.Future;
import scala.concurrent.duration.Duration;
import scala.jdk.javaapi.CollectionConverters;
import scala.util.Try;
class PlayScalaStreamedWsClientTest extends PlayWsClientBaseTest<StandaloneWSRequest> {
private static StandaloneWSClient wsClient;
private static StandaloneWSClient wsClientWithReadTimeout;
@BeforeAll
void setup() {
wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer);
wsClientWithReadTimeout =
new StandaloneAhcWSClient(asyncHttpClientWithReadTimeout, materializer);
}
@AfterAll
static void cleanup() throws IOException {
wsClient.close();
wsClientWithReadTimeout.close();
}
@Override
public StandaloneWSRequest buildRequest(String method, URI uri, Map<String, String> headers)
throws Exception {
return getClient(uri)
.url(uri.toURL().toString())
.withMethod(method)
.withFollowRedirects(true)
.withHttpHeaders(CollectionConverters.asScala(headers).toList());
}
@Override
public int sendRequest(
StandaloneWSRequest request, String method, URI uri, Map<String, String> headers)
throws Exception {
return Await.result(internalSendRequest(request), Duration.apply(10, TimeUnit.SECONDS))
.status();
}
@Override
public void sendRequestWithCallback(
StandaloneWSRequest request,
String method,
URI uri,
Map<String, String> headers,
HttpClientResult requestResult) {
internalSendRequest(request)
.onComplete(
new Function1<Try<StandaloneWSResponse>, Void>() {
@Override
public Void apply(Try<StandaloneWSResponse> response) {
if (response.isSuccess()) {
requestResult.complete(response.get().status());
} else {
requestResult.complete(response.failed().get());
}
return null;
}
},
ExecutionContext.global());
}
private static Future<StandaloneWSResponse> internalSendRequest(StandaloneWSRequest request) {
Future<StandaloneWSResponse> futureResponse = request.stream();
// The status can be ready before the body so explicitly call wait for body to be ready
Future<String> bodyResponse =
futureResponse.flatMap(
new Function1<StandaloneWSResponse, Future<String>>() {
@Override
public Future<String> apply(StandaloneWSResponse wsResponse) {
return wsResponse.bodyAsSource().runFold("", (acc, out) -> "", materializer);
}
},
ExecutionContext.global());
return bodyResponse.flatMap(
new Function1<String, Future<StandaloneWSResponse>>() {
@Override
public Future<StandaloneWSResponse> apply(String v1) {
return futureResponse;
}
},
ExecutionContext.global());
}
private static StandaloneWSClient getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return wsClientWithReadTimeout;
}
return wsClient;
}
}

View File

@ -0,0 +1,100 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v2_1;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import play.api.libs.ws.StandaloneWSClient;
import play.api.libs.ws.StandaloneWSRequest;
import play.api.libs.ws.StandaloneWSResponse;
import play.api.libs.ws.ahc.StandaloneAhcWSClient;
import scala.Function1;
import scala.concurrent.Await;
import scala.concurrent.ExecutionContext;
import scala.concurrent.Future;
import scala.concurrent.duration.Duration;
import scala.jdk.javaapi.CollectionConverters;
import scala.util.Try;
class PlayScalaWsClientTest extends PlayWsClientBaseTest<StandaloneWSRequest> {
private static StandaloneWSClient wsClient;
private static StandaloneWSClient wsClientWithReadTimeout;
@BeforeAll
void setup() {
wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer);
wsClientWithReadTimeout =
new StandaloneAhcWSClient(asyncHttpClientWithReadTimeout, materializer);
}
@AfterAll
static void cleanup() throws IOException {
wsClient.close();
wsClientWithReadTimeout.close();
}
@Override
public StandaloneWSRequest buildRequest(String method, URI uri, Map<String, String> headers)
throws MalformedURLException {
return getClient(uri)
.url(uri.toURL().toString())
.withMethod(method)
.withFollowRedirects(true)
.withHttpHeaders(CollectionConverters.asScala(headers).toSeq());
}
@Override
public int sendRequest(
StandaloneWSRequest request, String method, URI uri, Map<String, String> headers)
throws Exception {
Future<StandaloneWSResponse> futureResponse = request.execute();
Await.ready(futureResponse, Duration.apply(10, TimeUnit.SECONDS));
Try<StandaloneWSResponse> value = futureResponse.value().get();
if (value.isSuccess()) {
return value.get().status();
}
// Catch the Throwable and rethrow it
throw (Exception) value.failed().get();
}
@Override
public void sendRequestWithCallback(
StandaloneWSRequest request,
String method,
URI uri,
Map<String, String> headers,
HttpClientResult requestResult) {
request
.execute()
.onComplete(
new Function1<Try<StandaloneWSResponse>, Void>() {
@Override
public Void apply(Try<StandaloneWSResponse> response) {
if (response.isSuccess()) {
requestResult.complete(response.get().status());
} else {
requestResult.complete(response.failed().get());
}
return null;
}
},
ExecutionContext.global());
}
private static StandaloneWSClient getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return wsClientWithReadTimeout;
}
return wsClient;
}
}

View File

@ -0,0 +1,133 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v2_1;
import akka.actor.ActorSystem;
import akka.stream.Materializer;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions;
import io.opentelemetry.semconv.NetworkAttributes;
import io.opentelemetry.semconv.ServerAttributes;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.extension.RegisterExtension;
import play.shaded.ahc.io.netty.resolver.InetNameResolver;
import play.shaded.ahc.io.netty.util.concurrent.EventExecutor;
import play.shaded.ahc.io.netty.util.concurrent.ImmediateEventExecutor;
import play.shaded.ahc.io.netty.util.concurrent.Promise;
import play.shaded.ahc.org.asynchttpclient.AsyncHttpClient;
import play.shaded.ahc.org.asynchttpclient.AsyncHttpClientConfig;
import play.shaded.ahc.org.asynchttpclient.DefaultAsyncHttpClient;
import play.shaded.ahc.org.asynchttpclient.DefaultAsyncHttpClientConfig;
import play.shaded.ahc.org.asynchttpclient.RequestBuilderBase;
abstract class PlayWsClientBaseTest<REQUEST> extends AbstractHttpClientTest<REQUEST> {
@RegisterExtension
static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent();
private static ActorSystem system;
protected static AsyncHttpClient asyncHttpClient;
protected static AsyncHttpClient asyncHttpClientWithReadTimeout;
protected static Materializer materializer;
@BeforeAll
static void setupHttpClient() {
String name = "play-ws";
system = ActorSystem.create(name);
materializer = Materializer.matFromSystem(system);
// Replace dns name resolver with custom implementation that returns only once address for each
// host. This is needed for "connection error dropped request" because in case of connection
// failure ahc will try the next address which isn't necessary for this test.
RequestBuilderBase.DEFAULT_NAME_RESOLVER =
new CustomNameResolver(ImmediateEventExecutor.INSTANCE);
asyncHttpClient = createClient(false);
asyncHttpClientWithReadTimeout = createClient(true);
}
@AfterAll
static void cleanupHttpClient() throws IOException {
asyncHttpClient.close();
asyncHttpClientWithReadTimeout.close();
system.terminate();
}
@Override
protected void configure(HttpClientTestOptions.Builder optionsBuilder) {
super.configure(optionsBuilder);
// apparently play ws does not report the 302 status code
optionsBuilder.setResponseCodeOnRedirectError(null);
optionsBuilder.setMaxRedirects(3);
optionsBuilder.spanEndsAfterBody();
optionsBuilder.setHttpAttributes(
uri -> {
Set<AttributeKey<?>> attributes =
new HashSet<>(HttpClientTestOptions.DEFAULT_HTTP_ATTRIBUTES);
attributes.remove(NetworkAttributes.NETWORK_PROTOCOL_VERSION);
if (uri.toString().endsWith("/circular-redirect")) {
attributes.remove(ServerAttributes.SERVER_ADDRESS);
attributes.remove(ServerAttributes.SERVER_PORT);
}
return attributes;
});
}
private static AsyncHttpClient createClient(boolean readTimeout) {
DefaultAsyncHttpClientConfig.Builder builder =
new DefaultAsyncHttpClientConfig.Builder()
.setMaxRequestRetry(0)
.setShutdownQuietPeriod(0)
.setShutdownTimeout(0)
.setMaxRedirects(3)
.setConnectTimeout(5000);
if (readTimeout) {
builder.setReadTimeout(2000);
}
AsyncHttpClientConfig asyncHttpClientConfig = builder.build();
return new DefaultAsyncHttpClient(asyncHttpClientConfig);
}
private static class CustomNameResolver extends InetNameResolver {
public CustomNameResolver(EventExecutor executor) {
super(executor);
}
@Override
protected void doResolve(String inetHost, Promise<InetAddress> promise) throws Exception {
try {
promise.setSuccess(InetAddress.getByName(inetHost));
} catch (UnknownHostException exception) {
promise.setFailure(exception);
}
}
@Override
protected void doResolveAll(String inetHost, Promise<List<InetAddress>> promise)
throws Exception {
try {
// default implementation calls InetAddress.getAllByName
promise.setSuccess(Collections.singletonList(InetAddress.getByName(inetHost)));
} catch (UnknownHostException exception) {
promise.setFailure(exception);
}
}
}
}

View File

@ -1,12 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
class PlayJavaWsClientTest extends PlayJavaWsClientTestBase {}
class PlayJavaStreamedWsClientTest extends PlayJavaStreamedWsClientTestBase {}
class PlayScalaWsClientTest extends PlayScalaWsClientTestBase {}
class PlayScalaStreamedWsClientTest extends PlayScalaStreamedWsClientTestBase {}

View File

@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v2_1;
import io.opentelemetry.javaagent.instrumentation.playws.PlayJavaStreamedWsClientBaseTest;
class PlayJavaStreamedWsClientTest extends PlayJavaStreamedWsClientBaseTest {}

View File

@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v2_1;
import io.opentelemetry.javaagent.instrumentation.playws.PlayJavaWsClientBaseTest;
class PlayJavaWsClientTest extends PlayJavaWsClientBaseTest {}

View File

@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v2_1;
import io.opentelemetry.javaagent.instrumentation.playws.PlayScalaStreamedWsClientBaseTest;
class PlayScalaStreamedWsClientTest extends PlayScalaStreamedWsClientBaseTest {}

View File

@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws.v2_1;
import io.opentelemetry.javaagent.instrumentation.playws.PlayScalaWsClientBaseTest;
class PlayScalaWsClientTest extends PlayScalaWsClientBaseTest {}

View File

@ -8,7 +8,5 @@ dependencies {
api(project(":testing-common")) api(project(":testing-common"))
api("com.typesafe.play:play-ahc-ws-standalone_$scalaVersion:1.0.2") api("com.typesafe.play:play-ahc-ws-standalone_$scalaVersion:1.0.2")
implementation("org.apache.groovy:groovy")
implementation("io.opentelemetry:opentelemetry-api") implementation("io.opentelemetry:opentelemetry-api")
implementation("org.spockframework:spock-core")
} }

View File

@ -1,247 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult
import play.libs.ws.StandaloneWSClient
import play.libs.ws.StandaloneWSRequest
import play.libs.ws.StandaloneWSResponse
import play.libs.ws.ahc.StandaloneAhcWSClient
import scala.Function1
import scala.collection.JavaConverters
import scala.concurrent.Await
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.concurrent.duration.Duration
import scala.util.Try
import spock.lang.Shared
import java.util.concurrent.CompletionStage
import java.util.concurrent.TimeUnit
class PlayJavaWsClientTestBase extends PlayWsClientTestBaseBase<StandaloneWSRequest> {
@Shared
StandaloneWSClient wsClient
@Shared
StandaloneWSClient wsClientWithReadTimeout
@Override
StandaloneWSRequest buildRequest(String method, URI uri, Map<String, String> headers) {
def request = getClient(uri).url(uri.toURL().toString()).setFollowRedirects(true)
headers.entrySet().each { entry -> request.addHeader(entry.getKey(), entry.getValue()) }
return request.setMethod(method)
}
@Override
int sendRequest(StandaloneWSRequest request, String method, URI uri, Map<String, String> headers) {
return request.execute().toCompletableFuture().get().status
}
@Override
void sendRequestWithCallback(StandaloneWSRequest request, String method, URI uri, Map<String, String> headers, HttpClientResult requestResult) {
request.execute().whenComplete { response, throwable ->
requestResult.complete({ response.status }, throwable)
}
}
def getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return wsClientWithReadTimeout
}
return wsClient
}
def setupSpec() {
wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer)
wsClientWithReadTimeout = new StandaloneAhcWSClient(asyncHttpClientWithReadTimeout, materializer)
}
def cleanupSpec() {
wsClient?.close()
wsClientWithReadTimeout?.close()
}
}
class PlayJavaStreamedWsClientTestBase extends PlayWsClientTestBaseBase<StandaloneWSRequest> {
@Shared
StandaloneWSClient wsClient
@Shared
StandaloneWSClient wsClientWithReadTimeout
@Override
StandaloneWSRequest buildRequest(String method, URI uri, Map<String, String> headers) {
def request = getClient(uri).url(uri.toURL().toString()).setFollowRedirects(true)
headers.entrySet().each { entry -> request.addHeader(entry.getKey(), entry.getValue()) }
request.setMethod(method)
return request
}
@Override
int sendRequest(StandaloneWSRequest request, String method, URI uri, Map<String, String> headers) {
return internalSendRequest(request).toCompletableFuture().get().status
}
@Override
void sendRequestWithCallback(StandaloneWSRequest request, String method, URI uri, Map<String, String> headers, HttpClientResult requestResult) {
internalSendRequest(request).whenComplete { response, throwable ->
requestResult.complete({ response.status }, throwable?.getCause())
}
}
private CompletionStage<StandaloneWSResponse> internalSendRequest(StandaloneWSRequest request) {
def stream = request.stream()
// The status can be ready before the body so explicitly call wait for body to be ready
return stream
.thenCompose { StandaloneWSResponse response ->
response.getBodyAsSource().runFold("", { acc, out -> "" }, materializer)
}
.thenCombine(stream) { String body, StandaloneWSResponse response ->
response
}
}
def getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return wsClientWithReadTimeout
}
return wsClient
}
def setupSpec() {
wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer)
wsClientWithReadTimeout = new StandaloneAhcWSClient(asyncHttpClientWithReadTimeout, materializer)
}
def cleanupSpec() {
wsClient?.close()
wsClientWithReadTimeout?.close()
}
}
class PlayScalaWsClientTestBase extends PlayWsClientTestBaseBase<play.api.libs.ws.StandaloneWSRequest> {
@Shared
play.api.libs.ws.StandaloneWSClient wsClient
@Shared
play.api.libs.ws.StandaloneWSClient wsClientWithReadTimeout
@Override
play.api.libs.ws.StandaloneWSRequest buildRequest(String method, URI uri, Map<String, String> headers) {
return getClient(uri).url(uri.toURL().toString())
.withMethod(method)
.withFollowRedirects(true)
.withHttpHeaders(JavaConverters.mapAsScalaMap(headers).toSeq())
}
@Override
int sendRequest(play.api.libs.ws.StandaloneWSRequest request, String method, URI uri, Map<String, String> headers) {
def futureResponse = request.execute()
Await.ready(futureResponse, Duration.apply(10, TimeUnit.SECONDS))
def value = futureResponse.value().get()
if (value.isSuccess()) {
return value.get().status()
}
throw value.failed().get()
}
@Override
void sendRequestWithCallback(play.api.libs.ws.StandaloneWSRequest request, String method, URI uri, Map<String, String> headers, HttpClientResult requestResult) {
request.execute().onComplete(new Function1<Try<play.api.libs.ws.StandaloneWSResponse>, Void>() {
@Override
Void apply(Try<play.api.libs.ws.StandaloneWSResponse> response) {
if (response.isSuccess()) {
requestResult.complete(response.get().status())
} else {
requestResult.complete(response.failed().get())
}
return null
}
}, ExecutionContext.global())
}
def getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return wsClientWithReadTimeout
}
return wsClient
}
def setupSpec() {
wsClient = new play.api.libs.ws.ahc.StandaloneAhcWSClient(asyncHttpClient, materializer)
wsClientWithReadTimeout = new play.api.libs.ws.ahc.StandaloneAhcWSClient(asyncHttpClientWithReadTimeout, materializer)
}
def cleanupSpec() {
wsClient?.close()
wsClientWithReadTimeout?.close()
}
}
class PlayScalaStreamedWsClientTestBase extends PlayWsClientTestBaseBase<play.api.libs.ws.StandaloneWSRequest> {
@Shared
play.api.libs.ws.StandaloneWSClient wsClient
@Shared
play.api.libs.ws.StandaloneWSClient wsClientWithReadTimeout
@Override
play.api.libs.ws.StandaloneWSRequest buildRequest(String method, URI uri, Map<String, String> headers) {
return getClient(uri).url(uri.toURL().toString())
.withMethod(method)
.withFollowRedirects(true)
.withHttpHeaders(JavaConverters.mapAsScalaMap(headers).toSeq())
}
@Override
int sendRequest(play.api.libs.ws.StandaloneWSRequest request, String method, URI uri, Map<String, String> headers) {
Await.result(internalSendRequest(request), Duration.apply(10, TimeUnit.SECONDS)).status()
}
@Override
void sendRequestWithCallback(play.api.libs.ws.StandaloneWSRequest request, String method, URI uri, Map<String, String> headers, HttpClientResult requestResult) {
internalSendRequest(request).onComplete(new Function1<Try<play.api.libs.ws.StandaloneWSResponse>, Void>() {
@Override
Void apply(Try<play.api.libs.ws.StandaloneWSResponse> response) {
if (response.isSuccess()) {
requestResult.complete(response.get().status())
} else {
requestResult.complete(response.failed().get())
}
return null
}
}, ExecutionContext.global())
}
private Future<play.api.libs.ws.StandaloneWSResponse> internalSendRequest(play.api.libs.ws.StandaloneWSRequest request) {
Future<play.api.libs.ws.StandaloneWSResponse> futureResponse = request.stream()
// The status can be ready before the body so explicitly call wait for body to be ready
Future<String> bodyResponse = futureResponse.flatMap(new Function1<play.api.libs.ws.StandaloneWSResponse, Future<String>>() {
@Override
Future<String> apply(play.api.libs.ws.StandaloneWSResponse wsResponse) {
return wsResponse.bodyAsSource().runFold("", { acc, out -> "" }, materializer)
}
}, ExecutionContext.global())
return bodyResponse.flatMap(new Function1<String, Future<play.api.libs.ws.StandaloneWSResponse>>() {
@Override
Future<play.api.libs.ws.StandaloneWSResponse> apply(String v1) {
return futureResponse
}
}, ExecutionContext.global())
}
def getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return wsClientWithReadTimeout
}
return wsClient
}
def setupSpec() {
wsClient = new play.api.libs.ws.ahc.StandaloneAhcWSClient(asyncHttpClient, materializer)
wsClientWithReadTimeout = new play.api.libs.ws.ahc.StandaloneAhcWSClient(asyncHttpClientWithReadTimeout, materializer)
}
def cleanupSpec() {
wsClient?.close()
wsClientWithReadTimeout?.close()
}
}

View File

@ -1,119 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.ActorMaterializerSettings
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.semconv.ServerAttributes
import io.opentelemetry.semconv.NetworkAttributes
import play.shaded.ahc.io.netty.resolver.InetNameResolver
import play.shaded.ahc.io.netty.util.concurrent.EventExecutor
import play.shaded.ahc.io.netty.util.concurrent.ImmediateEventExecutor
import play.shaded.ahc.io.netty.util.concurrent.Promise
import play.shaded.ahc.org.asynchttpclient.AsyncHttpClient
import play.shaded.ahc.org.asynchttpclient.AsyncHttpClientConfig
import play.shaded.ahc.org.asynchttpclient.DefaultAsyncHttpClient
import play.shaded.ahc.org.asynchttpclient.DefaultAsyncHttpClientConfig
import play.shaded.ahc.org.asynchttpclient.RequestBuilderBase
import spock.lang.Shared
abstract class PlayWsClientTestBaseBase<REQUEST> extends HttpClientTest<REQUEST> implements AgentTestTrait {
@Shared
ActorSystem system
@Shared
AsyncHttpClient asyncHttpClient
@Shared
AsyncHttpClient asyncHttpClientWithReadTimeout
@Shared
ActorMaterializer materializer
def setupSpec() {
String name = "play-ws"
system = ActorSystem.create(name)
ActorMaterializerSettings settings = ActorMaterializerSettings.create(system)
materializer = ActorMaterializer.create(settings, system, name)
// Replace dns name resolver with custom implementation that returns only once address for each
// host. This is needed for "connection error dropped request" because in case of connection
// failure ahc will try the next address which isn't necessary for this test.
RequestBuilderBase.DEFAULT_NAME_RESOLVER = new CustomNameResolver(ImmediateEventExecutor.INSTANCE)
asyncHttpClient = createClient(false)
asyncHttpClientWithReadTimeout = createClient(true)
}
def createClient(boolean readTimeout) {
DefaultAsyncHttpClientConfig.Builder builder = new DefaultAsyncHttpClientConfig.Builder()
.setMaxRequestRetry(0)
.setShutdownQuietPeriod(0)
.setShutdownTimeout(0)
.setMaxRedirects(3)
.setConnectTimeout(CONNECT_TIMEOUT_MS)
if (readTimeout) {
builder.setReadTimeout(READ_TIMEOUT_MS)
}
AsyncHttpClientConfig asyncHttpClientConfig =builder.build()
return new DefaultAsyncHttpClient(asyncHttpClientConfig)
}
def cleanupSpec() {
system?.terminate()
asyncHttpClient?.close()
asyncHttpClientWithReadTimeout?.close()
}
@Override
Integer responseCodeOnRedirectError() {
// apparently play ws does not report the 302 status code
null
}
@Override
int maxRedirects() {
3
}
@Override
Set<AttributeKey<?>> httpAttributes(URI uri) {
def attributes = super.httpAttributes(uri)
attributes.remove(NetworkAttributes.NETWORK_PROTOCOL_VERSION)
if (uri.toString().endsWith("/circular-redirect")) {
attributes.remove(ServerAttributes.SERVER_ADDRESS)
attributes.remove(ServerAttributes.SERVER_PORT)
}
return attributes
}
}
class CustomNameResolver extends InetNameResolver {
CustomNameResolver(EventExecutor executor) {
super(executor)
}
protected void doResolve(String inetHost, Promise<InetAddress> promise) throws Exception {
try {
promise.setSuccess(InetAddress.getByName(inetHost))
} catch (UnknownHostException exception) {
promise.setFailure(exception)
}
}
protected void doResolveAll(String inetHost, Promise<List<InetAddress>> promise) throws Exception {
try {
// default implementation calls InetAddress.getAllByName
promise.setSuccess(Collections.singletonList(InetAddress.getByName(inetHost)))
} catch (UnknownHostException exception) {
promise.setFailure(exception)
}
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import play.libs.ws.StandaloneWSClient;
import play.libs.ws.StandaloneWSRequest;
import play.libs.ws.StandaloneWSResponse;
import play.libs.ws.ahc.StandaloneAhcWSClient;
public class PlayJavaStreamedWsClientBaseTest extends PlayWsClientBaseTest<StandaloneWSRequest> {
private static StandaloneWSClient wsClient;
private static StandaloneWSClient wsClientWithReadTimeout;
@BeforeAll
static void setup() {
wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer);
wsClientWithReadTimeout =
new StandaloneAhcWSClient(asyncHttpClientWithReadTimeout, materializer);
}
@AfterAll
static void cleanup() throws IOException {
wsClient.close();
wsClientWithReadTimeout.close();
}
@Override
public StandaloneWSRequest buildRequest(String method, URI uri, Map<String, String> headers) {
StandaloneWSRequest request = getClient(uri).url(uri.toString()).setFollowRedirects(true);
headers.forEach(request::addHeader);
request.setMethod(method);
return request;
}
@Override
public int sendRequest(
StandaloneWSRequest request, String method, URI uri, Map<String, String> headers)
throws ExecutionException, InterruptedException {
return internalSendRequest(request).toCompletableFuture().get().getStatus();
}
@Override
public void sendRequestWithCallback(
StandaloneWSRequest request,
String method,
URI uri,
Map<String, String> headers,
HttpClientResult requestResult) {
internalSendRequest(request)
.whenComplete(
(response, throwable) -> {
if (throwable != null) {
requestResult.complete(throwable.getCause());
} else {
requestResult.complete(response.getStatus());
}
});
}
private static CompletionStage<StandaloneWSResponse> internalSendRequest(
StandaloneWSRequest request) {
CompletionStage<? extends StandaloneWSResponse> stream = request.stream();
// The status can be ready before the body so explicitly call wait for body to be ready
return stream
.thenCompose(
response -> response.getBodyAsSource().runFold("", (acc, out) -> "", materializer))
.thenCombine(stream, (body, response) -> response);
}
private static StandaloneWSClient getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return wsClientWithReadTimeout;
}
return wsClient;
}
}

View File

@ -0,0 +1,78 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import play.libs.ws.StandaloneWSClient;
import play.libs.ws.StandaloneWSRequest;
import play.libs.ws.ahc.StandaloneAhcWSClient;
public class PlayJavaWsClientBaseTest extends PlayWsClientBaseTest<StandaloneWSRequest> {
private static StandaloneWSClient wsClient;
private static StandaloneWSClient wsClientWithReadTimeout;
@BeforeAll
static void setup() {
wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer);
wsClientWithReadTimeout =
new StandaloneAhcWSClient(asyncHttpClientWithReadTimeout, materializer);
// autoCleanup.deferCleanup(wsClient);
// autoCleanup.deferCleanup(wsClientWithReadTimeout);
}
@AfterAll
static void cleanup() throws IOException {
wsClient.close();
wsClientWithReadTimeout.close();
}
@Override
public StandaloneWSRequest buildRequest(String method, URI uri, Map<String, String> headers) {
StandaloneWSRequest request = getClient(uri).url(uri.toString()).setFollowRedirects(true);
headers.forEach(request::addHeader);
return request.setMethod(method);
}
@Override
public int sendRequest(
StandaloneWSRequest request, String method, URI uri, Map<String, String> headers)
throws ExecutionException, InterruptedException {
return request.execute().toCompletableFuture().get().getStatus();
}
@Override
public void sendRequestWithCallback(
StandaloneWSRequest request,
String method,
URI uri,
Map<String, String> headers,
HttpClientResult requestResult) {
request
.execute()
.whenComplete(
(response, throwable) -> {
if (throwable != null) {
requestResult.complete(throwable);
} else {
requestResult.complete(response.getStatus());
}
});
}
private static StandaloneWSClient getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return wsClientWithReadTimeout;
}
return wsClient;
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import play.api.libs.ws.StandaloneWSClient;
import play.api.libs.ws.StandaloneWSRequest;
import play.api.libs.ws.StandaloneWSResponse;
import play.api.libs.ws.ahc.StandaloneAhcWSClient;
import scala.Function1;
import scala.collection.JavaConverters;
import scala.concurrent.Await;
import scala.concurrent.ExecutionContext;
import scala.concurrent.Future;
import scala.concurrent.duration.Duration;
import scala.util.Try;
public class PlayScalaStreamedWsClientBaseTest extends PlayWsClientBaseTest<StandaloneWSRequest> {
private static StandaloneWSClient wsClient;
private static StandaloneWSClient wsClientWithReadTimeout;
@BeforeAll
void setup() {
wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer);
wsClientWithReadTimeout =
new StandaloneAhcWSClient(asyncHttpClientWithReadTimeout, materializer);
}
@AfterAll
static void cleanup() throws IOException {
wsClient.close();
wsClientWithReadTimeout.close();
}
@Override
public StandaloneWSRequest buildRequest(String method, URI uri, Map<String, String> headers)
throws Exception {
return getClient(uri)
.url(uri.toURL().toString())
.withMethod(method)
.withFollowRedirects(true)
.withHttpHeaders(JavaConverters.mapAsScalaMap(headers).toSeq());
}
@Override
public int sendRequest(
StandaloneWSRequest request, String method, URI uri, Map<String, String> headers)
throws Exception {
return Await.result(internalSendRequest(request), Duration.apply(10, TimeUnit.SECONDS))
.status();
}
@Override
public void sendRequestWithCallback(
StandaloneWSRequest request,
String method,
URI uri,
Map<String, String> headers,
HttpClientResult requestResult) {
internalSendRequest(request)
.onComplete(
new Function1<Try<StandaloneWSResponse>, Void>() {
@Override
public Void apply(Try<StandaloneWSResponse> response) {
if (response.isSuccess()) {
requestResult.complete(response.get().status());
} else {
requestResult.complete(response.failed().get());
}
return null;
}
},
ExecutionContext.global());
}
private static Future<StandaloneWSResponse> internalSendRequest(StandaloneWSRequest request) {
Future<StandaloneWSResponse> futureResponse = request.stream();
// The status can be ready before the body so explicitly call wait for body to be ready
Future<String> bodyResponse =
futureResponse.flatMap(
new Function1<StandaloneWSResponse, Future<String>>() {
@Override
public Future<String> apply(StandaloneWSResponse wsResponse) {
return wsResponse.bodyAsSource().runFold("", (acc, out) -> "", materializer);
}
},
ExecutionContext.global());
return bodyResponse.flatMap(
new Function1<String, Future<StandaloneWSResponse>>() {
@Override
public Future<StandaloneWSResponse> apply(String v1) {
return futureResponse;
}
},
ExecutionContext.global());
}
private static StandaloneWSClient getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return wsClientWithReadTimeout;
}
return wsClient;
}
}

View File

@ -0,0 +1,100 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import play.api.libs.ws.StandaloneWSClient;
import play.api.libs.ws.StandaloneWSRequest;
import play.api.libs.ws.StandaloneWSResponse;
import play.api.libs.ws.ahc.StandaloneAhcWSClient;
import scala.Function1;
import scala.collection.JavaConverters;
import scala.concurrent.Await;
import scala.concurrent.ExecutionContext;
import scala.concurrent.Future;
import scala.concurrent.duration.Duration;
import scala.util.Try;
public class PlayScalaWsClientBaseTest extends PlayWsClientBaseTest<StandaloneWSRequest> {
private static StandaloneWSClient wsClient;
private static StandaloneWSClient wsClientWithReadTimeout;
@BeforeAll
void setup() {
wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer);
wsClientWithReadTimeout =
new StandaloneAhcWSClient(asyncHttpClientWithReadTimeout, materializer);
}
@AfterAll
static void cleanup() throws IOException {
wsClient.close();
wsClientWithReadTimeout.close();
}
@Override
public StandaloneWSRequest buildRequest(String method, URI uri, Map<String, String> headers)
throws MalformedURLException {
return getClient(uri)
.url(uri.toURL().toString())
.withMethod(method)
.withFollowRedirects(true)
.withHttpHeaders(JavaConverters.mapAsScalaMap(headers).toSeq());
}
@Override
public int sendRequest(
StandaloneWSRequest request, String method, URI uri, Map<String, String> headers)
throws Exception {
Future<StandaloneWSResponse> futureResponse = request.execute();
Await.ready(futureResponse, Duration.apply(10, TimeUnit.SECONDS));
Try<StandaloneWSResponse> value = futureResponse.value().get();
if (value.isSuccess()) {
return value.get().status();
}
// Catch the Throwable and rethrow it
throw (Exception) value.failed().get();
}
@Override
public void sendRequestWithCallback(
StandaloneWSRequest request,
String method,
URI uri,
Map<String, String> headers,
HttpClientResult requestResult) {
request
.execute()
.onComplete(
new Function1<Try<StandaloneWSResponse>, Void>() {
@Override
public Void apply(Try<StandaloneWSResponse> response) {
if (response.isSuccess()) {
requestResult.complete(response.get().status());
} else {
requestResult.complete(response.failed().get());
}
return null;
}
},
ExecutionContext.global());
}
private static StandaloneWSClient getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return wsClientWithReadTimeout;
}
return wsClient;
}
}

View File

@ -0,0 +1,134 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.playws;
import akka.actor.ActorSystem;
import akka.stream.ActorMaterializer;
import akka.stream.ActorMaterializerSettings;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions;
import io.opentelemetry.semconv.NetworkAttributes;
import io.opentelemetry.semconv.ServerAttributes;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.extension.RegisterExtension;
import play.shaded.ahc.io.netty.resolver.InetNameResolver;
import play.shaded.ahc.io.netty.util.concurrent.EventExecutor;
import play.shaded.ahc.io.netty.util.concurrent.ImmediateEventExecutor;
import play.shaded.ahc.io.netty.util.concurrent.Promise;
import play.shaded.ahc.org.asynchttpclient.AsyncHttpClient;
import play.shaded.ahc.org.asynchttpclient.AsyncHttpClientConfig;
import play.shaded.ahc.org.asynchttpclient.DefaultAsyncHttpClient;
import play.shaded.ahc.org.asynchttpclient.DefaultAsyncHttpClientConfig;
import play.shaded.ahc.org.asynchttpclient.RequestBuilderBase;
abstract class PlayWsClientBaseTest<REQUEST> extends AbstractHttpClientTest<REQUEST> {
@RegisterExtension
static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent();
private static ActorSystem system;
protected static AsyncHttpClient asyncHttpClient;
protected static AsyncHttpClient asyncHttpClientWithReadTimeout;
protected static ActorMaterializer materializer;
@BeforeAll
static void setupHttpClient() {
String name = "play-ws";
system = ActorSystem.create(name);
materializer = ActorMaterializer.create(ActorMaterializerSettings.create(system), system, name);
// Replace dns name resolver with custom implementation that returns only once address for each
// host. This is needed for "connection error dropped request" because in case of connection
// failure ahc will try the next address which isn't necessary for this test.
RequestBuilderBase.DEFAULT_NAME_RESOLVER =
new CustomNameResolver(ImmediateEventExecutor.INSTANCE);
asyncHttpClient = createClient(false);
asyncHttpClientWithReadTimeout = createClient(true);
}
@AfterAll
static void cleanupHttpClient() throws IOException {
asyncHttpClient.close();
asyncHttpClientWithReadTimeout.close();
system.terminate();
}
@Override
protected void configure(HttpClientTestOptions.Builder optionsBuilder) {
super.configure(optionsBuilder);
// apparently play ws does not report the 302 status code
optionsBuilder.setResponseCodeOnRedirectError(null);
optionsBuilder.setMaxRedirects(3);
optionsBuilder.spanEndsAfterBody();
optionsBuilder.setHttpAttributes(
uri -> {
Set<AttributeKey<?>> attributes =
new HashSet<>(HttpClientTestOptions.DEFAULT_HTTP_ATTRIBUTES);
attributes.remove(NetworkAttributes.NETWORK_PROTOCOL_VERSION);
if (uri.toString().endsWith("/circular-redirect")) {
attributes.remove(ServerAttributes.SERVER_ADDRESS);
attributes.remove(ServerAttributes.SERVER_PORT);
}
return attributes;
});
}
private static AsyncHttpClient createClient(boolean readTimeout) {
DefaultAsyncHttpClientConfig.Builder builder =
new DefaultAsyncHttpClientConfig.Builder()
.setMaxRequestRetry(0)
.setShutdownQuietPeriod(0)
.setShutdownTimeout(0)
.setMaxRedirects(3)
.setConnectTimeout(5000);
if (readTimeout) {
builder.setReadTimeout(2000);
}
AsyncHttpClientConfig asyncHttpClientConfig = builder.build();
return new DefaultAsyncHttpClient(asyncHttpClientConfig);
}
private static class CustomNameResolver extends InetNameResolver {
public CustomNameResolver(EventExecutor executor) {
super(executor);
}
@Override
protected void doResolve(String inetHost, Promise<InetAddress> promise) throws Exception {
try {
promise.setSuccess(InetAddress.getByName(inetHost));
} catch (UnknownHostException exception) {
promise.setFailure(exception);
}
}
@Override
protected void doResolveAll(String inetHost, Promise<List<InetAddress>> promise)
throws Exception {
try {
// default implementation calls InetAddress.getAllByName
promise.setSuccess(Collections.singletonList(InetAddress.getByName(inetHost)));
} catch (UnknownHostException exception) {
promise.setFailure(exception);
}
}
}
}