opentelemetry-java-instrume.../dd-java-agent/instrumentation/http-url-connection/src/test/groovy/HttpUrlConnectionTest.groovy

456 lines
14 KiB
Groovy

import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.api.DDSpanTypes
import datadog.trace.api.DDTags
import io.opentracing.tag.Tags
import io.opentracing.util.GlobalTracer
import org.springframework.web.client.RestTemplate
import spock.lang.AutoCleanup
import spock.lang.Shared
import static datadog.trace.agent.test.TestUtils.runUnderTrace
import static datadog.trace.agent.test.server.http.TestHttpServer.httpServer
class HttpUrlConnectionTest extends AgentTestRunner {
static {
System.setProperty("dd.integration.httpurlconnection.enabled", "true")
}
static final RESPONSE = "<html><body><h1>Hello test.</h1>"
static final STATUS = 202
@AutoCleanup
@Shared
def server = httpServer {
handlers {
all {
handleDistributedRequest()
response.status(STATUS).send(RESPONSE)
}
}
}
def "trace request with propagation (useCaches: #useCaches)"() {
setup:
runUnderTrace("someTrace") {
HttpURLConnection connection = server.address.toURL().openConnection()
connection.useCaches = useCaches
assert GlobalTracer.get().scopeManager().active() != null
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 = server.getAddress().toURL().openConnection()
connection.useCaches = useCaches
assert GlobalTracer.get().scopeManager().active() != null
assert connection.getResponseCode() == STATUS // call before input stream to test alternate behavior
connection.inputStream
stream = connection.inputStream // one more to ensure state is working
lines = stream.readLines()
stream.close()
assert lines == [RESPONSE]
}
expect:
assertTraces(3) {
server.distributedRequestTrace(it, 0, TEST_WRITER[2][2])
server.distributedRequestTrace(it, 1, TEST_WRITER[2][1])
trace(2, 3) {
span(0) {
operationName "someTrace"
parent()
errored false
tags {
defaultTags()
}
}
span(1) {
operationName "http.request.input-stream"
childOf span(0)
errored false
tags {
"$Tags.COMPONENT.key" "HttpURLConnection"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
"$Tags.HTTP_URL.key" "$server.address"
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.HTTP_STATUS.key" STATUS
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
defaultTags()
}
}
span(2) {
operationName "http.request.input-stream"
childOf span(0)
errored false
tags {
"$Tags.COMPONENT.key" "HttpURLConnection"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
"$Tags.HTTP_URL.key" "$server.address"
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.HTTP_STATUS.key" STATUS
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
defaultTags()
}
}
}
}
where:
useCaches << [false, true]
}
def "trace request without propagation (useCaches: #useCaches)"() {
setup:
runUnderTrace("someTrace") {
HttpURLConnection connection = server.address.toURL().openConnection()
connection.useCaches = useCaches
connection.addRequestProperty("is-dd-server", "false")
assert GlobalTracer.get().scopeManager().active() != null
def stream = connection.inputStream
connection.inputStream // one more to ensure state is working
def lines = stream.readLines()
stream.close()
assert connection.getResponseCode() == STATUS
assert lines == [RESPONSE]
// call again to ensure the cycling is ok
connection = server.getAddress().toURL().openConnection()
connection.useCaches = useCaches
connection.addRequestProperty("is-dd-server", "false")
assert GlobalTracer.get().scopeManager().active() != null
assert connection.getResponseCode() == STATUS // call before input stream to test alternate behavior
stream = connection.inputStream
lines = stream.readLines()
stream.close()
assert lines == [RESPONSE]
}
expect:
assertTraces(1) {
trace(0, 3) {
span(0) {
operationName "someTrace"
parent()
errored false
tags {
defaultTags()
}
}
span(1) {
operationName "http.request.input-stream"
childOf span(0)
errored false
tags {
"$Tags.COMPONENT.key" "HttpURLConnection"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
"$Tags.HTTP_URL.key" "$server.address"
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.HTTP_STATUS.key" STATUS
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
defaultTags()
}
}
span(2) {
operationName "http.request.input-stream"
childOf span(0)
errored false
tags {
"$Tags.COMPONENT.key" "HttpURLConnection"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
"$Tags.HTTP_URL.key" "$server.address"
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.HTTP_STATUS.key" STATUS
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
defaultTags()
}
}
}
}
where:
useCaches << [false, true]
}
def "test response code"() {
setup:
runUnderTrace("someTrace") {
HttpURLConnection connection = server.address.toURL().openConnection()
connection.setRequestMethod("HEAD")
connection.addRequestProperty("is-dd-server", "false")
assert GlobalTracer.get().scopeManager().active() != null
assert connection.getResponseCode() == STATUS
}
expect:
assertTraces(1) {
trace(0, 2) {
span(0) {
operationName "someTrace"
parent()
errored false
tags {
defaultTags()
}
}
span(1) {
operationName "http.request.input-stream"
childOf span(0)
errored false
tags {
"$Tags.COMPONENT.key" "HttpURLConnection"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
"$Tags.HTTP_URL.key" "$server.address"
"$Tags.HTTP_METHOD.key" "HEAD"
"$Tags.HTTP_STATUS.key" STATUS
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
defaultTags()
}
}
}
}
}
def "test broken API usage"() {
setup:
HttpURLConnection conn = runUnderTrace("someTrace") {
HttpURLConnection connection = server.address.toURL().openConnection()
connection.setRequestProperty("Connection", "close")
connection.addRequestProperty("is-dd-server", "false")
assert GlobalTracer.get().scopeManager().active() != null
assert connection.getResponseCode() == STATUS
return connection
}
expect:
assertTraces(1) {
trace(0, 2) {
span(0) {
operationName "someTrace"
parent()
errored false
tags {
defaultTags()
}
}
span(1) {
operationName "http.request.input-stream"
childOf span(0)
errored false
tags {
"$Tags.COMPONENT.key" "HttpURLConnection"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
"$Tags.HTTP_URL.key" "$server.address"
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.HTTP_STATUS.key" STATUS
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
defaultTags()
}
}
}
}
cleanup:
conn.disconnect()
where:
iteration << (1..10)
}
def "test post request"() {
setup:
runUnderTrace("someTrace") {
HttpURLConnection connection = server.address.toURL().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(2) {
server.distributedRequestTrace(it, 0, TEST_WRITER[1][1])
trace(1, 3) {
span(0) {
operationName "someTrace"
parent()
errored false
tags {
defaultTags()
}
}
span(1) {
operationName "http.request.input-stream"
childOf span(0)
errored false
tags {
"$Tags.COMPONENT.key" "HttpURLConnection"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
"$Tags.HTTP_URL.key" "$server.address"
"$Tags.HTTP_METHOD.key" "POST"
"$Tags.HTTP_STATUS.key" STATUS
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
defaultTags()
}
}
span(2) {
operationName "http.request.output-stream"
childOf span(0)
errored false
tags {
"$Tags.COMPONENT.key" "HttpURLConnection"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
"$Tags.HTTP_URL.key" "$server.address"
"$Tags.HTTP_METHOD.key" "POST"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
defaultTags()
}
}
}
}
}
def "request that looks like a trace submission is ignored"() {
setup:
runUnderTrace("someTrace") {
HttpURLConnection connection = server.address.toURL().openConnection()
connection.addRequestProperty("Datadog-Meta-Lang", "false")
connection.addRequestProperty("is-dd-server", "false")
def stream = connection.inputStream
def lines = stream.readLines()
stream.close()
assert connection.getResponseCode() == STATUS
assert lines == [RESPONSE]
}
expect:
assertTraces(1) {
trace(0, 1) {
span(0) {
operationName "someTrace"
parent()
errored false
tags {
defaultTags()
}
}
}
}
}
def "top level httpurlconnection tracing disabled"() {
setup:
HttpURLConnection connection = server.address.toURL().openConnection()
connection.addRequestProperty("is-dd-server", "false")
def stream = connection.inputStream
def lines = stream.readLines()
stream.close()
assert connection.getResponseCode() == STATUS
assert lines == [RESPONSE]
expect:
assertTraces(0) {}
}
def "rest template"() {
setup:
runUnderTrace("someTrace") {
RestTemplate restTemplate = new RestTemplate()
String res = restTemplate.postForObject(server.address.toString(), "Hello", String)
assert res == "$RESPONSE"
}
expect:
assertTraces(2) {
server.distributedRequestTrace(it, 0, TEST_WRITER[1][2])
trace(1, 4) {
span(0) {
operationName "someTrace"
parent()
errored false
tags {
defaultTags()
}
}
span(1) {
operationName "http.request.input-stream"
childOf span(0)
errored false
tags {
"$Tags.COMPONENT.key" "HttpURLConnection"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
"$Tags.HTTP_URL.key" "$server.address"
"$Tags.HTTP_METHOD.key" "POST"
"$Tags.HTTP_STATUS.key" STATUS
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
defaultTags()
}
}
span(2) {
operationName "http.request.output-stream"
childOf span(0)
errored false
tags {
"$Tags.COMPONENT.key" "HttpURLConnection"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
"$Tags.HTTP_URL.key" "$server.address"
"$Tags.HTTP_METHOD.key" "POST"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
defaultTags()
}
}
span(3) {
operationName "http.request.connect"
childOf span(0)
errored false
tags {
"$Tags.COMPONENT.key" "HttpURLConnection"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
"$Tags.HTTP_URL.key" "$server.address"
"$Tags.HTTP_METHOD.key" "POST"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
defaultTags()
}
}
}
}
}
}