Skip to content

Commit b5b38ee

Browse files
author
Andrew Kent
committed
Mark all http status codes 5xx as an error.
1 parent b5759bd commit b5b38ee

6 files changed

Lines changed: 111 additions & 2 deletions

File tree

dd-java-agent/instrumentation/servlet-3/src/test/groovy/JettyServletTest.groovy

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,46 @@ class JettyServletTest extends AgentTestRunner {
166166
"sync" | "Hello Sync"
167167
}
168168

169+
@Unroll
170+
def "test #path non-throwing-error servlet call"() {
171+
setup:
172+
def request = new Request.Builder()
173+
.url("http://localhost:$PORT/$path?non-throwing-error=true")
174+
.get()
175+
.build()
176+
def response = client.newCall(request).execute()
177+
178+
expect:
179+
response.body().string().trim() != expectedResponse
180+
writer.size() == 2 // second (parent) trace is the okhttp call above...
181+
def trace = writer.firstTrace()
182+
trace.size() == 1
183+
def span = trace[0]
184+
185+
span.context().serviceName == "unnamed-java-app"
186+
span.context().operationName == "servlet.request"
187+
span.context().resourceName == "GET /$path"
188+
span.context().spanType == DDSpanTypes.WEB_SERVLET
189+
span.context().getErrorFlag()
190+
span.context().parentId != 0 // parent should be the okhttp call.
191+
span.context().tags["http.url"] == "http://localhost:$PORT/$path"
192+
span.context().tags["http.method"] == "GET"
193+
span.context().tags["span.kind"] == "server"
194+
span.context().tags["component"] == "java-web-servlet"
195+
span.context().tags["http.status_code"] == 500
196+
span.context().tags["thread.name"] != null
197+
span.context().tags["thread.id"] != null
198+
span.context().tags["error"] == true
199+
span.context().tags["error.msg"] == null
200+
span.context().tags["error.type"] == null
201+
span.context().tags["error.stack"] == null
202+
span.context().tags.size() == 9
203+
204+
where:
205+
path | expectedResponse
206+
"sync" | "Hello Sync"
207+
}
208+
169209
private static int randomOpenPort() {
170210
new ServerSocket(0).withCloseable {
171211
it.setReuseAddress(true)

dd-java-agent/instrumentation/servlet-3/src/test/groovy/TestServlet.groovy

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ class TestServlet {
1313
if (req.getParameter("error") != null) {
1414
throw new RuntimeException("some sync error")
1515
}
16+
if (req.getParameter("non-throwing-error") != null) {
17+
resp.sendError(500, "some sync error")
18+
return
19+
}
1620
resp.writer.print("Hello Sync")
1721
}
1822
}

dd-java-agent/instrumentation/servlet-3/src/test/groovy/TomcatServletTest.groovy

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,46 @@ class TomcatServletTest extends AgentTestRunner {
166166
"sync" | "Hello Sync"
167167
}
168168

169+
@Unroll
170+
def "test #path error servlet call for non-throwing error"() {
171+
setup:
172+
def request = new Request.Builder()
173+
.url("http://localhost:$PORT/$path?non-throwing-error=true")
174+
.get()
175+
.build()
176+
def response = client.newCall(request).execute()
177+
178+
expect:
179+
response.body().string().trim() != expectedResponse
180+
writer.size() == 2 // second (parent) trace is the okhttp call above...
181+
def trace = writer.firstTrace()
182+
trace.size() == 1
183+
def span = trace[0]
184+
185+
span.context().serviceName == "unnamed-java-app"
186+
span.context().operationName == "servlet.request"
187+
span.context().resourceName == "GET /$path"
188+
span.context().spanType == DDSpanTypes.WEB_SERVLET
189+
span.context().getErrorFlag()
190+
span.context().parentId != 0 // parent should be the okhttp call.
191+
span.context().tags["http.url"] == "http://localhost:$PORT/$path"
192+
span.context().tags["http.method"] == "GET"
193+
span.context().tags["span.kind"] == "server"
194+
span.context().tags["component"] == "java-web-servlet"
195+
span.context().tags["http.status_code"] == 500
196+
span.context().tags["thread.name"] != null
197+
span.context().tags["thread.id"] != null
198+
span.context().tags["error"] == true
199+
span.context().tags["error.msg"] == null
200+
span.context().tags["error.type"] == null
201+
span.context().tags["error.stack"] == null
202+
span.context().tags.size() == 9
203+
204+
where:
205+
path | expectedResponse
206+
"sync" | "Hello Sync"
207+
}
208+
169209
private static int randomOpenPort() {
170210
new ServerSocket(0).withCloseable {
171211
it.setReuseAddress(true)

dd-java-agent/instrumentation/spring-web/src/test/groovy/test/SpringBootBasedTest.groovy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,17 +148,17 @@ class SpringBootBasedTest extends AgentTestRunner {
148148
span1.context().operationName == "servlet.request"
149149
span1.context().resourceName == "GET /error"
150150
span1.context().spanType == DDSpanTypes.WEB_SERVLET
151-
!span1.context().getErrorFlag()
152151
span1.context().parentId == 0
153152
span1.context().tags["http.url"] == "http://localhost:$port/error"
154153
span1.context().tags["http.method"] == "GET"
155154
span1.context().tags["span.kind"] == "server"
156155
span1.context().tags["span.type"] == "web"
157156
span1.context().tags["component"] == "java-web-servlet"
158157
span1.context().tags["http.status_code"] == 500
158+
span1.context().getErrorFlag()
159159
span1.context().tags["thread.name"] != null
160160
span1.context().tags["thread.id"] != null
161-
span1.context().tags.size() == 8
161+
span1.context().tags.size() == 9
162162
}
163163

164164
def "validated form"() {

dd-trace-ot/src/main/java/datadog/opentracing/decorators/DDDecoratorsFactory.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public static List<AbstractDecorator> createBuiltinDecorators() {
2525
builtin.add(new OperationDecorator());
2626
builtin.add(new Status404Decorator());
2727
builtin.add(new URLAsResourceName());
28+
builtin.add(new Status5XXDecorator());
2829

2930
return builtin;
3031
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package datadog.opentracing.decorators;
2+
3+
import datadog.opentracing.DDSpanContext;
4+
import io.opentracing.tag.Tags;
5+
6+
/** Mark all 5xx status codes as an error */
7+
public class Status5XXDecorator extends AbstractDecorator {
8+
public Status5XXDecorator() {
9+
super();
10+
this.setMatchingTag(Tags.HTTP_STATUS.getKey());
11+
}
12+
13+
@Override
14+
public boolean afterSetTag(final DDSpanContext context, final String tag, final Object value) {
15+
if (Tags.HTTP_STATUS.getKey().equals(tag)) {
16+
final int responseCode = Integer.parseInt(value.toString());
17+
if (500 <= responseCode && responseCode < 600) {
18+
context.setTag(Tags.ERROR.getKey(), true);
19+
return true;
20+
}
21+
}
22+
return false;
23+
}
24+
}

0 commit comments

Comments
 (0)