Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
import com.google.showcase.v1beta1.EchoRequest;
import com.google.showcase.v1beta1.EchoResponse;
import com.google.showcase.v1beta1.EchoSettings;
import com.google.showcase.v1beta1.GetUserRequest;
import com.google.showcase.v1beta1.IdentityClient;
import com.google.showcase.v1beta1.it.util.TestClientInitializer;
import com.google.showcase.v1beta1.stub.EchoStub;
import com.google.showcase.v1beta1.stub.EchoStubSettings;
Expand Down Expand Up @@ -89,6 +91,39 @@ class ITOtelTracing {
private static final String SHOWCASE_ARTIFACT = "com.google.cloud:gapic-showcase";
private static final String SHOWCASE_USER_URL = "http://localhost:7469/v1beta1/echo:echo";

// Attribute Keys
private static final AttributeKey<String> RPC_SYSTEM_KEY =
AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE);
private static final AttributeKey<String> RPC_RESPONSE_STATUS_KEY =
AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE);
private static final AttributeKey<Long> HTTP_RESPONSE_STATUS_KEY =
AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE);
private static final AttributeKey<String> REPO_KEY =
AttributeKey.stringKey(ObservabilityAttributes.REPO_ATTRIBUTE);
private static final AttributeKey<String> ARTIFACT_KEY =
AttributeKey.stringKey(ObservabilityAttributes.ARTIFACT_ATTRIBUTE);
private static final AttributeKey<String> ERROR_TYPE_KEY =
AttributeKey.stringKey(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE);
private static final AttributeKey<String> EXCEPTION_TYPE_KEY =
AttributeKey.stringKey(ObservabilityAttributes.EXCEPTION_TYPE_ATTRIBUTE);
private static final AttributeKey<String> STATUS_MESSAGE_KEY =
AttributeKey.stringKey(ObservabilityAttributes.STATUS_MESSAGE_ATTRIBUTE);
private static final AttributeKey<String> DESTINATION_RESOURCE_ID_KEY =
AttributeKey.stringKey(ObservabilityAttributes.DESTINATION_RESOURCE_ID_ATTRIBUTE);

// Expected Values
private static final String VALUE_GRPC = "grpc";
private static final String VALUE_HTTP = "http";
private static final String VALUE_OK = "OK";
private static final String VALUE_TEST_USER = "users/test-user";
private static final String VALUE_UNAVAILABLE = "UNAVAILABLE";
private static final String VALUE_UNAVAILABLE_EXCEPTION = "UnavailableException";
private static final String VALUE_SERVICE_UNAVAILABLE = "Service Unavailable";
private static final String SPAN_NAME_ECHO_GRPC = "google.showcase.v1beta1.Echo/Echo";
private static final String SPAN_NAME_ECHO_HTTP = "POST v1beta1/echo:echo";
private static final String SPAN_NAME_GET_USER_GRPC = "google.showcase.v1beta1.Identity/GetUser";
private static final String SPAN_NAME_GET_USER_HTTP = "GET v1beta1/{name=users/*}";

private InMemorySpanExporter spanExporter;
private OpenTelemetrySdk openTelemetrySdk;

Expand Down Expand Up @@ -129,7 +164,7 @@ void testTracing_successfulEcho_grpc() throws Exception {

SpanData attemptSpan =
spans.stream()
.filter(span -> span.getName().equals("google.showcase.v1beta1.Echo/Echo"))
.filter(span -> span.getName().equals(SPAN_NAME_ECHO_GRPC))
.findFirst()
.orElseThrow(() -> new AssertionError("Incorrect span name"));
assertThat(attemptSpan.getKind()).isEqualTo(SpanKind.CLIENT);
Expand All @@ -143,21 +178,11 @@ void testTracing_successfulEcho_grpc() throws Exception {
.getAttributes()
.get(AttributeKey.longKey(ObservabilityAttributes.SERVER_PORT_ATTRIBUTE)))
.isEqualTo(SHOWCASE_SERVER_PORT);
assertThat(
attemptSpan
.getAttributes()
.get(AttributeKey.stringKey(ObservabilityAttributes.REPO_ATTRIBUTE)))
.isEqualTo(SHOWCASE_REPO);
assertThat(
attemptSpan
.getAttributes()
.get(AttributeKey.stringKey(ObservabilityAttributes.ARTIFACT_ATTRIBUTE)))
.isEqualTo(SHOWCASE_ARTIFACT);
assertThat(
attemptSpan
.getAttributes()
.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE)))
.isEqualTo("grpc");
assertThat(attemptSpan.getAttributes().get(RPC_SYSTEM_KEY)).isEqualTo(VALUE_GRPC);
assertThat(attemptSpan.getAttributes().get(RPC_RESPONSE_STATUS_KEY)).isEqualTo(VALUE_OK);
assertThat(attemptSpan.getAttributes().get(REPO_KEY)).isEqualTo(SHOWCASE_REPO);
assertThat(attemptSpan.getAttributes().get(ARTIFACT_KEY)).isEqualTo(SHOWCASE_ARTIFACT);

assertThat(
attemptSpan
.getAttributes()
Expand Down Expand Up @@ -209,7 +234,7 @@ void testTracing_successfulEcho_httpjson() throws Exception {

SpanData attemptSpan =
spans.stream()
.filter(span -> span.getName().equals("POST v1beta1/echo:echo"))
.filter(span -> span.getName().equals(SPAN_NAME_ECHO_HTTP))
.findFirst()
.orElseThrow(
() -> new AssertionError("Attempt span 'POST v1beta1/echo:echo' not found"));
Expand All @@ -224,16 +249,10 @@ void testTracing_successfulEcho_httpjson() throws Exception {
.getAttributes()
.get(AttributeKey.longKey(ObservabilityAttributes.SERVER_PORT_ATTRIBUTE)))
.isEqualTo(SHOWCASE_SERVER_PORT);
assertThat(
attemptSpan
.getAttributes()
.get(AttributeKey.stringKey(ObservabilityAttributes.REPO_ATTRIBUTE)))
.isEqualTo(SHOWCASE_REPO);
assertThat(
attemptSpan
.getAttributes()
.get(AttributeKey.stringKey(ObservabilityAttributes.ARTIFACT_ATTRIBUTE)))
.isEqualTo(SHOWCASE_ARTIFACT);
assertThat(attemptSpan.getAttributes().get(RPC_SYSTEM_KEY)).isEqualTo(VALUE_HTTP);
assertThat(attemptSpan.getAttributes().get(HTTP_RESPONSE_STATUS_KEY)).isEqualTo(200L);
assertThat(attemptSpan.getAttributes().get(REPO_KEY)).isEqualTo(SHOWCASE_REPO);
assertThat(attemptSpan.getAttributes().get(ARTIFACT_KEY)).isEqualTo(SHOWCASE_ARTIFACT);
assertThat(
attemptSpan
.getAttributes()
Expand Down Expand Up @@ -293,6 +312,60 @@ private long computeExpectedHttpJsonResponseSize(Message message)
return jsonPayload.getBytes(StandardCharsets.UTF_8).length;
}

@Test
void testTracing_successfulIdentityGetUser_grpc() throws Exception {
SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk);

try (IdentityClient client =
TestClientInitializer.createGrpcIdentityClientOpentelemetry(tracingFactory)) {

try {
client.getUser(GetUserRequest.newBuilder().setName("users/test-user").build());
} catch (Exception e) {
// Ignored, the showcase server may not have this user, but trace is still
// generated.
}

List<SpanData> spans = spanExporter.getFinishedSpanItems();
assertThat(spans).isNotEmpty();

SpanData attemptSpan =
spans.stream()
.filter(span -> span.getName().equals(SPAN_NAME_GET_USER_GRPC))
.findFirst()
.orElseThrow(() -> new AssertionError("Incorrect span name"));
assertThat(attemptSpan.getAttributes().get(DESTINATION_RESOURCE_ID_KEY))
.isEqualTo(VALUE_TEST_USER);
}
}

@Test
void testTracing_successfulIdentityGetUser_httpjson() throws Exception {
SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk);

try (IdentityClient client =
TestClientInitializer.createHttpJsonIdentityClientOpentelemetry(tracingFactory)) {

try {
client.getUser(GetUserRequest.newBuilder().setName("users/test-user").build());
} catch (Exception e) {
// Ignored, the showcase server may not have this user, but trace is still
// generated.
}

List<SpanData> spans = spanExporter.getFinishedSpanItems();
assertThat(spans).isNotEmpty();

SpanData attemptSpan =
spans.stream()
.filter(span -> span.getName().equals(SPAN_NAME_GET_USER_HTTP))
.findFirst()
.orElseThrow(() -> new AssertionError("Incorrect span name"));
assertThat(attemptSpan.getAttributes().get(DESTINATION_RESOURCE_ID_KEY))
.isEqualTo(VALUE_TEST_USER);
}
}

@Test
void testTracing_retry_grpc() throws Exception {
final int attempts = 5;
Expand Down Expand Up @@ -443,7 +516,7 @@ void testTracing_retry_httpjson() throws Exception {
assertThat(resendCounts).containsExactlyElementsIn(expectedCounts).inOrder();
}

private void verifyErrorTypeAttribute(String expectedErrorType) {
private SpanData getErrorSpan() {
List<SpanData> spans = spanExporter.getFinishedSpanItems();
assertThat(spans).isNotEmpty();

Expand All @@ -458,16 +531,11 @@ private void verifyErrorTypeAttribute(String expectedErrorType) {
!= null)
.findFirst()
.orElseThrow(() -> new AssertionError("Span with error.type not found"));

assertThat(
errorSpan
.getAttributes()
.get(AttributeKey.stringKey(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE)))
.isEqualTo(expectedErrorType);
return errorSpan;
}

@Test
void testTracing_failedEcho_grpc_recordsErrorType() throws Exception {
void testTracing_failedEcho_grpc_recordsErrorAttributes() throws Exception {
SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk);

ClientInterceptor interceptor =
Expand Down Expand Up @@ -509,53 +577,17 @@ public void sendMessage(ReqT message) {}
EchoRequest echoRequest = EchoRequest.newBuilder().build();

assertThrows(UnavailableException.class, () -> client.echo(echoRequest));
verifyErrorTypeAttribute("UNAVAILABLE");
SpanData errorSpan = getErrorSpan();
assertThat(errorSpan.getAttributes().get(ERROR_TYPE_KEY)).isEqualTo(VALUE_UNAVAILABLE);
assertThat(errorSpan.getAttributes().get(EXCEPTION_TYPE_KEY))
.isEqualTo("com.google.api.gax.rpc.UnavailableException");
assertThat(errorSpan.getAttributes().get(STATUS_MESSAGE_KEY))
.isEqualTo("io.grpc.StatusRuntimeException: UNAVAILABLE");
}
}

@Test
void testTracing_statusCodes_grpc() throws Exception {
SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk);
EchoRequest errorRequest =
EchoRequest.newBuilder()
.setError(
Status.newBuilder().setCode(StatusCode.Code.INVALID_ARGUMENT.ordinal()).build())
.build();
EchoRequest successRequest = EchoRequest.newBuilder().setContent("tracing-test").build();

try (EchoClient grpcClient =
TestClientInitializer.createGrpcEchoClientOpentelemetry(tracingFactory)) {

grpcClient.echo(successRequest);
assertThrows(
com.google.api.gax.rpc.InvalidArgumentException.class,
() -> grpcClient.echo(errorRequest));

List<SpanData> spans = spanExporter.getFinishedSpanItems();
assertThat(spans).hasSize(2);

SpanData grpcSuccessSpan = spans.get(0);
assertThat(
grpcSuccessSpan
.getAttributes()
.get(
AttributeKey.stringKey(
ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
.isEqualTo("OK");

SpanData grpcErrorSpan = spans.get(1);
assertThat(
grpcErrorSpan
.getAttributes()
.get(
AttributeKey.stringKey(
ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
.isEqualTo("INVALID_ARGUMENT");
}
}

@Test
void testTracing_failedEcho_httpjson_recordsErrorType() throws Exception {
void testTracing_failedEcho_httpjson_recordsErrorAttributes() throws Exception {
SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk);

HttpTransport mockTransport =
Expand Down Expand Up @@ -645,10 +677,57 @@ public String getHeaderValue(int index) {
EchoRequest echoRequest = EchoRequest.newBuilder().build();

assertThrows(UnavailableException.class, () -> client.echo(echoRequest));
verifyErrorTypeAttribute("503");
SpanData errorSpan = getErrorSpan();
assertThat(errorSpan.getAttributes().get(ERROR_TYPE_KEY)).isEqualTo("503");
assertThat(errorSpan.getAttributes().get(EXCEPTION_TYPE_KEY))
.isEqualTo("com.google.api.gax.rpc.UnavailableException");
assertThat(errorSpan.getAttributes().get(STATUS_MESSAGE_KEY))
.isEqualTo(VALUE_SERVICE_UNAVAILABLE);
}
}

@Test
void testTracing_statusCodes_grpc() throws Exception {
SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk);
EchoRequest errorRequest =
EchoRequest.newBuilder()
.setError(
Status.newBuilder().setCode(StatusCode.Code.INVALID_ARGUMENT.ordinal()).build())
.build();
EchoRequest successRequest = EchoRequest.newBuilder().setContent("tracing-test").build();

try (EchoClient grpcClient =
TestClientInitializer.createGrpcEchoClientOpentelemetry(tracingFactory)) {

grpcClient.echo(successRequest);
assertThrows(
com.google.api.gax.rpc.InvalidArgumentException.class,
() -> grpcClient.echo(errorRequest));

List<SpanData> spans = spanExporter.getFinishedSpanItems();
assertThat(spans).hasSize(2);

SpanData grpcSuccessSpan = spans.get(0);
assertThat(
grpcSuccessSpan
.getAttributes()
.get(
AttributeKey.stringKey(
ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
.isEqualTo("OK");

SpanData grpcErrorSpan = spans.get(1);
assertThat(
grpcErrorSpan
.getAttributes()
.get(
AttributeKey.stringKey(
ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
.isEqualTo("INVALID_ARGUMENT");
}
}

@Test
void testTracing_statusCodes_httpjson() throws Exception {
SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk);
EchoRequest errorRequest =
Expand Down
Loading