|
16 | 16 |
|
17 | 17 | package io.opentelemetry.javaagent.instrumentation.hypertrace.jaxrs.v2_0; |
18 | 18 |
|
19 | | -import io.opentelemetry.api.trace.Span; |
20 | | -import io.opentelemetry.sdk.trace.data.SpanData; |
21 | | -import java.io.IOException; |
22 | | -import java.io.OutputStream; |
23 | | -import java.lang.annotation.Annotation; |
24 | | -import java.lang.reflect.Type; |
25 | | -import java.util.List; |
26 | | -import java.util.concurrent.ExecutionException; |
27 | | -import java.util.concurrent.Future; |
28 | | -import java.util.concurrent.TimeoutException; |
29 | | -import javax.ws.rs.WebApplicationException; |
| 19 | +import java.util.Map; |
30 | 20 | import javax.ws.rs.client.Client; |
31 | 21 | import javax.ws.rs.client.ClientBuilder; |
32 | 22 | import javax.ws.rs.client.Entity; |
33 | | -import javax.ws.rs.client.WebTarget; |
| 23 | +import javax.ws.rs.client.Invocation; |
34 | 24 | import javax.ws.rs.core.MediaType; |
35 | | -import javax.ws.rs.core.MultivaluedHashMap; |
36 | | -import javax.ws.rs.core.MultivaluedMap; |
37 | | -import javax.ws.rs.core.Response; |
38 | | -import javax.ws.rs.ext.MessageBodyWriter; |
39 | | -import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes; |
40 | | -import org.hypertrace.agent.testing.AbstractInstrumenterTest; |
41 | | -import org.hypertrace.agent.testing.TestHttpServer; |
42 | | -import org.hypertrace.agent.testing.TestHttpServer.GetJsonHandler; |
43 | | -import org.junit.jupiter.api.AfterAll; |
44 | | -import org.junit.jupiter.api.Assertions; |
45 | | -import org.junit.jupiter.api.BeforeAll; |
46 | | -import org.junit.jupiter.api.Test; |
47 | | - |
48 | | -public class JaxrsClientBodyInstrumentationTest extends AbstractInstrumenterTest { |
49 | | - |
50 | | - private static final String JSON = "{\"id\":1,\"name\":\"John\"}"; |
51 | | - private static final TestHttpServer testHttpServer = new TestHttpServer(); |
52 | | - |
53 | | - @BeforeAll |
54 | | - public static void startServer() throws Exception { |
55 | | - testHttpServer.start(); |
56 | | - } |
| 25 | +import org.hypertrace.agent.testing.AbstractHttpClientTest; |
57 | 26 |
|
58 | | - @AfterAll |
59 | | - public static void closeServer() throws Exception { |
60 | | - testHttpServer.close(); |
61 | | - } |
| 27 | +public class JaxrsClientBodyInstrumentationTest extends AbstractHttpClientTest { |
62 | 28 |
|
63 | | - @Test |
64 | | - public void getJson() throws TimeoutException, InterruptedException { |
65 | | - ClientBuilder clientBuilder = ClientBuilder.newBuilder(); |
66 | | - Client client = clientBuilder.build(); |
67 | | - |
68 | | - Response response = |
69 | | - client |
70 | | - .target(String.format("http://localhost:%d/get_json", testHttpServer.port())) |
71 | | - .request() |
72 | | - .header("test-request-header", "test-header-value") |
73 | | - .get(); |
74 | | - assertGetJson(response); |
75 | | - } |
| 29 | + private static final Client client = ClientBuilder.newBuilder().build(); |
76 | 30 |
|
77 | | - @Test |
78 | | - public void getJsonAsync() throws TimeoutException, InterruptedException, ExecutionException { |
79 | | - ClientBuilder clientBuilder = ClientBuilder.newBuilder(); |
80 | | - Client client = clientBuilder.build(); |
81 | | - |
82 | | - Future<Response> responseFuture = |
83 | | - client |
84 | | - .target(String.format("http://localhost:%d/get_json", testHttpServer.port())) |
85 | | - .request() |
86 | | - .header("test-request-header", "test-header-value") |
87 | | - .async() |
88 | | - .get(); |
89 | | - |
90 | | - Response response = responseFuture.get(); |
91 | | - assertGetJson(response); |
| 31 | + public JaxrsClientBodyInstrumentationTest() { |
| 32 | + super(true); |
92 | 33 | } |
93 | 34 |
|
94 | | - public void assertGetJson(Response response) throws TimeoutException, InterruptedException { |
95 | | - Assertions.assertEquals(200, response.getStatus()); |
96 | | - // read entity has to happen before response.close() |
97 | | - String entity = response.readEntity(String.class); |
98 | | - Assertions.assertEquals(GetJsonHandler.RESPONSE_BODY, entity); |
99 | | - Assertions.assertEquals(false, Span.current().isRecording()); |
100 | | - response.close(); |
101 | | - |
102 | | - TEST_WRITER.waitForTraces(1); |
103 | | - List<List<SpanData>> traces = TEST_WRITER.getTraces(); |
104 | | - Assertions.assertEquals(1, traces.size()); |
105 | | - Assertions.assertEquals(2, traces.get(0).size()); |
106 | | - SpanData clientSpan = traces.get(0).get(0); |
107 | | - |
108 | | - Assertions.assertEquals( |
109 | | - "test-value", |
110 | | - clientSpan |
111 | | - .getAttributes() |
112 | | - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); |
113 | | - Assertions.assertEquals( |
114 | | - "test-header-value", |
115 | | - clientSpan |
116 | | - .getAttributes() |
117 | | - .get(HypertraceSemanticAttributes.httpRequestHeader("test-request-header"))); |
118 | | - Assertions.assertNull( |
119 | | - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); |
120 | | - SpanData responseBodySpan = traces.get(0).get(1); |
121 | | - Assertions.assertEquals( |
122 | | - GetJsonHandler.RESPONSE_BODY, |
123 | | - responseBodySpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); |
124 | | - } |
| 35 | + @Override |
| 36 | + public AbstractHttpClientTest.Response doPostRequest( |
| 37 | + String uri, Map<String, String> headers, String body, String contentType) { |
125 | 38 |
|
126 | | - @Test |
127 | | - public void postJson() throws TimeoutException, InterruptedException { |
128 | | - ClientBuilder clientBuilder = ClientBuilder.newBuilder(); |
129 | | - Client client = clientBuilder.build(); |
130 | | - |
131 | | - MyDto myDto = new MyDto(); |
132 | | - myDto.name = "foo"; |
133 | | - |
134 | | - Response response = |
135 | | - client |
136 | | - .target(String.format("http://localhost:%d/post", testHttpServer.port())) |
137 | | - .request() |
138 | | - .header("test-request-header", "test-header-value") |
139 | | - .post(Entity.entity(JSON, MediaType.APPLICATION_JSON_TYPE)); |
140 | | - Assertions.assertEquals(204, response.getStatus()); |
141 | | - |
142 | | - TEST_WRITER.waitForTraces(1); |
143 | | - List<List<SpanData>> traces = TEST_WRITER.getTraces(); |
144 | | - Assertions.assertEquals(1, traces.size()); |
145 | | - Assertions.assertEquals(1, traces.get(0).size()); |
146 | | - SpanData clientSpan = traces.get(0).get(0); |
147 | | - |
148 | | - Assertions.assertEquals( |
149 | | - "test-value", |
150 | | - clientSpan |
151 | | - .getAttributes() |
152 | | - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); |
153 | | - Assertions.assertEquals( |
154 | | - JSON, clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); |
155 | | - Assertions.assertNull( |
156 | | - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); |
157 | | - } |
| 39 | + Invocation.Builder builder = client.target(uri).request(); |
158 | 40 |
|
159 | | - @Test |
160 | | - public void postJsonDtoAsync() throws TimeoutException, InterruptedException, ExecutionException { |
161 | | - ClientBuilder clientBuilder = ClientBuilder.newBuilder(); |
162 | | - Client client = clientBuilder.register(MyDtoMessageBodyWriter.class).build(); |
163 | | - |
164 | | - MyDto myDto = new MyDto(); |
165 | | - myDto.name = "name"; |
166 | | - |
167 | | - Future<Response> post = |
168 | | - client |
169 | | - .target(String.format("http://localhost:%d/post", testHttpServer.port())) |
170 | | - .request() |
171 | | - .header("test-request-header", "test-header-value") |
172 | | - .async() |
173 | | - .post(Entity.json(myDto)); |
174 | | - Response response = post.get(); |
175 | | - Assertions.assertEquals(204, response.getStatus()); |
176 | | - |
177 | | - TEST_WRITER.waitForTraces(1); |
178 | | - List<List<SpanData>> traces = TEST_WRITER.getTraces(); |
179 | | - Assertions.assertEquals(1, traces.size()); |
180 | | - Assertions.assertEquals(1, traces.get(0).size()); |
181 | | - SpanData clientSpan = traces.get(0).get(0); |
182 | | - |
183 | | - Assertions.assertEquals( |
184 | | - "test-value", |
185 | | - clientSpan |
186 | | - .getAttributes() |
187 | | - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); |
188 | | - Assertions.assertEquals( |
189 | | - myDto.getJson(), |
190 | | - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); |
191 | | - Assertions.assertNull( |
192 | | - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); |
193 | | - } |
| 41 | + for (Map.Entry<String, String> entry : headers.entrySet()) { |
| 42 | + builder = builder.header(entry.getKey(), entry.getValue()); |
| 43 | + } |
| 44 | + |
| 45 | + javax.ws.rs.core.Response response = |
| 46 | + builder.post(Entity.entity(body, MediaType.valueOf(contentType))); |
194 | 47 |
|
195 | | - @Test |
196 | | - public void postUrlEncoded() throws TimeoutException, InterruptedException { |
197 | | - ClientBuilder clientBuilder = ClientBuilder.newBuilder(); |
198 | | - Client client = clientBuilder.build(); |
199 | | - |
200 | | - WebTarget webTarget = |
201 | | - client.target(String.format("http://localhost:%d/post", testHttpServer.port())); |
202 | | - MultivaluedMap<String, String> formData = new MultivaluedHashMap<>(); |
203 | | - formData.add("key1", "value1"); |
204 | | - formData.add("key2", "value2"); |
205 | | - Response response = webTarget.request().post(Entity.form(formData)); |
206 | | - Assertions.assertEquals(204, response.getStatus()); |
207 | | - |
208 | | - TEST_WRITER.waitForTraces(1); |
209 | | - List<List<SpanData>> traces = TEST_WRITER.getTraces(); |
210 | | - Assertions.assertEquals(1, traces.size()); |
211 | | - Assertions.assertEquals(1, traces.get(0).size()); |
212 | | - SpanData clientSpan = traces.get(0).get(0); |
213 | | - |
214 | | - Assertions.assertEquals( |
215 | | - "test-value", |
216 | | - clientSpan |
217 | | - .getAttributes() |
218 | | - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); |
219 | | - Assertions.assertEquals( |
220 | | - "key1=value1&key2=value2", |
221 | | - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); |
222 | | - Assertions.assertNull( |
223 | | - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); |
| 48 | + return new Response(response.readEntity(String.class), response.getStatus()); |
224 | 49 | } |
225 | 50 |
|
226 | | - public static class MyDto { |
227 | | - public String name; |
| 51 | + @Override |
| 52 | + public AbstractHttpClientTest.Response doGetRequest(String uri, Map<String, String> headers) { |
| 53 | + |
| 54 | + Invocation.Builder builder = client.target(uri).request(); |
228 | 55 |
|
229 | | - public String getJson() { |
230 | | - return "{name:\"" + name + "\"}"; |
| 56 | + for (Map.Entry<String, String> entry : headers.entrySet()) { |
| 57 | + builder = builder.header(entry.getKey(), entry.getValue()); |
231 | 58 | } |
232 | | - } |
233 | 59 |
|
234 | | - public static class MyDtoMessageBodyWriter implements MessageBodyWriter<MyDto> { |
| 60 | + javax.ws.rs.core.Response response = builder.get(); |
235 | 61 |
|
236 | | - @Override |
237 | | - public boolean isWriteable( |
238 | | - Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { |
239 | | - return true; |
240 | | - } |
| 62 | + String responseBody = response.readEntity(String.class); |
241 | 63 |
|
242 | | - @Override |
243 | | - public void writeTo( |
244 | | - MyDto myDto, |
245 | | - Class<?> type, |
246 | | - Type genericType, |
247 | | - Annotation[] annotations, |
248 | | - MediaType mediaType, |
249 | | - MultivaluedMap<String, Object> httpHeaders, |
250 | | - OutputStream entityStream) |
251 | | - throws IOException, WebApplicationException { |
252 | | - entityStream.write((myDto.getJson()).getBytes()); |
253 | | - } |
| 64 | + return new Response( |
| 65 | + responseBody == null || responseBody.isEmpty() ? null : responseBody, response.getStatus()); |
254 | 66 | } |
255 | 67 | } |
0 commit comments