1919import static org .junit .jupiter .api .Assertions .assertEquals ;
2020import static org .junit .jupiter .api .Assertions .assertNull ;
2121import static org .mockito .ArgumentMatchers .any ;
22+ import static org .mockito .ArgumentMatchers .anyBoolean ;
2223import static org .mockito .Mockito .mock ;
2324import static org .mockito .Mockito .times ;
2425import static org .mockito .Mockito .verify ;
26+ import static org .mockito .Mockito .when ;
2527
28+ import com .google .api .client .http .ByteArrayContent ;
2629import com .google .api .client .http .GenericUrl ;
30+ import com .google .api .client .http .HttpContent ;
31+ import com .google .api .client .http .HttpEncoding ;
2732import com .google .api .client .http .HttpRequest ;
2833import com .google .api .client .http .HttpRequestFactory ;
2934import com .google .api .client .http .HttpRequestInitializer ;
3035import com .google .api .client .http .HttpResponse ;
36+ import com .google .api .client .http .HttpResponseException ;
37+ import com .google .api .client .http .HttpResponseInterceptor ;
3138import com .google .api .client .http .HttpTransport ;
39+ import com .google .api .client .http .HttpUnsuccessfulResponseHandler ;
3240import com .google .api .client .http .LowLevelHttpRequest ;
3341import com .google .api .client .http .LowLevelHttpResponse ;
3442import com .google .api .client .testing .http .MockHttpTransport ;
@@ -77,22 +85,23 @@ public void setUp() {
7785 }
7886
7987 @ Test
80- public void testRequestAttributesAreSetIfSpanExists () throws IOException {
81- HttpTransport transport = createTransport ();
82- HttpRequest request = buildGetRequest (transport , initializer , BASE_URL );
88+ public void testAllAttributesAreSetOnSuccessfulCall () throws IOException {
89+ HttpResponseInterceptor originalInterceptor = mock (HttpResponseInterceptor .class );
90+ HttpRequestInitializer delegateInitializer =
91+ request -> request .setResponseInterceptor (originalInterceptor );
92+ HttpTracingRequestInitializer tracingInitializer =
93+ new HttpTracingRequestInitializer (delegateInitializer , tracer );
94+ String responseContent = "{\" status\" : \" ok\" }" ;
95+ HttpTransport transport = createTransport (200 , responseContent );
96+ HttpContent requestContent =
97+ ByteArrayContent .fromString ("application/json" , "{\" test\" : \" data\" }" );
98+ HttpRequest request = buildPostRequest (transport , tracingInitializer , BASE_URL , requestContent );
8399
84100 HttpResponse response = request .execute ();
85101 response .disconnect ();
86102
87- // End the span before verifying exported spans, so it appears in the exporter
88- spanScope .close ();
89- parentSpan .end ();
90-
91- List <SpanData > spans = spanExporter .getFinishedSpanItems ();
92- assertEquals (1 , spans .size ());
93-
94- SpanData span = spans .get (0 );
95- verifyGeneralSpanData (span );
103+ verify (originalInterceptor , times (1 )).interceptResponse (any (HttpResponse .class ));
104+ closeAndVerifySpanData (200 , "POST" , 16 , requestContent .getLength ());
96105 }
97106
98107 @ Test
@@ -103,14 +112,11 @@ public void testExistingParentAttributesAreNotAffectedByRequestAttributes() thro
103112
104113 HttpResponse response = request .execute ();
105114 response .disconnect ();
106-
107- // End the span before verifying exported spans, so it appears in the exporter
108115 spanScope .close ();
109116 parentSpan .end ();
110117
111118 List <SpanData > spans = spanExporter .getFinishedSpanItems ();
112119 assertEquals (1 , spans .size ());
113-
114120 SpanData span = spans .get (0 );
115121 assertEquals ("value" , span .getAttributes ().get (AttributeKey .stringKey ("parent_attribute" )));
116122 }
@@ -152,14 +158,160 @@ public void testDelegateInitializerIsCalled() throws IOException {
152158 verify (delegateInitializer , times (1 )).initialize (any (HttpRequest .class ));
153159 }
154160
161+ @ Test
162+ public void testUnsuccessfulResponseHandlerSetsAttributesAndCallsOriginal () throws IOException {
163+ HttpUnsuccessfulResponseHandler originalHandler = mock (HttpUnsuccessfulResponseHandler .class );
164+ when (originalHandler .handleResponse (
165+ any (HttpRequest .class ), any (HttpResponse .class ), anyBoolean ()))
166+ .thenReturn (false );
167+ HttpRequestInitializer delegateInitializer =
168+ request -> request .setUnsuccessfulResponseHandler (originalHandler );
169+ HttpTracingRequestInitializer tracingInitializer =
170+ new HttpTracingRequestInitializer (delegateInitializer , tracer );
171+ String responseContent = "{\" error\" : \" not found\" }" ;
172+ HttpTransport transport = createTransport (404 , responseContent );
173+ HttpContent requestContent =
174+ ByteArrayContent .fromString ("application/json" , "{\" test\" : \" data\" }" );
175+ HttpRequest request = buildPostRequest (transport , tracingInitializer , BASE_URL , requestContent );
176+
177+ try {
178+ request .execute ();
179+ } catch (HttpResponseException e ) {
180+ // Expected
181+ }
182+
183+ verify (originalHandler , times (1 ))
184+ .handleResponse (any (HttpRequest .class ), any (HttpResponse .class ), anyBoolean ());
185+ closeAndVerifySpanData (404 , "POST" , 16 , responseContent .length ());
186+ }
187+
188+ @ Test
189+ public void testUnsuccessfulResponseHandlerSetsErrorIfNoOriginal () throws IOException {
190+ HttpTracingRequestInitializer tracingInitializer =
191+ new HttpTracingRequestInitializer (null , tracer );
192+ HttpTransport transport = createTransport (401 );
193+ HttpRequest request = buildGetRequest (transport , tracingInitializer , BASE_URL );
194+
195+ try {
196+ request .execute ();
197+ } catch (HttpResponseException e ) {
198+ // Expected
199+ }
200+
201+ closeAndVerifySpanData (401 , "GET" , -1 , -1 );
202+ }
203+
204+ @ Test
205+ public void testAddRequestBodySizeToSpan_ExceptionHandled () throws IOException {
206+ HttpContent content = mock (HttpContent .class );
207+ when (content .getLength ()).thenThrow (new IOException ("test" ));
208+ HttpTransport transport = createTransport ();
209+ HttpRequest request = buildPostRequest (transport , null , BASE_URL , content );
210+
211+ HttpTracingRequestInitializer .addRequestBodySizeToSpan (request , parentSpan );
212+
213+ spanScope .close ();
214+ parentSpan .end ();
215+
216+ List <SpanData > spans = spanExporter .getFinishedSpanItems ();
217+ assertEquals (1 , spans .size ());
218+ SpanData span = spans .get (0 );
219+ assertNull (span .getAttributes ().get (HttpTracingRequestInitializer .HTTP_REQUEST_BODY_SIZE ));
220+ }
221+
222+ @ Test
223+ public void testAddRequestBodySizeToSpan_NullBody () throws IOException {
224+ HttpTransport transport = createTransport ();
225+ HttpRequest request = buildPostRequest (transport , null , BASE_URL , null );
226+
227+ HttpTracingRequestInitializer .addRequestBodySizeToSpan (request , parentSpan );
228+
229+ spanScope .close ();
230+ parentSpan .end ();
231+
232+ List <SpanData > spans = spanExporter .getFinishedSpanItems ();
233+ assertEquals (1 , spans .size ());
234+ SpanData span = spans .get (0 );
235+ assertNull (span .getAttributes ().get (HttpTracingRequestInitializer .HTTP_REQUEST_BODY_SIZE ));
236+ }
237+
238+ @ Test
239+ public void testAddRequestBodySizeToSpan_WithEncoding () throws IOException {
240+ HttpTransport transport = createTransport ();
241+ HttpContent content = ByteArrayContent .fromString ("application/json" , "{\" test\" : \" data\" }" );
242+ HttpRequest request = buildPostRequest (transport , null , BASE_URL , content );
243+ request .setEncoding (mock (HttpEncoding .class ));
244+
245+ HttpTracingRequestInitializer .addRequestBodySizeToSpan (request , parentSpan );
246+
247+ spanScope .close ();
248+ parentSpan .end ();
249+
250+ List <SpanData > spans = spanExporter .getFinishedSpanItems ();
251+ assertEquals (1 , spans .size ());
252+ SpanData span = spans .get (0 );
253+ assertNull (span .getAttributes ().get (HttpTracingRequestInitializer .HTTP_REQUEST_BODY_SIZE ));
254+ }
255+
256+ @ Test
257+ public void testAddRequestBodySizeToSpan () throws IOException {
258+ HttpTransport transport = createTransport ();
259+ HttpContent content = ByteArrayContent .fromString ("application/json" , "{\" test\" : \" data\" }" );
260+ HttpRequest request = buildPostRequest (transport , null , BASE_URL , content );
261+
262+ HttpTracingRequestInitializer .addRequestBodySizeToSpan (request , parentSpan );
263+
264+ spanScope .close ();
265+ parentSpan .end ();
266+
267+ List <SpanData > spans = spanExporter .getFinishedSpanItems ();
268+ assertEquals (1 , spans .size ());
269+ SpanData span = spans .get (0 );
270+ assertEquals (
271+ content .getLength (),
272+ span .getAttributes ().get (HttpTracingRequestInitializer .HTTP_REQUEST_BODY_SIZE ));
273+ }
274+
275+ @ Test
276+ public void testAddResponseBodySizeToSpan_NullLength () throws IOException {
277+ HttpTransport transport =
278+ createTransport (200 , null ); // Null response content means null Content-Length header
279+ HttpRequest request = buildGetRequest (transport , null , BASE_URL );
280+ HttpResponse response = request .execute ();
281+
282+ HttpTracingRequestInitializer .addResponseBodySizeToSpan (response , parentSpan );
283+
284+ spanScope .close ();
285+ parentSpan .end ();
286+
287+ List <SpanData > spans = spanExporter .getFinishedSpanItems ();
288+ assertEquals (1 , spans .size ());
289+ SpanData span = spans .get (0 );
290+ assertNull (span .getAttributes ().get (HttpTracingRequestInitializer .HTTP_RESPONSE_BODY_SIZE ));
291+ }
292+
155293 private static HttpTransport createTransport () {
294+ return createTransport (200 , null );
295+ }
296+
297+ private static HttpTransport createTransport (int statusCode ) {
298+ return createTransport (statusCode , null );
299+ }
300+
301+ private static HttpTransport createTransport (int statusCode , String responseContent ) {
156302 return new MockHttpTransport () {
157303 @ Override
158304 public LowLevelHttpRequest buildRequest (String method , String url ) {
159305 return new MockLowLevelHttpRequest () {
160306 @ Override
161307 public LowLevelHttpResponse execute () {
162- return new MockLowLevelHttpResponse ();
308+ MockLowLevelHttpResponse response = new MockLowLevelHttpResponse ();
309+ response .setStatusCode (statusCode );
310+ if (responseContent != null ) {
311+ response .setContent (responseContent );
312+ response .addHeader ("Content-Length" , String .valueOf (responseContent .length ()));
313+ }
314+ return response ;
163315 }
164316 };
165317 }
@@ -173,7 +325,25 @@ private static HttpRequest buildGetRequest(
173325 return requestFactory .buildGetRequest (new GenericUrl (url ));
174326 }
175327
176- private void verifyGeneralSpanData (SpanData span ) {
328+ private static HttpRequest buildPostRequest (
329+ HttpTransport transport ,
330+ HttpRequestInitializer requestInitializer ,
331+ String url ,
332+ HttpContent content )
333+ throws IOException {
334+ HttpRequestFactory requestFactory = transport .createRequestFactory (requestInitializer );
335+ return requestFactory .buildPostRequest (new GenericUrl (url ), content );
336+ }
337+
338+ private void closeAndVerifySpanData (
339+ long responseCode , String method , long requestBodySize , long responseBodySize ) {
340+ // close span so it is available for verification
341+ spanScope .close ();
342+ parentSpan .end ();
343+ List <SpanData > spans = spanExporter .getFinishedSpanItems ();
344+
345+ assertEquals (1 , spans .size ());
346+ SpanData span = spans .get (0 );
177347 assertEquals (SPAN_NAME , span .getName ());
178348 assertEquals (BIGQUERY_DOMAIN , span .getAttributes ().get (BigQueryTelemetryTracer .SERVER_ADDRESS ));
179349 assertEquals (443 , span .getAttributes ().get (BigQueryTelemetryTracer .SERVER_PORT ));
@@ -192,5 +362,24 @@ private void verifyGeneralSpanData(SpanData span) {
192362 assertEquals (
193363 HttpTracingRequestInitializer .HTTP_RPC_SYSTEM_NAME ,
194364 span .getAttributes ().get (BigQueryTelemetryTracer .RPC_SYSTEM_NAME ));
365+ assertEquals (
366+ responseCode ,
367+ span .getAttributes ().get (HttpTracingRequestInitializer .HTTP_RESPONSE_STATUS_CODE ));
368+ assertEquals (
369+ method , span .getAttributes ().get (HttpTracingRequestInitializer .HTTP_REQUEST_METHOD ));
370+ if (requestBodySize >= 0 ) {
371+ assertEquals (
372+ requestBodySize ,
373+ span .getAttributes ().get (HttpTracingRequestInitializer .HTTP_REQUEST_BODY_SIZE ));
374+ } else {
375+ assertNull (span .getAttributes ().get (HttpTracingRequestInitializer .HTTP_REQUEST_BODY_SIZE ));
376+ }
377+ if (responseBodySize >= 0 ) {
378+ assertEquals (
379+ responseBodySize ,
380+ span .getAttributes ().get (HttpTracingRequestInitializer .HTTP_RESPONSE_BODY_SIZE ));
381+ } else {
382+ assertNull (span .getAttributes ().get (HttpTracingRequestInitializer .HTTP_RESPONSE_BODY_SIZE ));
383+ }
195384 }
196385}
0 commit comments