@@ -116,6 +116,9 @@ public final class GrpcStorageOptions extends StorageOptions
116116 private final GrpcRetryAlgorithmManager retryAlgorithmManager ;
117117 private final Duration terminationAwaitDuration ;
118118 private final boolean attemptDirectPath ;
119+ private final boolean enableGrpcClientMetrics ;
120+
121+ private final boolean grpcClientMetricsManuallyEnabled ;
119122 private final GrpcInterceptorProvider grpcInterceptorProvider ;
120123 private final BlobWriteSessionConfig blobWriteSessionConfig ;
121124
@@ -129,6 +132,8 @@ private GrpcStorageOptions(Builder builder, GrpcStorageDefaults serviceDefaults)
129132 MoreObjects .firstNonNull (
130133 builder .terminationAwaitDuration , serviceDefaults .getTerminationAwaitDuration ());
131134 this .attemptDirectPath = builder .attemptDirectPath ;
135+ this .enableGrpcClientMetrics = builder .enableGrpcClientMetrics ;
136+ this .grpcClientMetricsManuallyEnabled = builder .grpcMetricsManuallyEnabled ;
132137 this .grpcInterceptorProvider = builder .grpcInterceptorProvider ;
133138 this .blobWriteSessionConfig = builder .blobWriteSessionConfig ;
134139 }
@@ -287,6 +292,16 @@ private Tuple<StorageSettings, Opts<UserProject>> resolveSettingsAndOpts() throw
287292 if (scheme .equals ("http" )) {
288293 channelProviderBuilder .setChannelConfigurator (ManagedChannelBuilder ::usePlaintext );
289294 }
295+
296+ if (enableGrpcClientMetrics ) {
297+ OpenTelemetryBootstrappingUtils .enableGrpcMetrics (
298+ channelProviderBuilder ,
299+ endpoint ,
300+ this .getProjectId (),
301+ this .getUniverseDomain (),
302+ !grpcClientMetricsManuallyEnabled );
303+ }
304+
290305 builder .setTransportChannelProvider (channelProviderBuilder .build ());
291306 RetrySettings baseRetrySettings = getRetrySettings ();
292307 RetrySettings readRetrySettings =
@@ -350,6 +365,7 @@ public int hashCode() {
350365 retryAlgorithmManager ,
351366 terminationAwaitDuration ,
352367 attemptDirectPath ,
368+ enableGrpcClientMetrics ,
353369 grpcInterceptorProvider ,
354370 blobWriteSessionConfig ,
355371 baseHashCode ());
@@ -365,6 +381,7 @@ public boolean equals(Object o) {
365381 }
366382 GrpcStorageOptions that = (GrpcStorageOptions ) o ;
367383 return attemptDirectPath == that .attemptDirectPath
384+ && enableGrpcClientMetrics == that .enableGrpcClientMetrics
368385 && Objects .equals (retryAlgorithmManager , that .retryAlgorithmManager )
369386 && Objects .equals (terminationAwaitDuration , that .terminationAwaitDuration )
370387 && Objects .equals (grpcInterceptorProvider , that .grpcInterceptorProvider )
@@ -408,11 +425,15 @@ public static final class Builder extends StorageOptions.Builder {
408425 private StorageRetryStrategy storageRetryStrategy ;
409426 private Duration terminationAwaitDuration ;
410427 private boolean attemptDirectPath = GrpcStorageDefaults .INSTANCE .isAttemptDirectPath ();
428+ private boolean enableGrpcClientMetrics =
429+ GrpcStorageDefaults .INSTANCE .isEnableGrpcClientMetrics ();
411430 private GrpcInterceptorProvider grpcInterceptorProvider =
412431 GrpcStorageDefaults .INSTANCE .grpcInterceptorProvider ();
413432 private BlobWriteSessionConfig blobWriteSessionConfig =
414433 GrpcStorageDefaults .INSTANCE .getDefaultStorageWriterConfig ();
415434
435+ private boolean grpcMetricsManuallyEnabled = false ;
436+
416437 Builder () {}
417438
418439 Builder (StorageOptions options ) {
@@ -421,6 +442,7 @@ public static final class Builder extends StorageOptions.Builder {
421442 this .storageRetryStrategy = gso .getRetryAlgorithmManager ().retryStrategy ;
422443 this .terminationAwaitDuration = gso .getTerminationAwaitDuration ();
423444 this .attemptDirectPath = gso .attemptDirectPath ;
445+ this .enableGrpcClientMetrics = gso .enableGrpcClientMetrics ;
424446 this .grpcInterceptorProvider = gso .grpcInterceptorProvider ;
425447 this .blobWriteSessionConfig = gso .blobWriteSessionConfig ;
426448 }
@@ -454,6 +476,21 @@ public GrpcStorageOptions.Builder setAttemptDirectPath(boolean attemptDirectPath
454476 this .attemptDirectPath = attemptDirectPath ;
455477 return this ;
456478 }
479+ /**
480+ * Option for whether this client should emit internal gRPC client internal metrics to Cloud
481+ * Monitoring. To disable metric reporting, set this to false. True by default. Emitting metrics
482+ * is free and requires minimal CPU and memory.
483+ *
484+ * @since 2.41.0 This new api is in preview and is subject to breaking changes.
485+ */
486+ @ BetaApi
487+ public GrpcStorageOptions .Builder setEnableGrpcClientMetrics (boolean enableGrpcClientMetrics ) {
488+ this .enableGrpcClientMetrics = enableGrpcClientMetrics ;
489+ if (enableGrpcClientMetrics ) {
490+ grpcMetricsManuallyEnabled = true ;
491+ }
492+ return this ;
493+ }
457494
458495 /** @since 2.14.0 This new api is in preview and is subject to breaking changes. */
459496 @ BetaApi
@@ -660,6 +697,12 @@ public boolean isAttemptDirectPath() {
660697 return false ;
661698 }
662699
700+ /** @since 2.41.0 This new api is in preview and is subject to breaking changes. */
701+ @ BetaApi
702+ public boolean isEnableGrpcClientMetrics () {
703+ return true ;
704+ }
705+
663706 /** @since 2.22.3 This new api is in preview and is subject to breaking changes. */
664707 @ BetaApi
665708 public GrpcInterceptorProvider grpcInterceptorProvider () {
0 commit comments