Skip to content
This repository has been archived by the owner on Dec 23, 2023. It is now read-only.

implement gRPC client retry stats measures and views #2084

Merged
Expand Up @@ -227,6 +227,37 @@ public final class RpcMeasureConstants {
Measure.MeasureLong.create(
"grpc.io/client/started_rpcs", "Number of started client RPCs.", COUNT);

/**
* {@link Measure} for total number of retry or hedging attempts excluding transparent retries
* made during the client call.
*
* @since 0.28
punya marked this conversation as resolved.
Show resolved Hide resolved
*/
public static final MeasureLong GRPC_CLIENT_RETRIES_PER_CALL =
Measure.MeasureLong.create(
"grpc.io/client/retries_per_call", "Number of retries per call.", COUNT);

/**
* {@link Measure} for total number of transparent retries made during the client call.
*
* @since 0.28
*/
public static final MeasureLong GRPC_CLIENT_TRANSPARENT_RETRIES_PER_CALL =
Measure.MeasureLong.create(
"grpc.io/client/transparent_retries_per_call",
"Number of transparent retries per call.",
COUNT);

/**
* {@link Measure} for total time of delay while there is no active attempt during the client
* call.
*
* @since 0.28
*/
public static final MeasureLong GRPC_CLIENT_RETRY_DELAY_PER_CALL =
Measure.MeasureLong.create(
"grpc.io/client/retry_delay_per_call", "Retry delay per call.", MILLISECOND);

/**
* {@link Measure} for gRPC client error counts.
*
Expand Down
Expand Up @@ -28,6 +28,9 @@
import static io.opencensus.contrib.grpc.metrics.RpcMeasureConstants.GRPC_CLIENT_SENT_MESSAGES_PER_RPC;
import static io.opencensus.contrib.grpc.metrics.RpcMeasureConstants.GRPC_CLIENT_SERVER_LATENCY;
import static io.opencensus.contrib.grpc.metrics.RpcMeasureConstants.GRPC_CLIENT_STARTED_RPCS;
import static io.opencensus.contrib.grpc.metrics.RpcMeasureConstants.GRPC_CLIENT_RETRIES_PER_CALL;
import static io.opencensus.contrib.grpc.metrics.RpcMeasureConstants.GRPC_CLIENT_TRANSPARENT_RETRIES_PER_CALL;
import static io.opencensus.contrib.grpc.metrics.RpcMeasureConstants.GRPC_CLIENT_RETRY_DELAY_PER_CALL;
import static io.opencensus.contrib.grpc.metrics.RpcMeasureConstants.GRPC_CLIENT_STATUS;
import static io.opencensus.contrib.grpc.metrics.RpcMeasureConstants.GRPC_SERVER_METHOD;
import static io.opencensus.contrib.grpc.metrics.RpcMeasureConstants.GRPC_SERVER_RECEIVED_BYTES_PER_METHOD;
Expand Down Expand Up @@ -502,6 +505,71 @@ public final class RpcViewConstants {
COUNT,
Arrays.asList(GRPC_CLIENT_METHOD));

/**
* {@link View} for client retries per call.
*
* @since 0.28
*/
public static final View GRPC_CLIENT_RETRIES_PER_CALL_VIEW =
View.create(
View.Name.create("grpc.io/client/retries_per_call"),
"Number of client retries per call",
GRPC_CLIENT_TRANSPARENT_RETRIES_PER_CALL,

Choose a reason for hiding this comment

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

should this be GRPC_CLIENT_RETRIES_PER_CALL ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes great catch, thanks @asafdav2 - updated

AGGREGATION_WITH_COUNT_HISTOGRAM,
Arrays.asList(GRPC_CLIENT_METHOD));

/**
* {@link View} for total transparent client retries across calls.
*
* @since 0.28
*/
public static final View GRPC_CLIENT_TRANSPARENT_RETRIES_VIEW =
View.create(
View.Name.create("grpc.io/client/transparent_retries"),
"Total number of transparent client retries across calls",
GRPC_CLIENT_TRANSPARENT_RETRIES_PER_CALL,
SUM,
Arrays.asList(GRPC_CLIENT_METHOD));

/**
* {@link View} for total time of delay while there is no active attempt during the client call.
*
* @since 0.28
*/
public static final View GRPC_CLIENT_RETRY_DELAY_PER_CALL_VIEW =
View.create(
View.Name.create("grpc.io/client/retry_delay_per_call"),
"Total time of delay while there is no active attempt during the client call",
GRPC_CLIENT_RETRY_DELAY_PER_CALL,
AGGREGATION_WITH_MILLIS_HISTOGRAM,
Arrays.asList(GRPC_CLIENT_METHOD));

/**
* {@link View} for total retries across all calls, excluding transparent retries
*
* @since 0.28
*/
public static final View GRPC_CLIENT_RETRIES_VIEW =
View.create(
View.Name.create("grpc.io/client/retries"),
"Total number of client retries across all calls",
GRPC_CLIENT_RETRIES_PER_CALL,
SUM,
Arrays.asList(GRPC_CLIENT_METHOD));

/**
* {@link View} for transparent retries per call
*
* @since 0.28
*/
public static final View GRPC_CLIENT_TRANSPARENT_RETRIES_PER_CALL_VIEW =
View.create(
View.Name.create("grpc.io/client/transparent_retries_per_call"),
"Number of transparent client retries per call",
GRPC_CLIENT_TRANSPARENT_RETRIES_PER_CALL,
AGGREGATION_WITH_COUNT_HISTOGRAM,
Arrays.asList(GRPC_CLIENT_METHOD));

// Rpc server cumulative views.

/**
Expand Down
Expand Up @@ -144,6 +144,15 @@ public final class RpcViews {
RpcViewConstants.GRPC_CLIENT_ROUNDTRIP_LATENCY_VIEW,
RpcViewConstants.GRPC_CLIENT_STARTED_RPC_VIEW);

@VisibleForTesting
static final ImmutableSet<View> GRPC_CLIENT_RETRY_VIEWS_SET =
ImmutableSet.of(
RpcViewConstants.GRPC_CLIENT_RETRIES_PER_CALL_VIEW,
RpcViewConstants.GRPC_CLIENT_RETRIES_VIEW,
RpcViewConstants.GRPC_CLIENT_TRANSPARENT_RETRIES_PER_CALL_VIEW,
RpcViewConstants.GRPC_CLIENT_TRANSPARENT_RETRIES_VIEW,
RpcViewConstants.GRPC_CLIENT_RETRY_DELAY_PER_CALL_VIEW);

@VisibleForTesting
static final ImmutableSet<View> GRPC_SERVER_BASIC_VIEWS_SET =
ImmutableSet.of(
Expand Down Expand Up @@ -188,6 +197,24 @@ static void registerClientGrpcViews(ViewManager viewManager) {
}
}

/**
* Registers client retry gRPC views.
*
* <p>It is recommended to call this method before doing any RPC call to avoid missing stats.
*
* @since 0.28
punya marked this conversation as resolved.
Show resolved Hide resolved
*/
public static void registerClientRetryGrpcViews() {
registerClientRetryGrpcViews(Stats.getViewManager());
}

@VisibleForTesting
static void registerClientRetryGrpcViews(ViewManager viewManager) {
for (View view : GRPC_CLIENT_RETRY_VIEWS_SET) {
viewManager.registerView(view);
}
}

/**
* Registers all standard server gRPC views.
*
Expand Down
Expand Up @@ -57,6 +57,9 @@ public void testConstants() {
assertThat(RpcMeasureConstants.GRPC_CLIENT_SERVER_LATENCY).isNotNull();
assertThat(RpcMeasureConstants.GRPC_CLIENT_ROUNDTRIP_LATENCY).isNotNull();
assertThat(RpcMeasureConstants.GRPC_CLIENT_STARTED_RPCS).isNotNull();
assertThat(RpcMeasureConstants.GRPC_CLIENT_RETRIES_PER_CALL).isNotNull();
assertThat(RpcMeasureConstants.GRPC_CLIENT_TRANSPARENT_RETRIES_PER_CALL).isNotNull();
assertThat(RpcMeasureConstants.GRPC_CLIENT_RETRY_DELAY_PER_CALL).isNotNull();

// Test server measurement descriptors.
assertThat(RpcMeasureConstants.RPC_SERVER_ERROR_COUNT).isNotNull();
Expand Down
Expand Up @@ -112,7 +112,11 @@ public void testConstants() {
assertThat(RpcViewConstants.GRPC_CLIENT_SENT_MESSAGES_PER_METHOD_VIEW).isNotNull();
assertThat(RpcViewConstants.GRPC_CLIENT_RECEIVED_MESSAGES_PER_METHOD_VIEW).isNotNull();
assertThat(RpcViewConstants.GRPC_CLIENT_SERVER_LATENCY_VIEW).isNotNull();
assertThat(RpcViewConstants.GRPC_CLIENT_STARTED_RPC_VIEW).isNotNull();
assertThat(RpcViewConstants.GRPC_CLIENT_RETRIES_PER_CALL_VIEW).isNotNull();
assertThat(RpcViewConstants.GRPC_CLIENT_RETRIES_VIEW).isNotNull();
assertThat(RpcViewConstants.GRPC_CLIENT_TRANSPARENT_RETRIES_PER_CALL_VIEW).isNotNull();
assertThat(RpcViewConstants.GRPC_CLIENT_TRANSPARENT_RETRIES_VIEW).isNotNull();
assertThat(RpcViewConstants.GRPC_CLIENT_RETRY_DELAY_PER_CALL_VIEW).isNotNull();

// Test server distribution view descriptors.
assertThat(RpcViewConstants.RPC_SERVER_ERROR_COUNT_VIEW).isNotNull();
Expand Down
Expand Up @@ -83,6 +83,14 @@ public void registerClientGrpcViews() {
.containsExactlyElementsIn(RpcViews.GRPC_CLIENT_VIEWS_SET);
}

@Test
public void registerClientRetryGrpcViews() {
FakeViewManager fakeViewManager = new FakeViewManager();
RpcViews.registerClientRetryGrpcViews(fakeViewManager);
assertThat(fakeViewManager.getRegisteredViews())
.containsExactlyElementsIn(RpcViews.GRPC_CLIENT_RETRY_VIEWS_SET);
}

@Test
public void registerServerGrpcViews() {
FakeViewManager fakeViewManager = new FakeViewManager();
Expand Down