Convert HttpClientTest to JUnit (#3652)

* Migrate HttpClientTest to junit to allow both Java or spock tests.

* More

* Update

* Finish

* Cleanup

* Better stack

* Java 15

* Merge

* Fix name

* Cleanup

* ? extends

* Moar
This commit is contained in:
Anuraag Agrawal 2021-07-27 21:55:40 +09:00 committed by GitHub
parent 262feb1730
commit 47be4a16b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 2060 additions and 1208 deletions

View File

@ -15,7 +15,8 @@ import akka.http.javadsl.model.headers.RawHeader
import akka.stream.ActorMaterializer
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import java.util.concurrent.TimeUnit
import spock.lang.Shared
@ -46,7 +47,7 @@ class AkkaHttpClientInstrumentationTest extends HttpClientTest<HttpRequest> impl
}
@Override
void sendRequestWithCallback(HttpRequest request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(HttpRequest request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
Http.get(system).singleRequest(request, materializer).whenComplete {response, throwable ->
if (throwable == null) {
response.discardEntityBytes(materializer)

View File

@ -6,6 +6,7 @@
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import java.util.concurrent.CancellationException
import org.apache.http.HttpResponse
@ -46,7 +47,7 @@ class ApacheHttpAsyncClientTest extends HttpClientTest<HttpUriRequest> implement
}
@Override
void sendRequestWithCallback(HttpUriRequest request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(HttpUriRequest request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
client.execute(request, new FutureCallback<HttpResponse>() {
@Override
void completed(HttpResponse httpResponse) {

View File

@ -6,6 +6,7 @@
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import java.util.function.Consumer
import org.apache.http.HttpHost
@ -59,7 +60,7 @@ abstract class ApacheHttpClientTest<T extends HttpRequest> extends HttpClientTes
}
// compilation fails with @Override annotation on this method (groovy quirk?)
void sendRequestWithCallback(T request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(T request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
try {
executeRequestWithCallback(request, uri) {
it.entity?.content?.close() // Make sure the connection is closed.

View File

@ -6,6 +6,7 @@
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import java.util.concurrent.TimeUnit
import java.util.function.Consumer
@ -64,7 +65,7 @@ abstract class ApacheHttpClientTest<T extends HttpRequest> extends HttpClientTes
}
// compilation fails with @Override annotation on this method (groovy quirk?)
void sendRequestWithCallback(T request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(T request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
try {
executeRequestWithCallback(request, uri) {
it.close() // Make sure the connection is closed.

View File

@ -1,17 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.armeria.v1_3
import com.linecorp.armeria.client.WebClientBuilder
import io.opentelemetry.instrumentation.armeria.v1_3.AbstractArmeriaHttpClientTest
import io.opentelemetry.instrumentation.test.AgentTestTrait
class ArmeriaHttpClientTest extends AbstractArmeriaHttpClientTest implements AgentTestTrait {
@Override
WebClientBuilder configureClient(WebClientBuilder clientBuilder) {
return clientBuilder
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.armeria.v1_3;
import com.linecorp.armeria.client.WebClientBuilder;
import io.opentelemetry.instrumentation.armeria.v1_3.AbstractArmeriaHttpClientTest;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension;
import org.junit.jupiter.api.extension.RegisterExtension;
class ArmeriaHttpClientTest extends AbstractArmeriaHttpClientTest {
@RegisterExtension
static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent();
@Override
protected WebClientBuilder configureClient(WebClientBuilder clientBuilder) {
return clientBuilder;
}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.armeria.v1_3
import com.linecorp.armeria.client.WebClientBuilder
import io.opentelemetry.instrumentation.test.LibraryTestTrait
class ArmeriaHttpClientTest extends AbstractArmeriaHttpClientTest implements LibraryTestTrait {
@Override
WebClientBuilder configureClient(WebClientBuilder clientBuilder) {
return clientBuilder.decorator(ArmeriaTracing.create(getOpenTelemetry()).newClientDecorator())
}
// library instrumentation doesn't have a good way of suppressing nested CLIENT spans yet
@Override
boolean testWithClientParent() {
false
}
// Agent users have automatic propagation through executor instrumentation, but library users
// should do manually using Armeria patterns.
@Override
boolean testCallbackWithParent() {
false
}
@Override
boolean testErrorWithCallback() {
return false
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.armeria.v1_3;
import com.linecorp.armeria.client.WebClientBuilder;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension;
import org.junit.jupiter.api.extension.RegisterExtension;
class ArmeriaHttpClientTest extends AbstractArmeriaHttpClientTest {
@RegisterExtension
static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forLibrary();
@Override
protected WebClientBuilder configureClient(WebClientBuilder clientBuilder) {
return clientBuilder.decorator(
ArmeriaTracing.create(testing.getOpenTelemetry()).newClientDecorator());
}
// library instrumentation doesn't have a good way of suppressing nested CLIENT spans yet
@Override
protected boolean testWithClientParent() {
return false;
}
// Agent users have automatic propagation through executor instrumentation, but library users
// should do manually using Armeria patterns.
@Override
protected boolean testCallbackWithParent() {
return false;
}
@Override
protected boolean testErrorWithCallback() {
return false;
}
}

View File

@ -1,77 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.armeria.v1_3
import com.linecorp.armeria.client.WebClient
import com.linecorp.armeria.client.WebClientBuilder
import com.linecorp.armeria.common.HttpMethod
import com.linecorp.armeria.common.HttpRequest
import com.linecorp.armeria.common.RequestHeaders
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import java.util.concurrent.CompletionException
import spock.lang.Shared
abstract class AbstractArmeriaHttpClientTest extends HttpClientTest<HttpRequest> {
abstract WebClientBuilder configureClient(WebClientBuilder clientBuilder)
@Shared
def client = configureClient(WebClient.builder()).build()
@Override
HttpRequest buildRequest(String method, URI uri, Map<String, String> headers) {
return HttpRequest.of(
RequestHeaders.builder(HttpMethod.valueOf(method), uri.toString())
.set(headers.entrySet())
.build())
}
@Override
int sendRequest(HttpRequest request, String method, URI uri, Map<String, String> headers) {
try {
return client.execute(request)
.aggregate()
.join()
.status()
.code()
} catch (CompletionException e) {
throw e.cause
}
}
@Override
void sendRequestWithCallback(HttpRequest request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
client.execute(request).aggregate().whenComplete {response, throwable ->
requestResult.complete({ response.status().code() }, throwable)
}
}
// Not supported yet: https://github.com/line/armeria/issues/2489
@Override
boolean testRedirects() {
false
}
@Override
boolean testReusedRequest() {
// armeria requests can't be reused
false
}
@Override
Set<AttributeKey<?>> httpAttributes(URI uri) {
Set<AttributeKey<?>> extra = [
SemanticAttributes.HTTP_HOST,
SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH,
SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
SemanticAttributes.HTTP_SCHEME,
SemanticAttributes.HTTP_TARGET
]
super.httpAttributes(uri) + extra
}
}

View File

@ -0,0 +1,96 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.armeria.v1_3;
import com.linecorp.armeria.client.ClientFactory;
import com.linecorp.armeria.client.WebClient;
import com.linecorp.armeria.client.WebClientBuilder;
import com.linecorp.armeria.common.HttpMethod;
import com.linecorp.armeria.common.HttpRequest;
import com.linecorp.armeria.common.RequestHeaders;
import com.linecorp.armeria.common.util.Exceptions;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.net.URI;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletionException;
import org.junit.jupiter.api.BeforeEach;
public abstract class AbstractArmeriaHttpClientTest extends AbstractHttpClientTest<HttpRequest> {
protected abstract WebClientBuilder configureClient(WebClientBuilder clientBuilder);
private WebClient client;
@BeforeEach
void setupClient() {
client =
configureClient(
WebClient.builder()
.factory(ClientFactory.builder().connectTimeout(connectTimeout()).build()))
.build();
}
@Override
protected final HttpRequest buildRequest(String method, URI uri, Map<String, String> headers) {
return HttpRequest.of(
RequestHeaders.builder(HttpMethod.valueOf(method), uri.toString())
.set(headers.entrySet())
.build());
}
@Override
protected final int sendRequest(
HttpRequest request, String method, URI uri, Map<String, String> headers) {
try {
return client.execute(request).aggregate().join().status().code();
} catch (CompletionException e) {
return Exceptions.throwUnsafely(e.getCause());
}
}
@Override
protected final void sendRequestWithCallback(
HttpRequest request,
String method,
URI uri,
Map<String, String> headers,
RequestResult requestResult) {
client
.execute(request)
.aggregate()
.whenComplete(
(response, throwable) ->
requestResult.complete(() -> response.status().code(), throwable));
}
// Not supported yet: https://github.com/line/armeria/issues/2489
@Override
protected final boolean testRedirects() {
return false;
}
@Override
protected final boolean testReusedRequest() {
// armeria requests can't be reused
return false;
}
@Override
protected Set<AttributeKey<?>> httpAttributes(URI uri) {
Set<AttributeKey<?>> extra = new HashSet<>();
extra.add(SemanticAttributes.HTTP_HOST);
extra.add(SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH);
extra.add(SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH);
extra.add(SemanticAttributes.HTTP_SCHEME);
extra.add(SemanticAttributes.HTTP_TARGET);
extra.addAll(super.httpAttributes(uri));
return extra;
}
}

View File

@ -12,7 +12,8 @@ import com.ning.http.client.Response
import com.ning.http.client.uri.Uri
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import spock.lang.AutoCleanup
import spock.lang.Shared
@ -39,7 +40,7 @@ class AsyncHttpClientTest extends HttpClientTest<Request> implements AgentTestTr
}
@Override
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
// TODO(anuraaga): Do we also need to test ListenableFuture callback?
client.executeRequest(request, new AsyncCompletionHandler<Void>() {
@Override

View File

@ -6,6 +6,7 @@
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import org.asynchttpclient.AsyncCompletionHandler
import org.asynchttpclient.Dsl
@ -40,7 +41,7 @@ class AsyncHttpClientTest extends HttpClientTest<Request> implements AgentTestTr
}
@Override
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
client.executeRequest(request, new AsyncCompletionHandler<Void>() {
@Override
Void onCompleted(Response response) throws Exception {

View File

@ -5,6 +5,7 @@
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import org.springframework.http.HttpEntity
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpMethod
@ -44,7 +45,7 @@ class SpringRestTemplateTest extends HttpClientTest<HttpEntity<String>> implemen
}
@Override
void sendRequestWithCallback(HttpEntity<String> request, String method, URI uri, Map<String, String> headers = [:], RequestResult requestResult) {
void sendRequestWithCallback(HttpEntity<String> request, String method, URI uri, Map<String, String> headers = [:], AbstractHttpClientTest.RequestResult requestResult) {
try {
restTemplate.execute(uri, HttpMethod.valueOf(method), { req ->
req.getHeaders().putAll(request.getHeaders())

View File

@ -5,6 +5,7 @@
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
@ -38,7 +39,7 @@ class JdkHttpClientTest extends HttpClientTest<HttpRequest> implements AgentTest
}
@Override
void sendRequestWithCallback(HttpRequest request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(HttpRequest request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.whenComplete { response, throwable ->
requestResult.complete({ response.statusCode() }, throwable?.getCause())

View File

@ -9,7 +9,8 @@ import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTr
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import java.util.concurrent.TimeUnit
import javax.ws.rs.ProcessingException
@ -46,7 +47,7 @@ abstract class JaxRsClientTest extends HttpClientTest<Invocation.Builder> implem
}
@Override
void sendRequestWithCallback(Invocation.Builder request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(Invocation.Builder request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
def body = BODY_METHODS.contains(method) ? Entity.text("") : null
request.async().method(method, (Entity) body, new InvocationCallback<Response>() {

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import java.util.concurrent.ExecutionException
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException

View File

@ -7,7 +7,9 @@ package io.opentelemetry.instrumentation.jetty.httpclient.v9_2
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import java.util.concurrent.TimeUnit
import org.eclipse.jetty.client.HttpClient
import org.eclipse.jetty.client.api.ContentResponse
import org.eclipse.jetty.client.api.Request
@ -15,12 +17,8 @@ import org.eclipse.jetty.client.api.Response
import org.eclipse.jetty.client.api.Result
import org.eclipse.jetty.http.HttpMethod
import org.eclipse.jetty.util.ssl.SslContextFactory
import org.junit.Rule
import org.junit.rules.TestName
import spock.lang.Shared
import java.util.concurrent.TimeUnit
abstract class AbstractJettyClient9Test extends HttpClientTest<Request> {
abstract HttpClient createStandardClient()
@ -33,9 +31,6 @@ abstract class AbstractJettyClient9Test extends HttpClientTest<Request> {
@Shared
def httpsClient = null
@Rule
TestName name = new TestName()
Request jettyRequest = null
def setupSpec() {
@ -55,6 +50,7 @@ abstract class AbstractJettyClient9Test extends HttpClientTest<Request> {
HttpClient theClient = uri.scheme == 'https' ? httpsClient : client
Request request = theClient.newRequest(uri)
request.agent("Jetty")
HttpMethod methodObj = HttpMethod.valueOf(method)
request.method(methodObj)
@ -67,9 +63,6 @@ abstract class AbstractJettyClient9Test extends HttpClientTest<Request> {
@Override
String userAgent() {
if (name.methodName.startsWith('connection error') && jettyRequest.getAgent() == null) {
return null
}
return "Jetty"
}
@ -102,7 +95,7 @@ abstract class AbstractJettyClient9Test extends HttpClientTest<Request> {
}
@Override
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
JettyClientListener jcl = new JettyClientListener()

View File

@ -11,8 +11,8 @@ import com.ning.http.client.RequestBuilder
import com.ning.http.client.Response
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.asserts.SpanAssert
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import java.nio.channels.ClosedChannelException
import spock.lang.AutoCleanup
import spock.lang.Shared
@ -62,7 +62,7 @@ class Netty38ClientTest extends HttpClientTest<Request> implements AgentTestTrai
}
@Override
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
// TODO(anuraaga): Do we also need to test ListenableFuture callback?
client.executeRequest(request, new AsyncCompletionHandler<Void>() {
@Override
@ -95,7 +95,7 @@ class Netty38ClientTest extends HttpClientTest<Request> implements AgentTestTrai
}
@Override
void assertClientSpanErrorEvent(SpanAssert spanAssert, URI uri, Throwable exception) {
Throwable clientSpanError(URI uri, Throwable exception) {
switch (uri.toString()) {
case "http://localhost:61/": // unopened port
exception = exception.getCause() != null ? exception.getCause() : new ConnectException("Connection refused: localhost/127.0.0.1:61")
@ -103,7 +103,7 @@ class Netty38ClientTest extends HttpClientTest<Request> implements AgentTestTrai
case "https://192.0.2.1/": // non routable address
exception = exception.getCause() != null ? exception.getCause() : new ClosedChannelException()
}
super.assertClientSpanErrorEvent(spanAssert, uri, exception)
return exception
}
@Override

View File

@ -22,6 +22,7 @@ import io.netty.handler.timeout.ReadTimeoutHandler
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit
import spock.lang.Shared
@ -86,7 +87,7 @@ class Netty40ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
}
@Override
void sendRequestWithCallback(DefaultFullHttpRequest request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(DefaultFullHttpRequest request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
Channel ch
try {
ch = getBootstrap(uri).connect(uri.host, getPort(uri)).sync().channel()

View File

@ -30,7 +30,8 @@ import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.api.trace.SpanKind
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.HttpClientTracingHandler
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit
@ -114,7 +115,7 @@ class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
}
@Override
void sendRequestWithCallback(DefaultFullHttpRequest request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(DefaultFullHttpRequest request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
Channel ch
try {
ch = getBootstrap(uri).connect(uri.host, getPort(uri)).sync().channel()

View File

@ -20,7 +20,7 @@ import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpVersion;
import io.opentelemetry.instrumentation.test.base.SingleConnection;
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;

View File

@ -12,6 +12,7 @@ import com.squareup.okhttp.Response
import com.squareup.okhttp.internal.http.HttpMethod
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import java.util.concurrent.TimeUnit
import spock.lang.Shared
@ -39,7 +40,7 @@ class OkHttp2Test extends HttpClientTest<Request> implements AgentTestTrait {
}
@Override
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
client.newCall(request).enqueue(new Callback() {
@Override
void onFailure(Request req, IOException e) {

View File

@ -7,6 +7,7 @@ package io.opentelemetry.instrumentation.okhttp.v3_0
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import java.util.concurrent.TimeUnit
import okhttp3.Call
@ -48,7 +49,7 @@ abstract class AbstractOkHttp3Test extends HttpClientTest<Request> {
}
@Override
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
client.newCall(request).enqueue(new Callback() {
@Override
void onFailure(Call call, IOException e) {

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import java.util.concurrent.CompletionStage
import java.util.concurrent.TimeUnit
import play.libs.ws.StandaloneWSClient
@ -36,7 +36,7 @@ class PlayJavaWsClientTestBase extends PlayWsClientTestBaseBase<StandaloneWSRequ
}
@Override
void sendRequestWithCallback(StandaloneWSRequest request, String method, URI uri, Map<String, String> headers, HttpClientTest.RequestResult requestResult) {
void sendRequestWithCallback(StandaloneWSRequest request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
request.execute().whenComplete { response, throwable ->
requestResult.complete({ response.status }, throwable)
}
@ -69,7 +69,7 @@ class PlayJavaStreamedWsClientTestBase extends PlayWsClientTestBaseBase<Standalo
}
@Override
void sendRequestWithCallback(StandaloneWSRequest request, String method, URI uri, Map<String, String> headers, HttpClientTest.RequestResult requestResult) {
void sendRequestWithCallback(StandaloneWSRequest request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
internalSendRequest(request).whenComplete { response, throwable ->
requestResult.complete({ response.status }, throwable?.getCause())
}
@ -120,7 +120,7 @@ class PlayScalaWsClientTestBase extends PlayWsClientTestBaseBase<play.api.libs.w
}
@Override
void sendRequestWithCallback(play.api.libs.ws.StandaloneWSRequest request, String method, URI uri, Map<String, String> headers, HttpClientTest.RequestResult requestResult) {
void sendRequestWithCallback(play.api.libs.ws.StandaloneWSRequest request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
request.execute().onComplete(new Function1<Try<play.api.libs.ws.StandaloneWSResponse>, Void>() {
@Override
Void apply(Try<play.api.libs.ws.StandaloneWSResponse> response) {
@ -161,7 +161,7 @@ class PlayScalaStreamedWsClientTestBase extends PlayWsClientTestBaseBase<play.ap
}
@Override
void sendRequestWithCallback(play.api.libs.ws.StandaloneWSRequest request, String method, URI uri, Map<String, String> headers, HttpClientTest.RequestResult requestResult) {
void sendRequestWithCallback(play.api.libs.ws.StandaloneWSRequest request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
internalSendRequest(request).onComplete(new Function1<Try<play.api.libs.ws.StandaloneWSResponse>, Void>() {
@Override
Void apply(Try<play.api.libs.ws.StandaloneWSResponse> response) {

View File

@ -8,7 +8,8 @@ package client
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import java.util.concurrent.CompletionStage
import play.libs.ws.WS
@ -41,7 +42,7 @@ class PlayWsClientTest extends HttpClientTest<WSRequest> implements AgentTestTra
}
@Override
void sendRequestWithCallback(WSRequest request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(WSRequest request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
internalSendRequest(request, method).whenComplete { response, throwable ->
requestResult.complete({ response.status }, throwable)
}

View File

@ -9,9 +9,9 @@ import io.netty.channel.ConnectTimeoutException
import io.netty.handler.timeout.ReadTimeoutException
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.asserts.SpanAssert
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import java.time.Duration
import java.util.concurrent.ExecutionException
import java.util.concurrent.TimeoutException
@ -69,7 +69,7 @@ class RatpackHttpClientTest extends HttpClientTest<Void> implements AgentTestTra
}
@Override
void sendRequestWithCallback(Void request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(Void request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
exec.execute(Operation.of {
internalSendRequest(client, method, uri, headers).result {result ->
requestResult.complete({ result.value }, result.throwable)
@ -122,16 +122,13 @@ class RatpackHttpClientTest extends HttpClientTest<Void> implements AgentTestTra
}
@Override
void assertClientSpanErrorEvent(SpanAssert spanAssert, URI uri, Throwable exception) {
// non routable address
Throwable clientSpanError(URI uri, Throwable exception) {
if (uri.toString() == "https://192.0.2.1/") {
spanAssert.errorEvent(ConnectTimeoutException, ~/connection timed out:/)
return
return new ConnectTimeoutException("connection timed out: /192.0.2.1:443")
} else if (uri.getPath() == "/read-timeout") {
spanAssert.errorEvent(ReadTimeoutException)
return
return new ReadTimeoutException()
}
super.assertClientSpanErrorEvent(spanAssert, uri, exception)
return exception
}
@Override

View File

@ -5,7 +5,7 @@
package client
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import ratpack.http.client.HttpClient
class RatpackPooledHttpClientTest extends RatpackHttpClientTest {

View File

@ -12,8 +12,8 @@ import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.SpanKind
import io.opentelemetry.api.trace.StatusCode
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.asserts.SpanAssert
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.sdk.trace.data.SpanData
import java.util.concurrent.atomic.AtomicReference
import reactor.netty.http.client.HttpClient
@ -51,7 +51,7 @@ abstract class AbstractReactorNettyHttpClientTest extends HttpClientTest<HttpCli
}
@Override
void sendRequestWithCallback(HttpClient.ResponseReceiver request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(HttpClient.ResponseReceiver request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
request.responseSingle {resp, content ->
// Make sure to consume content since that's when we close the span.
content.map { resp }
@ -74,7 +74,7 @@ abstract class AbstractReactorNettyHttpClientTest extends HttpClientTest<HttpCli
}
@Override
void assertClientSpanErrorEvent(SpanAssert spanAssert, URI uri, Throwable exception) {
Throwable clientSpanError(URI uri, Throwable exception) {
if (exception.class.getName().endsWith("ReactiveException")) {
switch (uri.toString()) {
case "http://localhost:61/": // unopened port
@ -82,7 +82,7 @@ abstract class AbstractReactorNettyHttpClientTest extends HttpClientTest<HttpCli
exception = exception.getCause()
}
}
super.assertClientSpanErrorEvent(spanAssert, uri, exception)
return exception
}
@Override

View File

@ -6,7 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.reactornetty.v0_9
import io.netty.channel.ChannelOption
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import java.util.concurrent.ExecutionException
import java.util.concurrent.TimeoutException
import reactor.netty.http.client.HttpClient

View File

@ -17,8 +17,8 @@ import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.SpanKind
import io.opentelemetry.api.trace.StatusCode
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.asserts.SpanAssert
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.sdk.trace.data.SpanData
import java.util.concurrent.atomic.AtomicReference
import reactor.netty.http.client.HttpClient
@ -56,7 +56,7 @@ abstract class AbstractReactorNettyHttpClientTest extends HttpClientTest<HttpCli
}
@Override
void sendRequestWithCallback(HttpClient.ResponseReceiver request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(HttpClient.ResponseReceiver request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
request.responseSingle {resp, content ->
// Make sure to consume content since that's when we close the span.
content.map { resp }
@ -79,7 +79,7 @@ abstract class AbstractReactorNettyHttpClientTest extends HttpClientTest<HttpCli
}
@Override
void assertClientSpanErrorEvent(SpanAssert spanAssert, URI uri, Throwable exception) {
Throwable clientSpanError(URI uri, Throwable exception) {
if (exception.class.getName().endsWith("ReactiveException")) {
switch (uri.toString()) {
case "http://localhost:61/": // unopened port
@ -87,7 +87,7 @@ abstract class AbstractReactorNettyHttpClientTest extends HttpClientTest<HttpCli
exception = exception.getCause()
}
}
super.assertClientSpanErrorEvent(spanAssert, uri, exception)
return exception
}
@Override

View File

@ -6,7 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.reactornetty.v1_0
import io.netty.channel.ChannelOption
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import java.util.concurrent.ExecutionException
import java.util.concurrent.TimeoutException
import reactor.netty.http.client.HttpClient

View File

@ -6,6 +6,7 @@
import io.opentelemetry.instrumentation.spring.httpclients.RestTemplateInterceptor
import io.opentelemetry.instrumentation.test.LibraryTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import org.springframework.http.HttpEntity
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpMethod
@ -43,7 +44,7 @@ class RestTemplateInstrumentationTest extends HttpClientTest<HttpEntity<String>>
}
@Override
void sendRequestWithCallback(HttpEntity<String> request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(HttpEntity<String> request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
try {
restTemplate.execute(uri, HttpMethod.valueOf(method), { req ->
headers.forEach(req.getHeaders().&add)

View File

@ -7,7 +7,7 @@ package client
import io.netty.channel.ChannelOption
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import java.util.concurrent.ExecutionException
import java.util.concurrent.TimeoutException
import org.springframework.http.HttpMethod

View File

@ -7,9 +7,9 @@ package client
import io.netty.channel.ChannelOption
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.asserts.SpanAssert
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import org.springframework.http.HttpMethod
import org.springframework.http.client.reactive.ReactorClientHttpConnector
import org.springframework.web.reactive.function.client.WebClient
@ -49,7 +49,7 @@ class SpringWebfluxHttpClientTest extends HttpClientTest<WebClient.RequestBodySp
}
@Override
void sendRequestWithCallback(WebClient.RequestBodySpec request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(WebClient.RequestBodySpec request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
request.exchange().subscribe({
requestResult.complete(it.statusCode().value())
}, {
@ -58,7 +58,7 @@ class SpringWebfluxHttpClientTest extends HttpClientTest<WebClient.RequestBodySp
}
@Override
void assertClientSpanErrorEvent(SpanAssert spanAssert, URI uri, Throwable exception) {
Throwable clientSpanError(URI uri, Throwable exception) {
if (!exception.getClass().getName().endsWith("WebClientRequestException")) {
switch (uri.toString()) {
case "http://localhost:61/": // unopened port
@ -70,7 +70,7 @@ class SpringWebfluxHttpClientTest extends HttpClientTest<WebClient.RequestBodySp
exception = exception.getCause()
}
}
super.assertClientSpanErrorEvent(spanAssert, uri, exception)
return exception
}
@Override

View File

@ -7,7 +7,8 @@ package client
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import io.vertx.core.Vertx
import io.vertx.core.VertxOptions
import io.vertx.core.http.HttpClientOptions
@ -52,7 +53,7 @@ class VertxHttpClientTest extends HttpClientTest<HttpClientRequest> implements A
}
@Override
void sendRequestWithCallback(HttpClientRequest request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(HttpClientRequest request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
sendRequest(request).whenComplete { status, throwable ->
requestResult.complete({ status }, throwable)
}

View File

@ -5,7 +5,7 @@
package client;
import io.opentelemetry.instrumentation.test.base.SingleConnection;
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.http.HttpClient;

View File

@ -7,7 +7,8 @@ package client
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import io.vertx.circuitbreaker.CircuitBreakerOptions
import io.vertx.core.AsyncResult
import io.vertx.core.VertxOptions
@ -70,7 +71,7 @@ class VertxRxCircuitBreakerWebClientTest extends HttpClientTest<HttpRequest<?>>
}
@Override
void sendRequestWithCallback(HttpRequest<?> request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(HttpRequest<?> request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
sendRequestWithCallback(request) {
if (it.succeeded()) {
requestResult.complete(it.result().statusCode())

View File

@ -6,9 +6,9 @@
package client
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.asserts.SpanAssert
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.test.base.SingleConnection
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import io.vertx.core.VertxOptions
import io.vertx.core.http.HttpMethod
import io.vertx.ext.web.client.WebClientOptions
@ -41,7 +41,7 @@ class VertxRxWebClientTest extends HttpClientTest<HttpRequest<Buffer>> implement
}
@Override
void sendRequestWithCallback(HttpRequest<Buffer> request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
void sendRequestWithCallback(HttpRequest<Buffer> request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
request.rxSend()
.subscribe(new io.reactivex.functions.Consumer<HttpResponse<?>>() {
@Override
@ -57,7 +57,7 @@ class VertxRxWebClientTest extends HttpClientTest<HttpRequest<Buffer>> implement
}
@Override
void assertClientSpanErrorEvent(SpanAssert spanAssert, URI uri, Throwable exception) {
Throwable clientSpanError(URI uri, Throwable exception) {
if (exception.class == RuntimeException) {
switch (uri.toString()) {
case "http://localhost:61/": // unopened port
@ -65,7 +65,7 @@ class VertxRxWebClientTest extends HttpClientTest<HttpRequest<Buffer>> implement
exception = exception.getCause()
}
}
super.assertClientSpanErrorEvent(spanAssert, uri, exception)
return exception
}
@Override

View File

@ -5,7 +5,7 @@
package client;
import io.opentelemetry.instrumentation.test.base.SingleConnection;
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection;
import io.vertx.core.VertxOptions;
import io.vertx.core.http.HttpMethod;
import io.vertx.ext.web.client.WebClientOptions;

View File

@ -16,7 +16,8 @@ sourceSets {
dependencies {
api("org.codehaus.groovy:groovy-all")
api("org.spockframework:spock-core")
implementation("org.junit.jupiter:junit-jupiter-api")
api("org.junit.jupiter:junit-jupiter-api")
api("org.junit.jupiter:junit-jupiter-params")
api("io.opentelemetry:opentelemetry-api")
api("io.opentelemetry:opentelemetry-semconv")
@ -27,6 +28,9 @@ dependencies {
api("org.assertj:assertj-core")
// Needs to be api dependency due to Spock restriction.
api("org.awaitility:awaitility")
compileOnly(project(path = ":testing:armeria-shaded-for-testing", configuration = "shadow"))
implementation("io.opentelemetry:opentelemetry-proto") {
@ -39,7 +43,6 @@ dependencies {
implementation("net.bytebuddy:byte-buddy-agent")
implementation("org.slf4j:slf4j-api")
implementation("ch.qos.logback:logback-classic")
implementation("org.awaitility:awaitility")
implementation("org.slf4j:log4j-over-slf4j")
implementation("org.slf4j:jcl-over-slf4j")
implementation("org.slf4j:jul-to-slf4j")

View File

@ -5,13 +5,11 @@
package io.opentelemetry.instrumentation.test.utils
import io.opentelemetry.api.GlobalOpenTelemetry
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.SpanKind
import io.opentelemetry.api.trace.StatusCode
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.extension.annotations.WithSpan
import io.opentelemetry.instrumentation.test.server.ServerTraceUtils
import io.opentelemetry.instrumentation.testing.util.ThrowingRunnable
import java.util.concurrent.Callable
@ -57,13 +55,6 @@ class TraceUtils {
tracer.spanBuilder(spanName).startSpan().end()
}
// Must create span within agent using annotation until
// https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/1726
@WithSpan(value = "parent-client-span", kind = SpanKind.CLIENT)
static <T> T runUnderParentClientSpan(Callable<T> r) {
r.call()
}
static <T> T runUnderTraceWithoutExceptionCatch(String spanName, Callable<T> r) {
Span span = tracer.spanBuilder(spanName).setSpanKind(SpanKind.INTERNAL).startSpan()

View File

@ -5,12 +5,22 @@
package io.opentelemetry.instrumentation.testing;
import static org.awaitility.Awaitility.await;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.testing.util.TelemetryDataUtil;
import io.opentelemetry.instrumentation.testing.util.ThrowingRunnable;
import io.opentelemetry.instrumentation.testing.util.ThrowingSupplier;
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.testing.assertj.TraceAssert;
import io.opentelemetry.sdk.testing.assertj.TracesAssert;
import io.opentelemetry.sdk.trace.data.SpanData;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.stream.StreamSupport;
import org.awaitility.core.ConditionTimeoutException;
/**
* This interface defines a common set of operations for interaction with OpenTelemetry SDK and
@ -34,6 +44,43 @@ public interface InstrumentationTestRunner {
boolean forceFlushCalled();
/** Return a list of all captured traces, where each trace is a sorted list of spans. */
default List<List<SpanData>> traces() {
return TelemetryDataUtil.groupTraces(getExportedSpans());
}
default List<List<SpanData>> waitForTraces(int numberOfTraces) {
try {
return TelemetryDataUtil.waitForTraces(
this::getExportedSpans, numberOfTraces, 20, TimeUnit.SECONDS);
} catch (TimeoutException | InterruptedException e) {
throw new AssertionError("Error waiting for " + numberOfTraces + " traces", e);
}
}
default void waitAndAssertTraces(Consumer<TraceAssert>... assertions) {
try {
await()
.untilAsserted(
() -> {
List<List<SpanData>> traces = waitForTraces(assertions.length);
TracesAssert.assertThat(traces).hasTracesSatisfyingExactly(assertions);
});
} catch (ConditionTimeoutException e) {
// Don't throw this failure since the stack is the awaitility thread, causing confusion.
// Instead, just assert one more time on the test thread, which will fail with a better stack
// trace.
// TODO(anuraaga): There is probably a better way to do this.
List<List<SpanData>> traces = waitForTraces(assertions.length);
TracesAssert.assertThat(traces).hasTracesSatisfyingExactly(assertions);
}
}
default void waitAndAssertTraces(Iterable<? extends Consumer<TraceAssert>> assertions) {
waitAndAssertTraces(
StreamSupport.stream(assertions.spliterator(), false).toArray(Consumer[]::new));
}
/**
* Runs the provided {@code callback} inside the scope of an INTERNAL span with name {@code
* spanName}.

View File

@ -11,14 +11,12 @@ import static org.awaitility.Awaitility.await;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.context.ContextStorage;
import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner;
import io.opentelemetry.instrumentation.testing.util.TelemetryDataUtil;
import io.opentelemetry.instrumentation.testing.util.ThrowingRunnable;
import io.opentelemetry.instrumentation.testing.util.ThrowingSupplier;
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.testing.assertj.TraceAssert;
import io.opentelemetry.sdk.trace.data.SpanData;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import org.assertj.core.api.ListAssert;
import org.junit.jupiter.api.extension.AfterAllCallback;
@ -38,7 +36,7 @@ public abstract class InstrumentationExtension
}
@Override
public void beforeAll(ExtensionContext extensionContext) {
public void beforeAll(ExtensionContext extensionContext) throws Exception {
testRunner.beforeTestClass();
}
@ -56,7 +54,7 @@ public abstract class InstrumentationExtension
}
@Override
public void afterAll(ExtensionContext extensionContext) {
public void afterAll(ExtensionContext extensionContext) throws Exception {
testRunner.afterTestClass();
}
@ -70,11 +68,6 @@ public abstract class InstrumentationExtension
return testRunner.getExportedSpans();
}
/** Return a list of all captured traces, where each trace is a sorted list of spans. */
public List<List<SpanData>> traces() {
return TelemetryDataUtil.groupTraces(spans());
}
/** Return a list of all captured metrics. */
public List<MetricData> metrics() {
return testRunner.getExportedMetrics();
@ -100,9 +93,8 @@ public abstract class InstrumentationExtension
}
/**
* Removes all captured telemetry data. After calling this method {@link #spans()}, {@link
* #traces()} and {@link #metrics()} will return empty lists until more telemetry data is
* captured.
* Removes all captured telemetry data. After calling this method {@link #spans()} and {@link
* #metrics()} will return empty lists until more telemetry data is captured.
*/
public void clearData() {
testRunner.clearAllExportedData();
@ -112,25 +104,14 @@ public abstract class InstrumentationExtension
* Wait until at least {@code numberOfTraces} traces are completed and return all captured traces.
* Note that there may be more than {@code numberOfTraces} collected. By default this waits up to
* 20 seconds, then times out.
*
* @throws TimeoutException when the operation times out
* @throws InterruptedException when the current thread is interrupted
*/
public List<List<SpanData>> waitForTraces(int numberOfTraces)
throws TimeoutException, InterruptedException {
return waitForTraces(numberOfTraces, DEFAULT_TRACE_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
public List<List<SpanData>> waitForTraces(int numberOfTraces) {
return testRunner.waitForTraces(numberOfTraces);
}
/**
* Wait until at least {@code numberOfTraces} traces are completed and return all captured traces.
* Note that there may be more than {@code numberOfTraces} collected.
*
* @throws TimeoutException when the operation times out
* @throws InterruptedException when the current thread is interrupted
*/
public List<List<SpanData>> waitForTraces(int numberOfTraces, long timeout, TimeUnit unit)
throws TimeoutException, InterruptedException {
return TelemetryDataUtil.waitForTraces(this::spans, numberOfTraces, timeout, unit);
@SafeVarargs
public final void waitAndAssertTraces(Consumer<TraceAssert>... assertions) {
testRunner.waitAndAssertTraces(assertions);
}
/**
@ -186,4 +167,8 @@ public abstract class InstrumentationExtension
String spanName, ThrowingSupplier<T, E> callback) throws E {
return testRunner.runWithServerSpan(spanName, callback);
}
protected InstrumentationTestRunner getTestRunner() {
return testRunner;
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.testing.junit.http;
import io.opentelemetry.instrumentation.testing.AgentTestRunner;
import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner;
import io.opentelemetry.instrumentation.testing.LibraryTestRunner;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import org.junit.jupiter.api.extension.ExtensionContext;
/**
* A {@link InstrumentationExtension} which sets up infrastructure, such as a test HTTP server, for
* {@link AbstractHttpClientTest}.
*/
public final class HttpClientInstrumentationExtension extends InstrumentationExtension {
/**
* Returns a {@link InstrumentationExtension} to be used with {@link AbstractHttpClientTest} for
* javaagent instrumentation.
*/
public static InstrumentationExtension forAgent() {
return new HttpClientInstrumentationExtension(AgentTestRunner.instance());
}
/**
* Returns a {@link InstrumentationExtension} to be used with {@link AbstractHttpClientTest} for
* library instrumentation.
*/
public static InstrumentationExtension forLibrary() {
return new HttpClientInstrumentationExtension(LibraryTestRunner.instance());
}
private final HttpClientTestServer server;
private HttpClientInstrumentationExtension(InstrumentationTestRunner runner) {
super(runner);
server = new HttpClientTestServer(getOpenTelemetry());
}
@Override
public void beforeAll(ExtensionContext extensionContext) throws Exception {
super.beforeAll(extensionContext);
server.beforeAll(extensionContext);
}
@Override
public void beforeEach(ExtensionContext extensionContext) {
super.beforeEach(extensionContext);
Object testInstance = extensionContext.getRequiredTestInstance();
if (!(testInstance instanceof AbstractHttpClientTest)) {
throw new AssertionError(
"HttpClientLibraryInstrumentationExtension can only be applied to a subclass of "
+ "AbstractHttpClientTest");
}
((AbstractHttpClientTest<?>) testInstance).setTesting(getTestRunner(), server);
}
@Override
public void afterAll(ExtensionContext extensionContext) throws Exception {
super.afterAll(extensionContext);
server.afterAll(extensionContext);
}
}

View File

@ -0,0 +1,122 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.testing.junit.http;
import static io.opentelemetry.api.trace.SpanKind.SERVER;
import static io.opentelemetry.testing.internal.armeria.common.MediaType.PLAIN_TEXT_UTF_8;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.SpanBuilder;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.test.server.http.RequestContextGetter;
import io.opentelemetry.testing.internal.armeria.common.HttpData;
import io.opentelemetry.testing.internal.armeria.common.HttpResponse;
import io.opentelemetry.testing.internal.armeria.common.HttpStatus;
import io.opentelemetry.testing.internal.armeria.common.ResponseHeaders;
import io.opentelemetry.testing.internal.armeria.common.ResponseHeadersBuilder;
import io.opentelemetry.testing.internal.armeria.server.ServerBuilder;
import io.opentelemetry.testing.internal.armeria.server.logging.LoggingService;
import io.opentelemetry.testing.internal.armeria.testing.junit5.server.ServerExtension;
import java.io.FileInputStream;
import java.net.URI;
import java.security.KeyStore;
import java.time.Duration;
import javax.net.ssl.KeyManagerFactory;
public final class HttpClientTestServer extends ServerExtension {
private final OpenTelemetry openTelemetry;
private final Tracer tracer;
public HttpClientTestServer(OpenTelemetry openTelemetry) {
this.openTelemetry = openTelemetry;
tracer = openTelemetry.getTracer("test");
}
@Override
protected void configure(ServerBuilder sb) throws Exception {
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(
new FileInputStream(System.getProperty("javax.net.ssl.trustStore")),
"testing".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keystore, "testing".toCharArray());
sb.http(0)
.https(0)
.tls(kmf)
.service(
"/success",
(ctx, req) -> {
ResponseHeadersBuilder headers = ResponseHeaders.builder(HttpStatus.OK);
String testRequestId = req.headers().get("test-request-id");
if (testRequestId != null) {
headers.set("test-request-id", testRequestId);
}
return HttpResponse.of(headers.build(), HttpData.ofAscii("Hello."));
})
.service(
"/client-error",
(ctx, req) -> HttpResponse.of(HttpStatus.BAD_REQUEST, PLAIN_TEXT_UTF_8, "Invalid RQ"))
.service(
"/error",
(ctx, req) ->
HttpResponse.of(HttpStatus.INTERNAL_SERVER_ERROR, PLAIN_TEXT_UTF_8, "Sorry."))
.service("/redirect", (ctx, req) -> HttpResponse.ofRedirect(HttpStatus.FOUND, "/success"))
.service(
"/another-redirect",
(ctx, req) -> HttpResponse.ofRedirect(HttpStatus.FOUND, "/redirect"))
.service(
"/circular-redirect",
(ctx, req) -> HttpResponse.ofRedirect(HttpStatus.FOUND, "/circular-redirect"))
.service(
"/secured",
(ctx, req) -> {
String auth = req.headers().get(AbstractHttpClientTest.BASIC_AUTH_KEY);
if (auth != null && auth.equals(AbstractHttpClientTest.BASIC_AUTH_VAL)) {
return HttpResponse.of(
HttpStatus.OK, PLAIN_TEXT_UTF_8, "secured string under basic auth");
}
return HttpResponse.of(HttpStatus.UNAUTHORIZED, PLAIN_TEXT_UTF_8, "Unauthorized");
})
.service("/to-secured", (ctx, req) -> HttpResponse.ofRedirect(HttpStatus.FOUND, "/secured"))
.service(
"/read-timeout",
(ctx, req) ->
HttpResponse.delayed(HttpResponse.of(HttpStatus.OK), Duration.ofSeconds(20)))
.decorator(
(delegate, ctx, req) -> {
for (String field : openTelemetry.getPropagators().getTextMapPropagator().fields()) {
if (req.headers().getAll(field).size() > 1) {
throw new AssertionError((Object) ("more than one " + field + " header present"));
}
}
SpanBuilder span =
tracer
.spanBuilder("test-http-server")
.setSpanKind(SERVER)
.setParent(
openTelemetry
.getPropagators()
.getTextMapPropagator()
.extract(Context.current(), ctx, RequestContextGetter.INSTANCE));
String traceRequestId = req.headers().get("test-request-id");
if (traceRequestId != null) {
span.setAttribute("test.request.id", Integer.parseInt(traceRequestId));
}
span.startSpan().end();
return delegate.serve(ctx, req);
})
.decorator(LoggingService.newDecorator());
}
URI resolveAddress(String path) {
return URI.create("http://localhost:" + httpPort() + path);
}
}

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.test.base;
package io.opentelemetry.instrumentation.testing.junit.http;
import java.util.Map;
import java.util.concurrent.ExecutionException;