convert http url connection test from groovy to java (#7676)
related to #7195
This commit is contained in:
parent
880c6db059
commit
6885c80fef
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import io.opentelemetry.instrumentation.test.AgentTestTrait
|
||||
import io.opentelemetry.instrumentation.test.base.HttpClientTest
|
||||
|
||||
class HttpUrlConnectionResponseCodeOnlyTest extends HttpClientTest<HttpURLConnection> implements AgentTestTrait {
|
||||
|
||||
@Override
|
||||
HttpURLConnection buildRequest(String method, URI uri, Map<String, String> headers) {
|
||||
return uri.toURL().openConnection() as HttpURLConnection
|
||||
}
|
||||
|
||||
@Override
|
||||
int sendRequest(HttpURLConnection connection, String method, URI uri, Map<String, String> headers) {
|
||||
try {
|
||||
connection.setRequestMethod(method)
|
||||
connection.connectTimeout = CONNECT_TIMEOUT_MS
|
||||
if (uri.toString().contains("/read-timeout")) {
|
||||
connection.readTimeout = READ_TIMEOUT_MS
|
||||
}
|
||||
headers.each { connection.setRequestProperty(it.key, it.value) }
|
||||
connection.setRequestProperty("Connection", "close")
|
||||
return connection.getResponseCode()
|
||||
} finally {
|
||||
connection.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
int maxRedirects() {
|
||||
20
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer responseCodeOnRedirectError() {
|
||||
return 302
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean testReusedRequest() {
|
||||
// HttpURLConnection can't be reused
|
||||
return false
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean testCallback() {
|
||||
return false
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean testReadTimeout() {
|
||||
true
|
||||
}
|
||||
}
|
|
@ -1,333 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import io.opentelemetry.api.trace.Span
|
||||
import io.opentelemetry.instrumentation.test.AgentTestTrait
|
||||
import io.opentelemetry.instrumentation.test.base.HttpClientTest
|
||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
|
||||
import spock.lang.Unroll
|
||||
|
||||
import static io.opentelemetry.api.trace.SpanKind.CLIENT
|
||||
import static io.opentelemetry.api.trace.SpanKind.SERVER
|
||||
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
|
||||
|
||||
class HttpUrlConnectionTest extends HttpClientTest<HttpURLConnection> implements AgentTestTrait {
|
||||
|
||||
static final RESPONSE = "Hello."
|
||||
static final STATUS = 200
|
||||
|
||||
@Override
|
||||
HttpURLConnection buildRequest(String method, URI uri, Map<String, String> headers) {
|
||||
return uri.toURL().openConnection() as HttpURLConnection
|
||||
}
|
||||
|
||||
@Override
|
||||
int sendRequest(HttpURLConnection connection, String method, URI uri, Map<String, String> headers) {
|
||||
if (uri.toString().contains("/read-timeout")) {
|
||||
connection.readTimeout = READ_TIMEOUT_MS
|
||||
}
|
||||
try {
|
||||
connection.setRequestMethod(method)
|
||||
headers.each { connection.setRequestProperty(it.key, it.value) }
|
||||
connection.setRequestProperty("Connection", "close")
|
||||
connection.useCaches = true
|
||||
connection.connectTimeout = CONNECT_TIMEOUT_MS
|
||||
def parentSpan = Span.current()
|
||||
def stream = connection.inputStream
|
||||
assert Span.current() == parentSpan
|
||||
stream.readLines()
|
||||
stream.close()
|
||||
return connection.getResponseCode()
|
||||
} finally {
|
||||
connection.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
int maxRedirects() {
|
||||
20
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer responseCodeOnRedirectError() {
|
||||
return 302
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean testReusedRequest() {
|
||||
// HttpURLConnection can't be reused
|
||||
return false
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean testCallback() {
|
||||
return false
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean testReadTimeout() {
|
||||
true
|
||||
}
|
||||
|
||||
@Unroll
|
||||
def "trace request (useCaches: #useCaches)"() {
|
||||
setup:
|
||||
def url = resolveAddress("/success").toURL()
|
||||
runWithSpan("someTrace") {
|
||||
HttpURLConnection connection = url.openConnection()
|
||||
connection.useCaches = useCaches
|
||||
assert Span.current().getSpanContext().isValid()
|
||||
def stream = connection.inputStream
|
||||
def lines = stream.readLines()
|
||||
stream.close()
|
||||
assert connection.getResponseCode() == STATUS
|
||||
assert lines == [RESPONSE]
|
||||
|
||||
// call again to ensure the cycling is ok
|
||||
connection = url.openConnection()
|
||||
connection.useCaches = useCaches
|
||||
assert Span.current().getSpanContext().isValid()
|
||||
// call before input stream to test alternate behavior
|
||||
assert connection.getResponseCode() == STATUS
|
||||
connection.inputStream
|
||||
stream = connection.inputStream // one more to ensure state is working
|
||||
lines = stream.readLines()
|
||||
stream.close()
|
||||
assert lines == [RESPONSE]
|
||||
}
|
||||
|
||||
expect:
|
||||
assertTraces(1) {
|
||||
trace(0, 5) {
|
||||
span(0) {
|
||||
name "someTrace"
|
||||
hasNoParent()
|
||||
attributes {
|
||||
}
|
||||
}
|
||||
span(1) {
|
||||
name "HTTP GET"
|
||||
kind CLIENT
|
||||
childOf span(0)
|
||||
attributes {
|
||||
"$SemanticAttributes.NET_TRANSPORT" IP_TCP
|
||||
"$SemanticAttributes.NET_PEER_NAME" "localhost"
|
||||
"$SemanticAttributes.NET_PEER_PORT" server.httpPort()
|
||||
"$SemanticAttributes.HTTP_URL" "$url"
|
||||
"$SemanticAttributes.HTTP_METHOD" "GET"
|
||||
"$SemanticAttributes.HTTP_STATUS_CODE" STATUS
|
||||
"$SemanticAttributes.HTTP_FLAVOR" "1.1"
|
||||
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
|
||||
}
|
||||
}
|
||||
span(2) {
|
||||
name "test-http-server"
|
||||
kind SERVER
|
||||
childOf span(1)
|
||||
attributes {
|
||||
}
|
||||
}
|
||||
span(3) {
|
||||
name "HTTP GET"
|
||||
kind CLIENT
|
||||
childOf span(0)
|
||||
attributes {
|
||||
"$SemanticAttributes.NET_TRANSPORT" IP_TCP
|
||||
"$SemanticAttributes.NET_PEER_NAME" "localhost"
|
||||
"$SemanticAttributes.NET_PEER_PORT" server.httpPort()
|
||||
"$SemanticAttributes.HTTP_URL" "$url"
|
||||
"$SemanticAttributes.HTTP_METHOD" "GET"
|
||||
"$SemanticAttributes.HTTP_STATUS_CODE" STATUS
|
||||
"$SemanticAttributes.HTTP_FLAVOR" "1.1"
|
||||
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
|
||||
}
|
||||
}
|
||||
span(4) {
|
||||
name "test-http-server"
|
||||
kind SERVER
|
||||
childOf span(3)
|
||||
attributes {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
where:
|
||||
useCaches << [false, true]
|
||||
}
|
||||
|
||||
def "test broken API usage (#iteration)"() {
|
||||
setup:
|
||||
def url = resolveAddress("/success").toURL()
|
||||
HttpURLConnection connection = runWithSpan("someTrace") {
|
||||
HttpURLConnection con = url.openConnection()
|
||||
con.setRequestProperty("Connection", "close")
|
||||
assert Span.current().getSpanContext().isValid()
|
||||
assert con.getResponseCode() == STATUS
|
||||
return con
|
||||
}
|
||||
|
||||
expect:
|
||||
assertTraces(1) {
|
||||
trace(0, 3) {
|
||||
span(0) {
|
||||
name "someTrace"
|
||||
hasNoParent()
|
||||
attributes {
|
||||
}
|
||||
}
|
||||
span(1) {
|
||||
name "HTTP GET"
|
||||
kind CLIENT
|
||||
childOf span(0)
|
||||
attributes {
|
||||
"$SemanticAttributes.NET_PEER_NAME" "localhost"
|
||||
"$SemanticAttributes.NET_PEER_PORT" server.httpPort()
|
||||
"$SemanticAttributes.NET_TRANSPORT" IP_TCP
|
||||
"$SemanticAttributes.HTTP_URL" "$url"
|
||||
"$SemanticAttributes.HTTP_METHOD" "GET"
|
||||
"$SemanticAttributes.HTTP_STATUS_CODE" STATUS
|
||||
"$SemanticAttributes.HTTP_FLAVOR" "1.1"
|
||||
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
|
||||
}
|
||||
}
|
||||
serverSpan(it, 2, span(1))
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
connection.disconnect()
|
||||
|
||||
where:
|
||||
iteration << (1..10)
|
||||
}
|
||||
|
||||
def "test post request"() {
|
||||
setup:
|
||||
def url = resolveAddress("/success").toURL()
|
||||
runWithSpan("someTrace") {
|
||||
HttpURLConnection connection = url.openConnection()
|
||||
connection.setRequestMethod("POST")
|
||||
|
||||
String urlParameters = "q=ASDF&w=&e=&r=12345&t="
|
||||
|
||||
// Send post request
|
||||
connection.setDoOutput(true)
|
||||
DataOutputStream wr = new DataOutputStream(connection.getOutputStream())
|
||||
wr.writeBytes(urlParameters)
|
||||
wr.flush()
|
||||
wr.close()
|
||||
|
||||
assert connection.getResponseCode() == STATUS
|
||||
|
||||
def stream = connection.inputStream
|
||||
def lines = stream.readLines()
|
||||
stream.close()
|
||||
assert lines == [RESPONSE]
|
||||
}
|
||||
|
||||
expect:
|
||||
assertTraces(1) {
|
||||
trace(0, 3) {
|
||||
span(0) {
|
||||
name "someTrace"
|
||||
hasNoParent()
|
||||
attributes {
|
||||
}
|
||||
}
|
||||
span(1) {
|
||||
name "HTTP POST"
|
||||
kind CLIENT
|
||||
childOf span(0)
|
||||
attributes {
|
||||
"$SemanticAttributes.NET_TRANSPORT" IP_TCP
|
||||
"$SemanticAttributes.NET_PEER_NAME" "localhost"
|
||||
"$SemanticAttributes.NET_PEER_PORT" server.httpPort()
|
||||
"$SemanticAttributes.HTTP_URL" "$url"
|
||||
"$SemanticAttributes.HTTP_METHOD" "POST"
|
||||
"$SemanticAttributes.HTTP_STATUS_CODE" STATUS
|
||||
"$SemanticAttributes.HTTP_FLAVOR" "1.1"
|
||||
"$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" Long
|
||||
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
|
||||
}
|
||||
}
|
||||
span(2) {
|
||||
name "test-http-server"
|
||||
kind SERVER
|
||||
childOf span(1)
|
||||
attributes {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def "sun.net.www.protocol.http.HttpURLConnection.getOutputStream should transform GET into POST"() {
|
||||
setup:
|
||||
def url = resolveAddress("/success").toURL()
|
||||
runWithSpan("someTrace") {
|
||||
|
||||
HttpURLConnection connection = url.openConnection()
|
||||
|
||||
def connectionClassName = connection.getClass().getName()
|
||||
|
||||
assert "sun.net.www.protocol.http.HttpURLConnection".equals(connectionClassName)
|
||||
|
||||
connection.setRequestMethod("GET")
|
||||
|
||||
String urlParameters = "q=ASDF&w=&e=&r=12345&t="
|
||||
|
||||
// Send POST request
|
||||
connection.setDoOutput(true)
|
||||
DataOutputStream wr = new DataOutputStream(connection.getOutputStream())
|
||||
wr.writeBytes(urlParameters)
|
||||
wr.flush()
|
||||
wr.close()
|
||||
|
||||
assert connection.getResponseCode() == STATUS
|
||||
|
||||
def stream = connection.inputStream
|
||||
def lines = stream.readLines()
|
||||
stream.close()
|
||||
assert lines == [RESPONSE]
|
||||
}
|
||||
|
||||
expect:
|
||||
assertTraces(1) {
|
||||
trace(0, 3) {
|
||||
span(0) {
|
||||
name "someTrace"
|
||||
hasNoParent()
|
||||
attributes {
|
||||
}
|
||||
}
|
||||
span(1) {
|
||||
name "HTTP POST"
|
||||
kind CLIENT
|
||||
childOf span(0)
|
||||
attributes {
|
||||
"$SemanticAttributes.NET_TRANSPORT" IP_TCP
|
||||
"$SemanticAttributes.NET_PEER_NAME" "localhost"
|
||||
"$SemanticAttributes.NET_PEER_PORT" server.httpPort()
|
||||
"$SemanticAttributes.HTTP_URL" "$url"
|
||||
"$SemanticAttributes.HTTP_METHOD" "POST"
|
||||
"$SemanticAttributes.HTTP_STATUS_CODE" STATUS
|
||||
"$SemanticAttributes.HTTP_FLAVOR" "1.1"
|
||||
"$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" Long
|
||||
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
|
||||
}
|
||||
}
|
||||
span(2) {
|
||||
name "test-http-server"
|
||||
kind SERVER
|
||||
childOf span(1)
|
||||
attributes {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import io.opentelemetry.api.trace.Span
|
||||
import io.opentelemetry.instrumentation.test.AgentTestTrait
|
||||
import io.opentelemetry.instrumentation.test.base.HttpClientTest
|
||||
|
||||
class HttpUrlConnectionUseCachesFalseTest extends HttpClientTest<HttpURLConnection> implements AgentTestTrait {
|
||||
|
||||
@Override
|
||||
HttpURLConnection buildRequest(String method, URI uri, Map<String, String> headers) {
|
||||
return uri.toURL().openConnection() as HttpURLConnection
|
||||
}
|
||||
|
||||
@Override
|
||||
int sendRequest(HttpURLConnection connection, String method, URI uri, Map<String, String> headers) {
|
||||
try {
|
||||
connection.setRequestMethod(method)
|
||||
headers.each { connection.setRequestProperty(it.key, it.value) }
|
||||
connection.setRequestProperty("Connection", "close")
|
||||
connection.useCaches = false
|
||||
connection.connectTimeout = CONNECT_TIMEOUT_MS
|
||||
if (uri.toString().contains("/read-timeout")) {
|
||||
connection.readTimeout = READ_TIMEOUT_MS
|
||||
}
|
||||
def parentSpan = Span.current()
|
||||
def stream = connection.inputStream
|
||||
assert Span.current() == parentSpan
|
||||
stream.readLines()
|
||||
stream.close()
|
||||
return connection.getResponseCode()
|
||||
} finally {
|
||||
connection.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
int maxRedirects() {
|
||||
20
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer responseCodeOnRedirectError() {
|
||||
return 302
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean testReusedRequest() {
|
||||
// HttpURLConnection can't be reused
|
||||
return false
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean testCallback() {
|
||||
return false
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean testReadTimeout() {
|
||||
true
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import io.opentelemetry.api.trace.Span
|
||||
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
|
||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
|
||||
|
||||
import static io.opentelemetry.api.trace.SpanKind.CLIENT
|
||||
import static io.opentelemetry.api.trace.StatusCode.ERROR
|
||||
import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT
|
||||
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
|
||||
|
||||
class UrlConnectionTest extends AgentInstrumentationSpecification {
|
||||
|
||||
def "trace request with connection failure #scheme"() {
|
||||
when:
|
||||
runWithSpan("someTrace") {
|
||||
URLConnection connection = url.openConnection()
|
||||
connection.setConnectTimeout(10000)
|
||||
connection.setReadTimeout(10000)
|
||||
assert Span.current() != null
|
||||
connection.inputStream
|
||||
}
|
||||
|
||||
then:
|
||||
thrown ConnectException
|
||||
|
||||
expect:
|
||||
assertTraces(1) {
|
||||
trace(0, 2) {
|
||||
span(0) {
|
||||
name "someTrace"
|
||||
hasNoParent()
|
||||
status ERROR
|
||||
errorEvent ConnectException, String
|
||||
}
|
||||
span(1) {
|
||||
name "HTTP GET"
|
||||
kind CLIENT
|
||||
childOf span(0)
|
||||
status ERROR
|
||||
errorEvent ConnectException, String
|
||||
attributes {
|
||||
"$SemanticAttributes.NET_TRANSPORT" IP_TCP
|
||||
"$SemanticAttributes.NET_PEER_NAME" "localhost"
|
||||
"$SemanticAttributes.NET_PEER_PORT" UNUSABLE_PORT
|
||||
"$SemanticAttributes.HTTP_URL" "$url"
|
||||
"$SemanticAttributes.HTTP_METHOD" "GET"
|
||||
"$SemanticAttributes.HTTP_FLAVOR" "1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
where:
|
||||
scheme << ["http", "https"]
|
||||
|
||||
url = new URI("$scheme://localhost:$UNUSABLE_PORT").toURL()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.httpurlconnection;
|
||||
|
||||
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest;
|
||||
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class HttpUrlConnectionResponseCodeOnlyTest extends AbstractHttpClientTest<HttpURLConnection> {
|
||||
@RegisterExtension
|
||||
static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent();
|
||||
|
||||
@Override
|
||||
public HttpURLConnection buildRequest(String method, URI uri, Map<String, String> headers)
|
||||
throws Exception {
|
||||
return (HttpURLConnection) uri.toURL().openConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sendRequest(
|
||||
HttpURLConnection connection, String method, URI uri, Map<String, String> headers)
|
||||
throws Exception {
|
||||
try {
|
||||
connection.setRequestMethod(method);
|
||||
connection.setConnectTimeout((int) CONNECTION_TIMEOUT.toMillis());
|
||||
if (uri.toString().contains("/read-timeout")) {
|
||||
connection.setReadTimeout((int) READ_TIMEOUT.toMillis());
|
||||
}
|
||||
|
||||
headers.forEach(connection::setRequestProperty);
|
||||
connection.setRequestProperty("Connection", "close");
|
||||
return connection.getResponseCode();
|
||||
} finally {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maxRedirects() {
|
||||
return 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer responseCodeOnRedirectError() {
|
||||
return 302;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testReusedRequest() {
|
||||
// HttpURLConnection can't be reused
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testCallback() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testReadTimeout() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.httpurlconnection;
|
||||
|
||||
import static io.opentelemetry.api.trace.SpanKind.CLIENT;
|
||||
import static io.opentelemetry.api.trace.SpanKind.SERVER;
|
||||
import static io.opentelemetry.javaagent.instrumentation.httpurlconnection.StreamUtils.readLines;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
|
||||
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.trace.Span;
|
||||
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.semconv.trace.attributes.SemanticAttributes;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.assertj.core.api.AbstractLongAssert;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
class HttpUrlConnectionTest extends AbstractHttpClientTest<HttpURLConnection> {
|
||||
|
||||
@RegisterExtension
|
||||
static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent();
|
||||
|
||||
static final List<String> RESPONSE = Collections.singletonList("Hello.");
|
||||
static final int STATUS = 200;
|
||||
|
||||
@Override
|
||||
public HttpURLConnection buildRequest(String method, URI uri, Map<String, String> headers)
|
||||
throws Exception {
|
||||
return (HttpURLConnection) uri.toURL().openConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sendRequest(
|
||||
HttpURLConnection connection, String method, URI uri, Map<String, String> headers)
|
||||
throws Exception {
|
||||
if (uri.toString().contains("/read-timeout")) {
|
||||
connection.setReadTimeout((int) READ_TIMEOUT.toMillis());
|
||||
}
|
||||
try {
|
||||
connection.setRequestMethod(method);
|
||||
headers.forEach(connection::setRequestProperty);
|
||||
connection.setRequestProperty("Connection", "close");
|
||||
connection.setUseCaches(true);
|
||||
connection.setConnectTimeout((int) CONNECTION_TIMEOUT.toMillis());
|
||||
Span parentSpan = Span.current();
|
||||
InputStream stream = connection.getInputStream();
|
||||
assertThat(Span.current()).isEqualTo(parentSpan);
|
||||
stream.close();
|
||||
return connection.getResponseCode();
|
||||
} finally {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maxRedirects() {
|
||||
return 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer responseCodeOnRedirectError() {
|
||||
return 302;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testReusedRequest() {
|
||||
// HttpURLConnection can't be reused
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testCallback() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testReadTimeout() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {false, true})
|
||||
public void traceRequest(boolean useCache) throws IOException {
|
||||
URL url = resolveAddress("/success").toURL();
|
||||
|
||||
testing.runWithSpan(
|
||||
"someTrace",
|
||||
() -> {
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setUseCaches(useCache);
|
||||
assertThat(Span.current().getSpanContext().isValid()).isTrue();
|
||||
InputStream stream = connection.getInputStream();
|
||||
List<String> lines = readLines(stream);
|
||||
stream.close();
|
||||
assertThat(connection.getResponseCode()).isEqualTo(STATUS);
|
||||
assertThat(lines).isEqualTo(RESPONSE);
|
||||
|
||||
// call again to ensure the cycling is ok
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setUseCaches(useCache);
|
||||
assertThat(Span.current().getSpanContext().isValid()).isTrue();
|
||||
// call before input stream to test alternate behavior
|
||||
assertThat(connection.getResponseCode()).isEqualTo(STATUS);
|
||||
connection.getInputStream();
|
||||
stream = connection.getInputStream(); // one more to ensure state is working
|
||||
lines = readLines(stream);
|
||||
stream.close();
|
||||
assertThat(lines).isEqualTo(RESPONSE);
|
||||
});
|
||||
|
||||
testing.waitAndAssertTraces(
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span -> span.hasName("someTrace").hasNoParent(),
|
||||
span ->
|
||||
span.hasName("HTTP GET")
|
||||
.hasKind(CLIENT)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(SemanticAttributes.NET_TRANSPORT, IP_TCP),
|
||||
equalTo(SemanticAttributes.NET_PEER_NAME, "localhost"),
|
||||
equalTo(SemanticAttributes.NET_PEER_PORT, url.getPort()),
|
||||
equalTo(SemanticAttributes.HTTP_URL, url.toString()),
|
||||
equalTo(SemanticAttributes.HTTP_METHOD, "GET"),
|
||||
equalTo(SemanticAttributes.HTTP_STATUS_CODE, STATUS),
|
||||
equalTo(SemanticAttributes.HTTP_FLAVOR, "1.1"),
|
||||
satisfies(
|
||||
SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
|
||||
AbstractLongAssert::isNotNegative)),
|
||||
span ->
|
||||
span.hasName("test-http-server").hasKind(SERVER).hasParent(trace.getSpan(1)),
|
||||
span ->
|
||||
span.hasName("HTTP GET")
|
||||
.hasKind(CLIENT)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(SemanticAttributes.NET_TRANSPORT, IP_TCP),
|
||||
equalTo(SemanticAttributes.NET_PEER_NAME, "localhost"),
|
||||
equalTo(SemanticAttributes.NET_PEER_PORT, url.getPort()),
|
||||
equalTo(SemanticAttributes.HTTP_URL, url.toString()),
|
||||
equalTo(SemanticAttributes.HTTP_METHOD, "GET"),
|
||||
equalTo(SemanticAttributes.HTTP_STATUS_CODE, STATUS),
|
||||
equalTo(SemanticAttributes.HTTP_FLAVOR, "1.1"),
|
||||
satisfies(
|
||||
SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
|
||||
AbstractLongAssert::isNotNegative)),
|
||||
span ->
|
||||
span.hasName("test-http-server").hasKind(SERVER).hasParent(trace.getSpan(3))));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||
public void testBrokenApiUsage() throws IOException {
|
||||
URL url = resolveAddress("/success").toURL();
|
||||
HttpURLConnection connection =
|
||||
testing.runWithSpan(
|
||||
"someTrace",
|
||||
() -> {
|
||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||
con.setRequestProperty("Connection", "close");
|
||||
assertThat(Span.current().getSpanContext().isValid()).isTrue();
|
||||
assertThat(con.getResponseCode()).isEqualTo(STATUS);
|
||||
return con;
|
||||
});
|
||||
|
||||
testing.waitAndAssertTraces(
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span -> span.hasName("someTrace").hasNoParent(),
|
||||
span ->
|
||||
span.hasName("HTTP GET")
|
||||
.hasKind(CLIENT)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(SemanticAttributes.NET_TRANSPORT, IP_TCP),
|
||||
equalTo(SemanticAttributes.NET_PEER_NAME, "localhost"),
|
||||
equalTo(SemanticAttributes.NET_PEER_PORT, url.getPort()),
|
||||
equalTo(SemanticAttributes.HTTP_URL, url.toString()),
|
||||
equalTo(SemanticAttributes.HTTP_METHOD, "GET"),
|
||||
equalTo(SemanticAttributes.HTTP_STATUS_CODE, STATUS),
|
||||
equalTo(SemanticAttributes.HTTP_FLAVOR, "1.1"),
|
||||
satisfies(
|
||||
SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
|
||||
AbstractLongAssert::isNotNegative)),
|
||||
span ->
|
||||
span.hasName("test-http-server").hasKind(SERVER).hasParent(trace.getSpan(1))));
|
||||
|
||||
connection.disconnect();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPostRequest() throws IOException {
|
||||
URL url = resolveAddress("/success").toURL();
|
||||
testing.runWithSpan(
|
||||
"someTrace",
|
||||
() -> {
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
|
||||
String urlParameters = "q=ASDF&w=&e=&r=12345&t=";
|
||||
|
||||
// Send post request
|
||||
connection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
|
||||
wr.writeBytes(urlParameters);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
|
||||
assertThat(connection.getResponseCode()).isEqualTo(STATUS);
|
||||
|
||||
InputStream stream = connection.getInputStream();
|
||||
List<String> lines = readLines(stream);
|
||||
stream.close();
|
||||
assertThat(lines).isEqualTo(RESPONSE);
|
||||
});
|
||||
|
||||
testing.waitAndAssertTraces(
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span -> span.hasName("someTrace").hasNoParent(),
|
||||
span ->
|
||||
span.hasName("HTTP POST")
|
||||
.hasKind(CLIENT)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(SemanticAttributes.NET_TRANSPORT, IP_TCP),
|
||||
equalTo(SemanticAttributes.NET_PEER_NAME, "localhost"),
|
||||
equalTo(SemanticAttributes.NET_PEER_PORT, url.getPort()),
|
||||
equalTo(SemanticAttributes.HTTP_URL, url.toString()),
|
||||
equalTo(SemanticAttributes.HTTP_METHOD, "POST"),
|
||||
equalTo(SemanticAttributes.HTTP_STATUS_CODE, STATUS),
|
||||
equalTo(SemanticAttributes.HTTP_FLAVOR, "1.1"),
|
||||
satisfies(
|
||||
SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH,
|
||||
AbstractLongAssert::isNotNegative),
|
||||
satisfies(
|
||||
SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
|
||||
AbstractLongAssert::isNotNegative)),
|
||||
span ->
|
||||
span.hasName("test-http-server").hasKind(SERVER).hasParent(trace.getSpan(1))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getOutputStreamShouldTransformGetIntoPost() throws IOException {
|
||||
URL url = resolveAddress("/success").toURL();
|
||||
testing.runWithSpan(
|
||||
"someTrace",
|
||||
() -> {
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
assertThat(connection.getClass().getName())
|
||||
.isEqualTo("sun.net.www.protocol.http.HttpURLConnection");
|
||||
|
||||
connection.setRequestMethod("GET");
|
||||
|
||||
String urlParameters = "q=ASDF&w=&e=&r=12345&t=";
|
||||
|
||||
// Send POST request
|
||||
connection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
|
||||
wr.writeBytes(urlParameters);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
|
||||
assertThat(connection.getResponseCode()).isEqualTo(STATUS);
|
||||
|
||||
InputStream stream = connection.getInputStream();
|
||||
List<String> lines = readLines(stream);
|
||||
stream.close();
|
||||
assertThat(lines).isEqualTo(RESPONSE);
|
||||
});
|
||||
|
||||
testing.waitAndAssertTraces(
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span -> span.hasName("someTrace").hasNoParent(),
|
||||
span ->
|
||||
span.hasName("HTTP POST")
|
||||
.hasKind(CLIENT)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(SemanticAttributes.NET_TRANSPORT, IP_TCP),
|
||||
equalTo(SemanticAttributes.NET_PEER_NAME, "localhost"),
|
||||
equalTo(SemanticAttributes.NET_PEER_PORT, url.getPort()),
|
||||
equalTo(SemanticAttributes.HTTP_URL, url.toString()),
|
||||
equalTo(SemanticAttributes.HTTP_METHOD, "POST"),
|
||||
equalTo(SemanticAttributes.HTTP_STATUS_CODE, STATUS),
|
||||
equalTo(SemanticAttributes.HTTP_FLAVOR, "1.1"),
|
||||
satisfies(
|
||||
SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH,
|
||||
AbstractLongAssert::isNotNegative),
|
||||
satisfies(
|
||||
SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
|
||||
AbstractLongAssert::isNotNegative)),
|
||||
span ->
|
||||
span.hasName("test-http-server").hasKind(SERVER).hasParent(trace.getSpan(1))));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.httpurlconnection;
|
||||
|
||||
import static io.opentelemetry.javaagent.instrumentation.httpurlconnection.StreamUtils.readLines;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.trace.Span;
|
||||
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest;
|
||||
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class HttpUrlConnectionUseCachesFalseTest extends AbstractHttpClientTest<HttpURLConnection> {
|
||||
@RegisterExtension
|
||||
static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent();
|
||||
|
||||
@Override
|
||||
public HttpURLConnection buildRequest(String method, URI uri, Map<String, String> headers)
|
||||
throws Exception {
|
||||
return (HttpURLConnection) uri.toURL().openConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sendRequest(
|
||||
HttpURLConnection connection, String method, URI uri, Map<String, String> headers)
|
||||
throws Exception {
|
||||
try {
|
||||
connection.setRequestMethod(method);
|
||||
headers.forEach(connection::setRequestProperty);
|
||||
connection.setRequestProperty("Connection", "close");
|
||||
connection.setUseCaches(false);
|
||||
connection.setConnectTimeout((int) CONNECTION_TIMEOUT.toMillis());
|
||||
if (uri.toString().contains("/read-timeout")) {
|
||||
connection.setReadTimeout((int) READ_TIMEOUT.toMillis());
|
||||
}
|
||||
Span parentSpan = Span.current();
|
||||
InputStream stream = connection.getInputStream();
|
||||
assertThat(Span.current()).isEqualTo(parentSpan);
|
||||
readLines(stream);
|
||||
stream.close();
|
||||
return connection.getResponseCode();
|
||||
} finally {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maxRedirects() {
|
||||
return 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer responseCodeOnRedirectError() {
|
||||
return 302;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testReusedRequest() {
|
||||
// HttpURLConnection can't be reused
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testCallback() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testReadTimeout() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.httpurlconnection;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
final class StreamUtils {
|
||||
static List<String> readLines(InputStream stream) throws IOException {
|
||||
List<String> lines = new ArrayList<>();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, UTF_8));
|
||||
while (reader.ready()) {
|
||||
String line = reader.readLine();
|
||||
if (!Strings.isNullOrEmpty(line)) {
|
||||
lines.add(line);
|
||||
}
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
private StreamUtils() {}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.httpurlconnection;
|
||||
|
||||
import static io.opentelemetry.api.trace.SpanKind.CLIENT;
|
||||
import static io.opentelemetry.api.trace.SpanKind.INTERNAL;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
|
||||
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.catchThrowable;
|
||||
|
||||
import io.opentelemetry.api.trace.Span;
|
||||
import io.opentelemetry.instrumentation.test.utils.PortUtils;
|
||||
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
|
||||
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||
import io.opentelemetry.sdk.trace.data.StatusData;
|
||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
class UrlConnectionTest {
|
||||
@RegisterExtension
|
||||
static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"http", "https"})
|
||||
public void traceRequestWithConnectionFailure(String scheme) {
|
||||
String uri = scheme + "://localhost:" + PortUtils.UNUSABLE_PORT;
|
||||
|
||||
Throwable thrown =
|
||||
catchThrowable(
|
||||
() ->
|
||||
testing.runWithSpan(
|
||||
"someTrace",
|
||||
() -> {
|
||||
URL url = new URI(uri).toURL();
|
||||
URLConnection connection = url.openConnection();
|
||||
connection.setConnectTimeout(10000);
|
||||
connection.setReadTimeout(10000);
|
||||
assertThat(Span.current().getSpanContext().isValid()).isTrue();
|
||||
connection.getInputStream();
|
||||
}));
|
||||
|
||||
testing.waitAndAssertTraces(
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span ->
|
||||
span.hasName("someTrace")
|
||||
.hasKind(INTERNAL)
|
||||
.hasNoParent()
|
||||
.hasStatus(StatusData.error())
|
||||
.hasException(thrown),
|
||||
span ->
|
||||
span.hasName("HTTP GET")
|
||||
.hasKind(CLIENT)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasStatus(StatusData.error())
|
||||
.hasException(thrown)
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(SemanticAttributes.NET_TRANSPORT, IP_TCP),
|
||||
equalTo(SemanticAttributes.NET_PEER_NAME, "localhost"),
|
||||
equalTo(SemanticAttributes.NET_PEER_PORT, PortUtils.UNUSABLE_PORT),
|
||||
equalTo(SemanticAttributes.HTTP_URL, uri),
|
||||
equalTo(SemanticAttributes.HTTP_METHOD, "GET"),
|
||||
equalTo(SemanticAttributes.HTTP_FLAVOR, "1.1"))));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue