5151import com .google .showcase .v1beta1 .EchoRequest ;
5252import com .google .showcase .v1beta1 .EchoResponse ;
5353import com .google .showcase .v1beta1 .EchoSettings ;
54+ import com .google .showcase .v1beta1 .GetUserRequest ;
55+ import com .google .showcase .v1beta1 .IdentityClient ;
5456import com .google .showcase .v1beta1 .it .util .TestClientInitializer ;
5557import com .google .showcase .v1beta1 .stub .EchoStub ;
5658import com .google .showcase .v1beta1 .stub .EchoStubSettings ;
@@ -89,6 +91,39 @@ class ITOtelTracing {
8991 private static final String SHOWCASE_ARTIFACT = "com.google.cloud:gapic-showcase" ;
9092 private static final String SHOWCASE_USER_URL = "http://localhost:7469/v1beta1/echo:echo" ;
9193
94+ // Attribute Keys
95+ private static final AttributeKey <String > RPC_SYSTEM_KEY =
96+ AttributeKey .stringKey (ObservabilityAttributes .RPC_SYSTEM_NAME_ATTRIBUTE );
97+ private static final AttributeKey <String > RPC_RESPONSE_STATUS_KEY =
98+ AttributeKey .stringKey (ObservabilityAttributes .RPC_RESPONSE_STATUS_ATTRIBUTE );
99+ private static final AttributeKey <Long > HTTP_RESPONSE_STATUS_KEY =
100+ AttributeKey .longKey (ObservabilityAttributes .HTTP_RESPONSE_STATUS_ATTRIBUTE );
101+ private static final AttributeKey <String > REPO_KEY =
102+ AttributeKey .stringKey (ObservabilityAttributes .REPO_ATTRIBUTE );
103+ private static final AttributeKey <String > ARTIFACT_KEY =
104+ AttributeKey .stringKey (ObservabilityAttributes .ARTIFACT_ATTRIBUTE );
105+ private static final AttributeKey <String > ERROR_TYPE_KEY =
106+ AttributeKey .stringKey (ObservabilityAttributes .ERROR_TYPE_ATTRIBUTE );
107+ private static final AttributeKey <String > EXCEPTION_TYPE_KEY =
108+ AttributeKey .stringKey (ObservabilityAttributes .EXCEPTION_TYPE_ATTRIBUTE );
109+ private static final AttributeKey <String > STATUS_MESSAGE_KEY =
110+ AttributeKey .stringKey (ObservabilityAttributes .STATUS_MESSAGE_ATTRIBUTE );
111+ private static final AttributeKey <String > DESTINATION_RESOURCE_ID_KEY =
112+ AttributeKey .stringKey (ObservabilityAttributes .DESTINATION_RESOURCE_ID_ATTRIBUTE );
113+
114+ // Expected Values
115+ private static final String VALUE_GRPC = "grpc" ;
116+ private static final String VALUE_HTTP = "http" ;
117+ private static final String VALUE_OK = "OK" ;
118+ private static final String VALUE_TEST_USER = "users/test-user" ;
119+ private static final String VALUE_UNAVAILABLE = "UNAVAILABLE" ;
120+ private static final String VALUE_UNAVAILABLE_EXCEPTION = "UnavailableException" ;
121+ private static final String VALUE_SERVICE_UNAVAILABLE = "Service Unavailable" ;
122+ private static final String SPAN_NAME_ECHO_GRPC = "google.showcase.v1beta1.Echo/Echo" ;
123+ private static final String SPAN_NAME_ECHO_HTTP = "POST v1beta1/echo:echo" ;
124+ private static final String SPAN_NAME_GET_USER_GRPC = "google.showcase.v1beta1.Identity/GetUser" ;
125+ private static final String SPAN_NAME_GET_USER_HTTP = "GET v1beta1/{name=users/*}" ;
126+
92127 private InMemorySpanExporter spanExporter ;
93128 private OpenTelemetrySdk openTelemetrySdk ;
94129
@@ -129,7 +164,7 @@ void testTracing_successfulEcho_grpc() throws Exception {
129164
130165 SpanData attemptSpan =
131166 spans .stream ()
132- .filter (span -> span .getName ().equals ("google.showcase.v1beta1.Echo/Echo" ))
167+ .filter (span -> span .getName ().equals (SPAN_NAME_ECHO_GRPC ))
133168 .findFirst ()
134169 .orElseThrow (() -> new AssertionError ("Incorrect span name" ));
135170 assertThat (attemptSpan .getKind ()).isEqualTo (SpanKind .CLIENT );
@@ -143,21 +178,11 @@ void testTracing_successfulEcho_grpc() throws Exception {
143178 .getAttributes ()
144179 .get (AttributeKey .longKey (ObservabilityAttributes .SERVER_PORT_ATTRIBUTE )))
145180 .isEqualTo (SHOWCASE_SERVER_PORT );
146- assertThat (
147- attemptSpan
148- .getAttributes ()
149- .get (AttributeKey .stringKey (ObservabilityAttributes .REPO_ATTRIBUTE )))
150- .isEqualTo (SHOWCASE_REPO );
151- assertThat (
152- attemptSpan
153- .getAttributes ()
154- .get (AttributeKey .stringKey (ObservabilityAttributes .ARTIFACT_ATTRIBUTE )))
155- .isEqualTo (SHOWCASE_ARTIFACT );
156- assertThat (
157- attemptSpan
158- .getAttributes ()
159- .get (AttributeKey .stringKey (ObservabilityAttributes .RPC_SYSTEM_NAME_ATTRIBUTE )))
160- .isEqualTo ("grpc" );
181+ assertThat (attemptSpan .getAttributes ().get (RPC_SYSTEM_KEY )).isEqualTo (VALUE_GRPC );
182+ assertThat (attemptSpan .getAttributes ().get (RPC_RESPONSE_STATUS_KEY )).isEqualTo (VALUE_OK );
183+ assertThat (attemptSpan .getAttributes ().get (REPO_KEY )).isEqualTo (SHOWCASE_REPO );
184+ assertThat (attemptSpan .getAttributes ().get (ARTIFACT_KEY )).isEqualTo (SHOWCASE_ARTIFACT );
185+
161186 assertThat (
162187 attemptSpan
163188 .getAttributes ()
@@ -209,7 +234,7 @@ void testTracing_successfulEcho_httpjson() throws Exception {
209234
210235 SpanData attemptSpan =
211236 spans .stream ()
212- .filter (span -> span .getName ().equals ("POST v1beta1/echo:echo" ))
237+ .filter (span -> span .getName ().equals (SPAN_NAME_ECHO_HTTP ))
213238 .findFirst ()
214239 .orElseThrow (
215240 () -> new AssertionError ("Attempt span 'POST v1beta1/echo:echo' not found" ));
@@ -224,16 +249,10 @@ void testTracing_successfulEcho_httpjson() throws Exception {
224249 .getAttributes ()
225250 .get (AttributeKey .longKey (ObservabilityAttributes .SERVER_PORT_ATTRIBUTE )))
226251 .isEqualTo (SHOWCASE_SERVER_PORT );
227- assertThat (
228- attemptSpan
229- .getAttributes ()
230- .get (AttributeKey .stringKey (ObservabilityAttributes .REPO_ATTRIBUTE )))
231- .isEqualTo (SHOWCASE_REPO );
232- assertThat (
233- attemptSpan
234- .getAttributes ()
235- .get (AttributeKey .stringKey (ObservabilityAttributes .ARTIFACT_ATTRIBUTE )))
236- .isEqualTo (SHOWCASE_ARTIFACT );
252+ assertThat (attemptSpan .getAttributes ().get (RPC_SYSTEM_KEY )).isEqualTo (VALUE_HTTP );
253+ assertThat (attemptSpan .getAttributes ().get (HTTP_RESPONSE_STATUS_KEY )).isEqualTo (200L );
254+ assertThat (attemptSpan .getAttributes ().get (REPO_KEY )).isEqualTo (SHOWCASE_REPO );
255+ assertThat (attemptSpan .getAttributes ().get (ARTIFACT_KEY )).isEqualTo (SHOWCASE_ARTIFACT );
237256 assertThat (
238257 attemptSpan
239258 .getAttributes ()
@@ -293,6 +312,60 @@ private long computeExpectedHttpJsonResponseSize(Message message)
293312 return jsonPayload .getBytes (StandardCharsets .UTF_8 ).length ;
294313 }
295314
315+ @ Test
316+ void testTracing_successfulIdentityGetUser_grpc () throws Exception {
317+ SpanTracerFactory tracingFactory = new SpanTracerFactory (openTelemetrySdk );
318+
319+ try (IdentityClient client =
320+ TestClientInitializer .createGrpcIdentityClientOpentelemetry (tracingFactory )) {
321+
322+ try {
323+ client .getUser (GetUserRequest .newBuilder ().setName ("users/test-user" ).build ());
324+ } catch (Exception e ) {
325+ // Ignored, the showcase server may not have this user, but trace is still
326+ // generated.
327+ }
328+
329+ List <SpanData > spans = spanExporter .getFinishedSpanItems ();
330+ assertThat (spans ).isNotEmpty ();
331+
332+ SpanData attemptSpan =
333+ spans .stream ()
334+ .filter (span -> span .getName ().equals (SPAN_NAME_GET_USER_GRPC ))
335+ .findFirst ()
336+ .orElseThrow (() -> new AssertionError ("Incorrect span name" ));
337+ assertThat (attemptSpan .getAttributes ().get (DESTINATION_RESOURCE_ID_KEY ))
338+ .isEqualTo (VALUE_TEST_USER );
339+ }
340+ }
341+
342+ @ Test
343+ void testTracing_successfulIdentityGetUser_httpjson () throws Exception {
344+ SpanTracerFactory tracingFactory = new SpanTracerFactory (openTelemetrySdk );
345+
346+ try (IdentityClient client =
347+ TestClientInitializer .createHttpJsonIdentityClientOpentelemetry (tracingFactory )) {
348+
349+ try {
350+ client .getUser (GetUserRequest .newBuilder ().setName ("users/test-user" ).build ());
351+ } catch (Exception e ) {
352+ // Ignored, the showcase server may not have this user, but trace is still
353+ // generated.
354+ }
355+
356+ List <SpanData > spans = spanExporter .getFinishedSpanItems ();
357+ assertThat (spans ).isNotEmpty ();
358+
359+ SpanData attemptSpan =
360+ spans .stream ()
361+ .filter (span -> span .getName ().equals (SPAN_NAME_GET_USER_HTTP ))
362+ .findFirst ()
363+ .orElseThrow (() -> new AssertionError ("Incorrect span name" ));
364+ assertThat (attemptSpan .getAttributes ().get (DESTINATION_RESOURCE_ID_KEY ))
365+ .isEqualTo (VALUE_TEST_USER );
366+ }
367+ }
368+
296369 @ Test
297370 void testTracing_retry_grpc () throws Exception {
298371 final int attempts = 5 ;
@@ -443,7 +516,7 @@ void testTracing_retry_httpjson() throws Exception {
443516 assertThat (resendCounts ).containsExactlyElementsIn (expectedCounts ).inOrder ();
444517 }
445518
446- private void verifyErrorTypeAttribute ( String expectedErrorType ) {
519+ private SpanData getErrorSpan ( ) {
447520 List <SpanData > spans = spanExporter .getFinishedSpanItems ();
448521 assertThat (spans ).isNotEmpty ();
449522
@@ -458,16 +531,11 @@ private void verifyErrorTypeAttribute(String expectedErrorType) {
458531 != null )
459532 .findFirst ()
460533 .orElseThrow (() -> new AssertionError ("Span with error.type not found" ));
461-
462- assertThat (
463- errorSpan
464- .getAttributes ()
465- .get (AttributeKey .stringKey (ObservabilityAttributes .ERROR_TYPE_ATTRIBUTE )))
466- .isEqualTo (expectedErrorType );
534+ return errorSpan ;
467535 }
468536
469537 @ Test
470- void testTracing_failedEcho_grpc_recordsErrorType () throws Exception {
538+ void testTracing_failedEcho_grpc_recordsErrorAttributes () throws Exception {
471539 SpanTracerFactory tracingFactory = new SpanTracerFactory (openTelemetrySdk );
472540
473541 ClientInterceptor interceptor =
@@ -509,53 +577,17 @@ public void sendMessage(ReqT message) {}
509577 EchoRequest echoRequest = EchoRequest .newBuilder ().build ();
510578
511579 assertThrows (UnavailableException .class , () -> client .echo (echoRequest ));
512- verifyErrorTypeAttribute ("UNAVAILABLE" );
580+ SpanData errorSpan = getErrorSpan ();
581+ assertThat (errorSpan .getAttributes ().get (ERROR_TYPE_KEY )).isEqualTo (VALUE_UNAVAILABLE );
582+ assertThat (errorSpan .getAttributes ().get (EXCEPTION_TYPE_KEY ))
583+ .isEqualTo ("com.google.api.gax.rpc.UnavailableException" );
584+ assertThat (errorSpan .getAttributes ().get (STATUS_MESSAGE_KEY ))
585+ .isEqualTo ("io.grpc.StatusRuntimeException: UNAVAILABLE" );
513586 }
514587 }
515588
516589 @ Test
517- void testTracing_statusCodes_grpc () throws Exception {
518- SpanTracerFactory tracingFactory = new SpanTracerFactory (openTelemetrySdk );
519- EchoRequest errorRequest =
520- EchoRequest .newBuilder ()
521- .setError (
522- Status .newBuilder ().setCode (StatusCode .Code .INVALID_ARGUMENT .ordinal ()).build ())
523- .build ();
524- EchoRequest successRequest = EchoRequest .newBuilder ().setContent ("tracing-test" ).build ();
525-
526- try (EchoClient grpcClient =
527- TestClientInitializer .createGrpcEchoClientOpentelemetry (tracingFactory )) {
528-
529- grpcClient .echo (successRequest );
530- assertThrows (
531- com .google .api .gax .rpc .InvalidArgumentException .class ,
532- () -> grpcClient .echo (errorRequest ));
533-
534- List <SpanData > spans = spanExporter .getFinishedSpanItems ();
535- assertThat (spans ).hasSize (2 );
536-
537- SpanData grpcSuccessSpan = spans .get (0 );
538- assertThat (
539- grpcSuccessSpan
540- .getAttributes ()
541- .get (
542- AttributeKey .stringKey (
543- ObservabilityAttributes .RPC_RESPONSE_STATUS_ATTRIBUTE )))
544- .isEqualTo ("OK" );
545-
546- SpanData grpcErrorSpan = spans .get (1 );
547- assertThat (
548- grpcErrorSpan
549- .getAttributes ()
550- .get (
551- AttributeKey .stringKey (
552- ObservabilityAttributes .RPC_RESPONSE_STATUS_ATTRIBUTE )))
553- .isEqualTo ("INVALID_ARGUMENT" );
554- }
555- }
556-
557- @ Test
558- void testTracing_failedEcho_httpjson_recordsErrorType () throws Exception {
590+ void testTracing_failedEcho_httpjson_recordsErrorAttributes () throws Exception {
559591 SpanTracerFactory tracingFactory = new SpanTracerFactory (openTelemetrySdk );
560592
561593 HttpTransport mockTransport =
@@ -645,10 +677,57 @@ public String getHeaderValue(int index) {
645677 EchoRequest echoRequest = EchoRequest .newBuilder ().build ();
646678
647679 assertThrows (UnavailableException .class , () -> client .echo (echoRequest ));
648- verifyErrorTypeAttribute ("503" );
680+ SpanData errorSpan = getErrorSpan ();
681+ assertThat (errorSpan .getAttributes ().get (ERROR_TYPE_KEY )).isEqualTo ("503" );
682+ assertThat (errorSpan .getAttributes ().get (EXCEPTION_TYPE_KEY ))
683+ .isEqualTo ("com.google.api.gax.rpc.UnavailableException" );
684+ assertThat (errorSpan .getAttributes ().get (STATUS_MESSAGE_KEY ))
685+ .isEqualTo (VALUE_SERVICE_UNAVAILABLE );
649686 }
650687 }
651688
689+ @ Test
690+ void testTracing_statusCodes_grpc () throws Exception {
691+ SpanTracerFactory tracingFactory = new SpanTracerFactory (openTelemetrySdk );
692+ EchoRequest errorRequest =
693+ EchoRequest .newBuilder ()
694+ .setError (
695+ Status .newBuilder ().setCode (StatusCode .Code .INVALID_ARGUMENT .ordinal ()).build ())
696+ .build ();
697+ EchoRequest successRequest = EchoRequest .newBuilder ().setContent ("tracing-test" ).build ();
698+
699+ try (EchoClient grpcClient =
700+ TestClientInitializer .createGrpcEchoClientOpentelemetry (tracingFactory )) {
701+
702+ grpcClient .echo (successRequest );
703+ assertThrows (
704+ com .google .api .gax .rpc .InvalidArgumentException .class ,
705+ () -> grpcClient .echo (errorRequest ));
706+
707+ List <SpanData > spans = spanExporter .getFinishedSpanItems ();
708+ assertThat (spans ).hasSize (2 );
709+
710+ SpanData grpcSuccessSpan = spans .get (0 );
711+ assertThat (
712+ grpcSuccessSpan
713+ .getAttributes ()
714+ .get (
715+ AttributeKey .stringKey (
716+ ObservabilityAttributes .RPC_RESPONSE_STATUS_ATTRIBUTE )))
717+ .isEqualTo ("OK" );
718+
719+ SpanData grpcErrorSpan = spans .get (1 );
720+ assertThat (
721+ grpcErrorSpan
722+ .getAttributes ()
723+ .get (
724+ AttributeKey .stringKey (
725+ ObservabilityAttributes .RPC_RESPONSE_STATUS_ATTRIBUTE )))
726+ .isEqualTo ("INVALID_ARGUMENT" );
727+ }
728+ }
729+
730+ @ Test
652731 void testTracing_statusCodes_httpjson () throws Exception {
653732 SpanTracerFactory tracingFactory = new SpanTracerFactory (openTelemetrySdk );
654733 EchoRequest errorRequest =
0 commit comments