Skip to content

Commit 3fd498d

Browse files
committed
Get and test metrics for injection failures and skips
1 parent 3d4ac53 commit 3fd498d

File tree

4 files changed

+226
-32
lines changed

4 files changed

+226
-32
lines changed

dd-java-agent/instrumentation/servlet/request-3/src/main/java/datadog/trace/instrumentation/servlet3/RumHttpServletResponseWrapper.java

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,24 @@ public ServletOutputStream getOutputStream() throws IOException {
4545
return outputStream;
4646
}
4747
if (!shouldInject) {
48+
RumInjector.getTelemetryCollector().onInjectionSkipped();
4849
return super.getOutputStream();
4950
}
50-
String encoding = getCharacterEncoding();
51-
if (encoding == null) {
52-
encoding = Charset.defaultCharset().name();
51+
try {
52+
String encoding = getCharacterEncoding();
53+
if (encoding == null) {
54+
encoding = Charset.defaultCharset().name();
55+
}
56+
outputStream =
57+
new WrappedServletOutputStream(
58+
super.getOutputStream(),
59+
rumInjector.getMarkerBytes(encoding),
60+
rumInjector.getSnippetBytes(encoding),
61+
this::onInjected);
62+
} catch (Exception e) {
63+
RumInjector.getTelemetryCollector().onInjectionFailed();
64+
throw e;
5365
}
54-
outputStream =
55-
new WrappedServletOutputStream(
56-
super.getOutputStream(),
57-
rumInjector.getMarkerBytes(encoding),
58-
rumInjector.getSnippetBytes(encoding),
59-
this::onInjected);
6066

6167
return outputStream;
6268
}
@@ -67,15 +73,21 @@ public PrintWriter getWriter() throws IOException {
6773
return printWriter;
6874
}
6975
if (!shouldInject) {
76+
RumInjector.getTelemetryCollector().onInjectionSkipped();
7077
return super.getWriter();
7178
}
72-
wrappedPipeWriter =
73-
new InjectingPipeWriter(
74-
super.getWriter(),
75-
rumInjector.getMarkerChars(),
76-
rumInjector.getSnippetChars(),
77-
this::onInjected);
78-
printWriter = new PrintWriter(wrappedPipeWriter);
79+
try {
80+
wrappedPipeWriter =
81+
new InjectingPipeWriter(
82+
super.getWriter(),
83+
rumInjector.getMarkerChars(),
84+
rumInjector.getSnippetChars(),
85+
this::onInjected);
86+
printWriter = new PrintWriter(wrappedPipeWriter);
87+
} catch (Exception e) {
88+
RumInjector.getTelemetryCollector().onInjectionFailed();
89+
throw e;
90+
}
7991

8092
return printWriter;
8193
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import datadog.trace.agent.test.AgentTestRunner
2+
import datadog.trace.api.rum.RumInjector
3+
import datadog.trace.api.rum.RumTelemetryCollector
4+
import datadog.trace.instrumentation.servlet3.RumHttpServletResponseWrapper
5+
import spock.lang.Subject
6+
7+
import javax.servlet.http.HttpServletResponse
8+
9+
class RumHttpServletResponseWrapperTest extends AgentTestRunner {
10+
11+
def mockResponse = Mock(HttpServletResponse)
12+
def mockTelemetryCollector = Mock(RumTelemetryCollector)
13+
14+
@Subject
15+
RumHttpServletResponseWrapper wrapper
16+
17+
void setup() {
18+
wrapper = new RumHttpServletResponseWrapper(mockResponse)
19+
RumInjector.setTelemetryCollector(mockTelemetryCollector)
20+
}
21+
22+
void cleanup() {
23+
RumInjector.setTelemetryCollector(RumTelemetryCollector.NO_OP)
24+
}
25+
26+
void 'onInjected calls telemetry collector onInjectionSucceed'() {
27+
when:
28+
wrapper.onInjected()
29+
30+
then:
31+
1 * mockTelemetryCollector.onInjectionSucceed()
32+
}
33+
34+
void 'getOutputStream with non-HTML content reports skipped'() {
35+
setup:
36+
wrapper.setContentType("text/plain")
37+
38+
when:
39+
wrapper.getOutputStream()
40+
41+
then:
42+
1 * mockTelemetryCollector.onInjectionSkipped()
43+
1 * mockResponse.getOutputStream()
44+
}
45+
46+
void 'getWriter with non-HTML content reports skipped'() {
47+
setup:
48+
wrapper.setContentType("text/plain")
49+
50+
when:
51+
wrapper.getWriter()
52+
53+
then:
54+
1 * mockTelemetryCollector.onInjectionSkipped()
55+
1 * mockResponse.getWriter()
56+
}
57+
58+
void 'getOutputStream exception reports failure'() {
59+
setup:
60+
wrapper.setContentType("text/html")
61+
mockResponse.getOutputStream() >> { throw new IOException("stream error") }
62+
63+
when:
64+
try {
65+
wrapper.getOutputStream()
66+
} catch (IOException ignored) {}
67+
68+
then:
69+
1 * mockTelemetryCollector.onInjectionFailed()
70+
}
71+
72+
void 'getWriter exception reports failure'() {
73+
setup:
74+
wrapper.setContentType("text/html")
75+
mockResponse.getWriter() >> { throw new IOException("writer error") }
76+
77+
when:
78+
try {
79+
wrapper.getWriter()
80+
} catch (IOException ignored) {}
81+
82+
then:
83+
1 * mockTelemetryCollector.onInjectionFailed()
84+
}
85+
}

dd-java-agent/instrumentation/servlet/request-5/src/main/java/datadog/trace/instrumentation/servlet5/RumHttpServletResponseWrapper.java

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,24 @@ public ServletOutputStream getOutputStream() throws IOException {
2727
return outputStream;
2828
}
2929
if (!shouldInject) {
30+
RumInjector.getTelemetryCollector().onInjectionSkipped();
3031
return super.getOutputStream();
3132
}
32-
String encoding = getCharacterEncoding();
33-
if (encoding == null) {
34-
encoding = Charset.defaultCharset().name();
33+
try {
34+
String encoding = getCharacterEncoding();
35+
if (encoding == null) {
36+
encoding = Charset.defaultCharset().name();
37+
}
38+
outputStream =
39+
new WrappedServletOutputStream(
40+
super.getOutputStream(),
41+
rumInjector.getMarkerBytes(encoding),
42+
rumInjector.getSnippetBytes(encoding),
43+
this::onInjected);
44+
} catch (Exception e) {
45+
RumInjector.getTelemetryCollector().onInjectionFailed();
46+
throw e;
3547
}
36-
outputStream =
37-
new WrappedServletOutputStream(
38-
super.getOutputStream(),
39-
rumInjector.getMarkerBytes(encoding),
40-
rumInjector.getSnippetBytes(encoding),
41-
this::onInjected);
4248
return outputStream;
4349
}
4450

@@ -48,15 +54,21 @@ public PrintWriter getWriter() throws IOException {
4854
return printWriter;
4955
}
5056
if (!shouldInject) {
57+
RumInjector.getTelemetryCollector().onInjectionSkipped();
5158
return super.getWriter();
5259
}
53-
wrappedPipeWriter =
54-
new InjectingPipeWriter(
55-
super.getWriter(),
56-
rumInjector.getMarkerChars(),
57-
rumInjector.getSnippetChars(),
58-
this::onInjected);
59-
printWriter = new PrintWriter(wrappedPipeWriter);
60+
try {
61+
wrappedPipeWriter =
62+
new InjectingPipeWriter(
63+
super.getWriter(),
64+
rumInjector.getMarkerChars(),
65+
rumInjector.getSnippetChars(),
66+
this::onInjected);
67+
printWriter = new PrintWriter(wrappedPipeWriter);
68+
} catch (Exception e) {
69+
RumInjector.getTelemetryCollector().onInjectionFailed();
70+
throw e;
71+
}
6072

6173
return printWriter;
6274
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import datadog.trace.agent.test.AgentTestRunner
2+
import datadog.trace.api.rum.RumInjector
3+
import datadog.trace.api.rum.RumTelemetryCollector
4+
import datadog.trace.instrumentation.servlet5.RumHttpServletResponseWrapper
5+
import spock.lang.Subject
6+
7+
import jakarta.servlet.http.HttpServletResponse
8+
9+
class RumHttpServletResponseWrapperTest extends AgentTestRunner {
10+
11+
def mockResponse = Mock(HttpServletResponse)
12+
def mockTelemetryCollector = Mock(RumTelemetryCollector)
13+
14+
@Subject
15+
RumHttpServletResponseWrapper wrapper
16+
17+
void setup() {
18+
wrapper = new RumHttpServletResponseWrapper(mockResponse)
19+
RumInjector.setTelemetryCollector(mockTelemetryCollector)
20+
}
21+
22+
void cleanup() {
23+
RumInjector.setTelemetryCollector(RumTelemetryCollector.NO_OP)
24+
}
25+
26+
void 'onInjected calls telemetry collector onInjectionSucceed'() {
27+
when:
28+
wrapper.onInjected()
29+
30+
then:
31+
1 * mockTelemetryCollector.onInjectionSucceed()
32+
}
33+
34+
void 'getOutputStream with non-HTML content reports skipped'() {
35+
setup:
36+
wrapper.setContentType("text/plain")
37+
38+
when:
39+
wrapper.getOutputStream()
40+
41+
then:
42+
1 * mockTelemetryCollector.onInjectionSkipped()
43+
1 * mockResponse.getOutputStream()
44+
}
45+
46+
void 'getWriter with non-HTML content reports skipped'() {
47+
setup:
48+
wrapper.setContentType("text/plain")
49+
50+
when:
51+
wrapper.getWriter()
52+
53+
then:
54+
1 * mockTelemetryCollector.onInjectionSkipped()
55+
1 * mockResponse.getWriter()
56+
}
57+
58+
void 'getOutputStream exception reports failure'() {
59+
setup:
60+
wrapper.setContentType("text/html")
61+
mockResponse.getOutputStream() >> { throw new IOException("stream error") }
62+
63+
when:
64+
try {
65+
wrapper.getOutputStream()
66+
} catch (IOException ignored) {}
67+
68+
then:
69+
1 * mockTelemetryCollector.onInjectionFailed()
70+
}
71+
72+
void 'getWriter exception reports failure'() {
73+
setup:
74+
wrapper.setContentType("text/html")
75+
mockResponse.getWriter() >> { throw new IOException("writer error") }
76+
77+
when:
78+
try {
79+
wrapper.getWriter()
80+
} catch (IOException ignored) {}
81+
82+
then:
83+
1 * mockTelemetryCollector.onInjectionFailed()
84+
}
85+
}

0 commit comments

Comments
 (0)