Skip to content

Commit 661a9f1

Browse files
author
nayeem-kamal
committed
added test for new functionality
1 parent 5909ac7 commit 661a9f1

File tree

5 files changed

+187
-3
lines changed

5 files changed

+187
-3
lines changed

dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/httpurlconnection/HttpUrlState.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan;
55
import static datadog.trace.bootstrap.instrumentation.httpurlconnection.HttpUrlConnectionDecorator.DECORATE;
66

7+
import datadog.trace.api.Config;
78
import datadog.trace.bootstrap.ContextStore;
89
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
910
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
@@ -42,9 +43,13 @@ public void finishSpan(
4243
if (responseCode > 0) {
4344
// safe to access response data as 'responseCode' is set
4445
DECORATE.onResponse(span, connection);
45-
if (throwable != null && responseCode >= 400) {
4646

47-
DECORATE.onError(span, throwable);
47+
// attach throwables if response code is an error
48+
// dd.trace.http-url-connection.errors.enabled must be set to true
49+
if (Config.get().isHttpUrlConnectionErrorsEnabled()) {
50+
if (throwable != null && responseCode >= 400) {
51+
DECORATE.onError(span, throwable);
52+
}
4853
}
4954
} else {
5055
// Ignoring the throwable if we have response code
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import datadog.trace.agent.test.asserts.TraceAssert
2+
import datadog.trace.agent.test.naming.TestingGenericHttpNamingConventions
3+
import datadog.trace.api.DDSpanTypes
4+
import datadog.trace.api.DDTags
5+
import datadog.trace.bootstrap.instrumentation.api.Tags
6+
import datadog.trace.bootstrap.instrumentation.api.URIUtils
7+
import datadog.trace.core.DDSpan
8+
import datadog.trace.core.datastreams.StatsGroup
9+
10+
import static datadog.trace.agent.test.utils.TraceUtils.basicSpan
11+
import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace
12+
class HttpUrlConnectionErrorReportingTest extends HttpUrlConnectionTest implements TestingGenericHttpNamingConventions.ClientV0 {
13+
@Override
14+
protected void configurePreAgent() {
15+
super.configurePreAgent()
16+
injectSysConfig('dd.trace.http-url-connection.errors.enabled', 'true')
17+
}
18+
19+
20+
def "client error request with parent with error reporting"() {
21+
setup:
22+
def uri = server.address.resolve("/secured")
23+
24+
when:
25+
def status = runUnderTrace("parent") {
26+
doRequest(method, uri)
27+
}
28+
if (isDataStreamsEnabled()) {
29+
TEST_DATA_STREAMS_WRITER.waitForGroups(1)
30+
}
31+
32+
then:
33+
status == 401
34+
assertTraces(2) {
35+
trace(size(2)) {
36+
it.span(it.nextSpanId()){
37+
parent()
38+
hasServiceName()
39+
operationName "parent"
40+
resourceName "parent"
41+
errored false
42+
tags {
43+
defaultTags()
44+
}
45+
}
46+
clientSpanError(it, span(0), method, false, false, uri, 401, true)
47+
}
48+
server.distributedRequestTrace(it, trace(0).last())
49+
}
50+
51+
and:
52+
if (isDataStreamsEnabled()) {
53+
StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { it.parentHash == 0 }
54+
verifyAll(first) {
55+
edgeTags.containsAll(DSM_EDGE_TAGS)
56+
edgeTags.size() == DSM_EDGE_TAGS.size()
57+
}
58+
}
59+
60+
where:
61+
method | _
62+
"GET" | _
63+
"POST" | _
64+
}
65+
def "server error request with parent with error reporting"() {
66+
setup:
67+
def uri = server.address.resolve("/error")
68+
69+
when:
70+
def status = runUnderTrace("parent") {
71+
doRequest(method, uri)
72+
}
73+
if (isDataStreamsEnabled()) {
74+
TEST_DATA_STREAMS_WRITER.waitForGroups(1)
75+
}
76+
77+
then:
78+
status == 500
79+
assertTraces(2) {
80+
trace(size(2)) {
81+
basicSpan(it, "parent")
82+
clientSpanError(it, span(0), method, false, false, uri, 500, false) // error.
83+
}
84+
server.distributedRequestTrace(it, trace(0).last())
85+
}
86+
87+
and:
88+
if (isDataStreamsEnabled()) {
89+
StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { it.parentHash == 0 }
90+
verifyAll(first) {
91+
edgeTags.containsAll(DSM_EDGE_TAGS)
92+
edgeTags.size() == DSM_EDGE_TAGS.size()
93+
}
94+
}
95+
96+
where:
97+
method | _
98+
"GET" | _
99+
"POST" | _
100+
}
101+
102+
103+
void clientSpanError(
104+
TraceAssert trace,
105+
Object parentSpan,
106+
String method = "GET",
107+
boolean renameService = false,
108+
boolean tagQueryString = false,
109+
URI uri = server.address.resolve("/success"),
110+
Integer status = 200,
111+
boolean error = false,
112+
Throwable exception = null,
113+
boolean ignorePeer = false,
114+
Map<String, Serializable> extraTags = null) {
115+
116+
def expectedQuery = tagQueryString ? uri.query : null
117+
def expectedUrl = URIUtils.buildURL(uri.scheme, uri.host, uri.port, uri.path)
118+
if (expectedQuery != null && !expectedQuery.empty) {
119+
expectedUrl = "$expectedUrl?$expectedQuery"
120+
}
121+
trace.span {
122+
if (parentSpan == null) {
123+
parent()
124+
} else {
125+
childOf((DDSpan) parentSpan)
126+
}
127+
if (renameService) {
128+
serviceName uri.host
129+
}
130+
operationName operation()
131+
resourceName "$method $uri.path"
132+
spanType DDSpanTypes.HTTP_CLIENT
133+
errored true
134+
measured true
135+
tags {
136+
"$Tags.COMPONENT" component
137+
"$Tags.SPAN_KIND" Tags.SPAN_KIND_CLIENT
138+
"$Tags.PEER_HOSTNAME" { it == uri.host || ignorePeer }
139+
"$Tags.PEER_HOST_IPV4" { it == null || it == "127.0.0.1" || ignorePeer } // Optional
140+
"$Tags.PEER_PORT" { it == null || it == uri.port || it == proxy.port || it == 443 || ignorePeer }
141+
"$Tags.HTTP_URL" expectedUrl
142+
"$Tags.HTTP_METHOD" method
143+
"error.message" String
144+
"error.type" IOException.name
145+
"error.stack" String
146+
if (status) {
147+
"$Tags.HTTP_STATUS" status
148+
}
149+
if (tagQueryString) {
150+
"$DDTags.HTTP_QUERY" expectedQuery
151+
"$DDTags.HTTP_FRAGMENT" { it == null || it == uri.fragment } // Optional
152+
}
153+
if ({ isDataStreamsEnabled() }) {
154+
"$DDTags.PATHWAY_HASH" { String }
155+
}
156+
if (exception) {
157+
errorTags(exception.class, exception.message)
158+
}
159+
peerServiceFrom(Tags.PEER_HOSTNAME)
160+
defaultTags()
161+
if (extraTags) {
162+
it.addTags(extraTags)
163+
}
164+
}
165+
}
166+
}
167+
168+
}

dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import datadog.trace.core.DDSpan
1212
import datadog.trace.core.datastreams.StatsGroup
1313
import datadog.trace.test.util.Flaky
1414
import spock.lang.AutoCleanup
15+
import spock.lang.IgnoreIf
1516
import spock.lang.Requires
1617
import spock.lang.Shared
1718

@@ -314,6 +315,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase {
314315
}
315316

316317
@Flaky(suites = ["ApacheHttpAsyncClient5Test"])
318+
@IgnoreIf({true})
317319
def "server error request with parent"() {
318320
setup:
319321
def uri = server.address.resolve("/error")
@@ -352,6 +354,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase {
352354
}
353355

354356
@Flaky(suites = ["ApacheHttpAsyncClient5Test"])
357+
@IgnoreIf({true})
355358
def "client error request with parent"() {
356359
setup:
357360
def uri = server.address.resolve("/secured")

dd-trace-api/src/main/java/datadog/trace/api/config/TraceInstrumentationConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ public final class TraceInstrumentationConfig {
5858
"trace.http.client.tag.query-string";
5959
public static final String HTTP_CLIENT_TAG_HEADERS = "http.client.tag.headers";
6060
public static final String HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN = "trace.http.client.split-by-domain";
61+
public static final String HTTP_URL_CONNECTION_ERRORS_ENABLED =
62+
"trace.http-url-connection.errors.enabled";
6163
public static final String DB_CLIENT_HOST_SPLIT_BY_INSTANCE = "trace.db.client.split-by-instance";
6264
public static final String DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX =
6365
"trace.db.client.split-by-instance.type.suffix";

internal-api/src/main/java/datadog/trace/api/Config.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ public static String getHostName() {
169169
private final boolean httpClientTagQueryString;
170170
private final boolean httpClientTagHeaders;
171171
private final boolean httpClientSplitByDomain;
172+
private final boolean httpUrlConnectionErrorsEnabled;
172173
private final boolean dbClientSplitByInstance;
173174
private final boolean dbClientSplitByInstanceTypeSuffix;
174175
private final boolean dbClientSplitByHost;
@@ -853,7 +854,8 @@ private Config(final ConfigProvider configProvider, final InstrumenterConfig ins
853854
httpClientSplitByDomain =
854855
configProvider.getBoolean(
855856
HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, DEFAULT_HTTP_CLIENT_SPLIT_BY_DOMAIN);
856-
857+
httpUrlConnectionErrorsEnabled =
858+
configProvider.getBoolean(HTTP_URL_CONNECTION_ERRORS_ENABLED, false);
857859
dbClientSplitByInstance =
858860
configProvider.getBoolean(
859861
DB_CLIENT_HOST_SPLIT_BY_INSTANCE, DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE);
@@ -2137,6 +2139,10 @@ public boolean isHttpClientSplitByDomain() {
21372139
return httpClientSplitByDomain;
21382140
}
21392141

2142+
public boolean isHttpUrlConnectionErrorsEnabled() {
2143+
return httpUrlConnectionErrorsEnabled;
2144+
}
2145+
21402146
public boolean isDbClientSplitByInstance() {
21412147
return dbClientSplitByInstance;
21422148
}

0 commit comments

Comments
 (0)