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