Skip to content
Closed
Show file tree
Hide file tree
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 @@ -35,25 +35,23 @@

import com.google.api.client.http.HttpTransport;
import com.google.api.gax.core.NoCredentialsProvider;
import com.google.api.gax.rpc.StatusCode;
import com.google.api.gax.retrying.RetrySettings;
import com.google.api.gax.rpc.TransportChannelProvider;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The new test cases use DeadlineExceededException. Please add the corresponding import to support the more specific assertions.

Suggested change
import com.google.api.gax.rpc.TransportChannelProvider;
import com.google.api.gax.rpc.DeadlineExceededException;
import com.google.api.gax.rpc.TransportChannelProvider;

import com.google.api.gax.rpc.UnavailableException;
import com.google.api.gax.tracing.GoldenSignalsMetricsTracerFactory;
import com.google.api.gax.tracing.ObservabilityAttributes;
import com.google.common.collect.ImmutableList;
import com.google.rpc.Status;
import com.google.showcase.v1beta1.EchoClient;
import com.google.showcase.v1beta1.EchoRequest;
import com.google.showcase.v1beta1.EchoResponse;
import com.google.showcase.v1beta1.EchoSettings;
import com.google.showcase.v1beta1.it.util.TestClientInitializer;
import com.google.showcase.v1beta1.stub.EchoStubSettings;
import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.ClientCall;
import io.grpc.ClientInterceptor;
import io.grpc.MethodDescriptor;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
Expand Down Expand Up @@ -103,7 +101,8 @@ void testMetrics_successfulEcho_grpc() throws Exception {

// The end of an operation is tracked in a separate thread.
// Add a small sleep to make sure the tracking is completed.
// This is implemented by adding a TraceFinisher to ApiFuture as a callback in TracedUnaryCallable,
// This is implemented by adding a TraceFinisher to ApiFuture as a callback in
// TracedUnaryCallable,
// which could be executed in a different thread.
Thread.sleep(100);
Collection<MetricData> metrics = metricReader.collectAllMetrics();
Expand All @@ -122,22 +121,27 @@ void testMetrics_successfulEcho_grpc() throws Exception {
durationMetric.getHistogramData().getPoints().iterator().next().getAttributes();

assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE)))
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE)))
.isEqualTo(SHOWCASE_SERVER_ADDRESS);
assertThat(
attributes.get(AttributeKey.longKey(ObservabilityAttributes.SERVER_PORT_ATTRIBUTE)))
.isEqualTo(SHOWCASE_SERVER_PORT);
assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE)))
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE)))
.isEqualTo("grpc");
assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE)))
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE)))
.isEqualTo("showcase");
assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE)))
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE)))
.isEqualTo("google.showcase.v1beta1.Echo/Echo");
assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
.isEqualTo("OK");
}
}
Expand Down Expand Up @@ -201,7 +205,8 @@ public void sendMessage(ReqT message) {}
durationMetric.getHistogramData().getPoints().iterator().next().getAttributes();

assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
.isEqualTo("UNAVAILABLE");
assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE)))
Expand Down Expand Up @@ -236,29 +241,36 @@ void testMetrics_successfulEcho_httpjson() throws Exception {
durationMetric.getHistogramData().getPoints().iterator().next().getAttributes();

assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE)))
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE)))
.isEqualTo(SHOWCASE_SERVER_ADDRESS);
assertThat(
attributes.get(AttributeKey.longKey(ObservabilityAttributes.SERVER_PORT_ATTRIBUTE)))
.isEqualTo(SHOWCASE_SERVER_PORT);
assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE)))
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE)))
.isEqualTo("http");
assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE)))
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE)))
.isEqualTo("showcase");
assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
.isEqualTo("OK");
assertThat(
attributes.get(AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE)))
attributes.get(
AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE)))
.isEqualTo(200L);
assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.URL_TEMPLATE_ATTRIBUTE)))
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.URL_TEMPLATE_ATTRIBUTE)))
.isEqualTo("v1beta1/echo:echo");
assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE)))
.isEqualTo("google.showcase.v1beta1.Echo/Echo");
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE)))
.isEqualTo("google.showcase.v1beta1.Echo/Echo");
}
}

Expand Down Expand Up @@ -369,14 +381,106 @@ public String getHeaderValue(int index) {
durationMetric.getHistogramData().getPoints().iterator().next().getAttributes();

assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
.isEqualTo("UNAVAILABLE");
assertThat(
attributes.get(AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE)))
attributes.get(
AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE)))
.isEqualTo(503L);
assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE)))
.isEqualTo("503");
}
}

@Test
void testMetrics_zeroDeadline_grpc() throws Exception {
GoldenSignalsMetricsTracerFactory tracerFactory =
new GoldenSignalsMetricsTracerFactory(openTelemetrySdk);

// Using 1ms as 0ms might be rejected by some validation or trigger immediate failure before
// metrics
RetrySettings zeroRetrySettings =
RetrySettings.newBuilder()
.setInitialRpcTimeout(org.threeten.bp.Duration.ofMillis(1))
.setMaxRpcTimeout(org.threeten.bp.Duration.ofMillis(1))
.setTotalTimeout(org.threeten.bp.Duration.ofMillis(1))
.setMaxAttempts(1)
.build();

try (EchoClient client =
TestClientInitializer.createGrpcEchoClientOpentelemetryWithRetrySettings(
tracerFactory, zeroRetrySettings)) {

assertThrows(
Exception.class,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using a more specific exception class like DeadlineExceededException.class is preferred over Exception.class. This ensures the test specifically validates the timeout behavior and doesn't pass due to unrelated errors (e.g., configuration issues).

Suggested change
Exception.class,
DeadlineExceededException.class,

() -> client.echo(EchoRequest.newBuilder().setContent("metrics-test").build()));

Thread.sleep(100);
Collection<MetricData> metrics = metricReader.collectAllMetrics();
assertThat(metrics).isNotEmpty();

MetricData durationMetric =
metrics.stream()
.filter(m -> m.getName().equals("gcp.client.request.duration"))
.findFirst()
.orElseThrow(() -> new AssertionError("Duration metric not found"));

io.opentelemetry.api.common.Attributes attributes =
durationMetric.getHistogramData().getPoints().iterator().next().getAttributes();

assertThat(
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
.isEqualTo("DEADLINE_EXCEEDED");
assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE)))
.isEqualTo("DEADLINE_EXCEEDED");
}
}

@Test
void testMetrics_zeroDeadline_httpjson() throws Exception {
GoldenSignalsMetricsTracerFactory tracerFactory =
new GoldenSignalsMetricsTracerFactory(openTelemetrySdk);

RetrySettings zeroRetrySettings =
RetrySettings.newBuilder()
.setInitialRpcTimeout(org.threeten.bp.Duration.ofMillis(1))
.setMaxRpcTimeout(org.threeten.bp.Duration.ofMillis(1))
.setTotalTimeout(org.threeten.bp.Duration.ofMillis(1))
.setMaxAttempts(1)
.build();

try (EchoClient client =
TestClientInitializer.createHttpJsonEchoClientOpentelemetryWithRetrySettings(
tracerFactory, zeroRetrySettings)) {

assertThrows(
Exception.class,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using a more specific exception class like DeadlineExceededException.class is preferred over Exception.class. This ensures the test specifically validates the timeout behavior and doesn't pass due to unrelated errors.

Suggested change
Exception.class,
DeadlineExceededException.class,

() -> client.echo(EchoRequest.newBuilder().setContent("metrics-test").build()));

Thread.sleep(100);
Collection<MetricData> metrics = metricReader.collectAllMetrics();
assertThat(metrics).isNotEmpty();

MetricData durationMetric =
metrics.stream()
.filter(m -> m.getName().equals("gcp.client.request.duration"))
.findFirst()
.orElseThrow(() -> new AssertionError("Duration metric not found"));

io.opentelemetry.api.common.Attributes attributes =
durationMetric.getHistogramData().getPoints().iterator().next().getAttributes();

assertThat(
attributes.get(
AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE)))
.isEqualTo("DEADLINE_EXCEEDED");
assertThat(
attributes.get(AttributeKey.stringKey(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE)))
.isEqualTo("504");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import com.google.showcase.v1beta1.stub.EchoStubSettings;
import io.grpc.ClientInterceptor;
import io.grpc.ManagedChannelBuilder;

import java.io.IOException;
import java.util.List;
import java.util.Set;
Expand Down Expand Up @@ -329,6 +328,43 @@ public static EchoClient createHttpJsonEchoClientOpentelemetry(
return EchoClient.create(createStubWithServiceName(httpJsonEchoSettings, metricsTracerFactory));
}

public static EchoClient createGrpcEchoClientOpentelemetryWithRetrySettings(
ApiTracerFactory metricsTracerFactory, RetrySettings retrySettings) throws Exception {
EchoStubSettings.Builder grpcEchoSettingsBuilder = EchoStubSettings.newBuilder();
grpcEchoSettingsBuilder.echoSettings().setRetrySettings(retrySettings);
EchoSettings grpcEchoSettings = EchoSettings.create(grpcEchoSettingsBuilder.build());
grpcEchoSettings =
grpcEchoSettings.toBuilder()
.setCredentialsProvider(NoCredentialsProvider.create())
.setTransportChannelProvider(
EchoSettings.defaultGrpcTransportProviderBuilder()
.setChannelConfigurator(ManagedChannelBuilder::usePlaintext)
.build())
.setEndpoint(DEFAULT_GRPC_ENDPOINT)
.build();

return EchoClient.create(createStubWithServiceName(grpcEchoSettings, metricsTracerFactory));
}

public static EchoClient createHttpJsonEchoClientOpentelemetryWithRetrySettings(
ApiTracerFactory metricsTracerFactory, RetrySettings retrySettings) throws Exception {
EchoStubSettings.Builder httpJsonEchoSettingsBuilder = EchoStubSettings.newHttpJsonBuilder();
httpJsonEchoSettingsBuilder.echoSettings().setRetrySettings(retrySettings);
EchoSettings httpJsonEchoSettings = EchoSettings.create(httpJsonEchoSettingsBuilder.build());
httpJsonEchoSettings =
httpJsonEchoSettings.toBuilder()
.setCredentialsProvider(NoCredentialsProvider.create())
.setTransportChannelProvider(
EchoSettings.defaultHttpJsonTransportProviderBuilder()
.setHttpTransport(
new NetHttpTransport.Builder().doNotValidateCertificate().build())
.setEndpoint(DEFAULT_HTTPJSON_ENDPOINT)
.build())
.build();

return EchoClient.create(createStubWithServiceName(httpJsonEchoSettings, metricsTracerFactory));
}

public static IdentityClient createGrpcIdentityClientOpentelemetry(ApiTracerFactory tracerFactory)
throws Exception {
IdentitySettings grpcIdentitySettings =
Expand Down Expand Up @@ -371,9 +407,9 @@ public static IdentityClient createHttpJsonIdentityClientOpentelemetry(
}

private static EchoStub createStubWithServiceName(
EchoSettings settings, ApiTracerFactory tracingFactory) throws IOException {
EchoSettings settings, ApiTracerFactory tracingFactory) throws IOException {
EchoStubSettings.Builder builder =
(EchoStubSettings.Builder) settings.getStubSettings().toBuilder();
(EchoStubSettings.Builder) settings.getStubSettings().toBuilder();
builder.setTracerFactory(tracingFactory);
return new ExtendedEchoStubSettings(builder).createStub();
}
Expand Down
Loading