8181import io .grpc .MethodDescriptor ;
8282import io .grpc .Status ;
8383import io .grpc .protobuf .ProtoUtils ;
84+ import io .opentelemetry .api .OpenTelemetry ;
8485import java .io .Closeable ;
8586import java .io .IOException ;
8687import java .io .InputStream ;
88+ import java .io .ObjectInputStream ;
8789import java .io .Serializable ;
8890import java .net .URI ;
8991import java .nio .ByteBuffer ;
@@ -119,6 +121,7 @@ public final class GrpcStorageOptions extends StorageOptions
119121 private final boolean grpcClientMetricsManuallyEnabled ;
120122 private final GrpcInterceptorProvider grpcInterceptorProvider ;
121123 private final BlobWriteSessionConfig blobWriteSessionConfig ;
124+ private transient OpenTelemetry openTelemetry ;
122125
123126 private GrpcStorageOptions (Builder builder , GrpcStorageDefaults serviceDefaults ) {
124127 super (builder , serviceDefaults );
@@ -135,6 +138,7 @@ private GrpcStorageOptions(Builder builder, GrpcStorageDefaults serviceDefaults)
135138 this .grpcClientMetricsManuallyEnabled = builder .grpcMetricsManuallyEnabled ;
136139 this .grpcInterceptorProvider = builder .grpcInterceptorProvider ;
137140 this .blobWriteSessionConfig = builder .blobWriteSessionConfig ;
141+ this .openTelemetry = builder .openTelemetry ;
138142 }
139143
140144 @ Override
@@ -157,6 +161,11 @@ StorageSettings getStorageSettings() throws IOException {
157161 return resolveSettingsAndOpts ().x ();
158162 }
159163
164+ private void readObject (ObjectInputStream in ) throws IOException , ClassNotFoundException {
165+ in .defaultReadObject ();
166+ this .openTelemetry = HttpStorageOptions .getDefaultInstance ().getOpenTelemetry ();
167+ }
168+
160169 /**
161170 * We have to perform several introspections and detections to cross-wire/support several features
162171 * that are either gapic primitives, ServiceOption primitives or GCS semantic requirements.
@@ -349,6 +358,13 @@ private Tuple<StorageSettings, Opts<UserProject>> resolveSettingsAndOpts() throw
349358 return Tuple .of (builder .build (), defaultOpts );
350359 }
351360
361+ /** @since 2.47.0 This new api is in preview and is subject to breaking changes. */
362+ @ BetaApi
363+ @ Override
364+ public OpenTelemetry getOpenTelemetry () {
365+ return openTelemetry ;
366+ }
367+
352368 /** @since 2.14.0 */
353369 @ Override
354370 public GrpcStorageOptions .Builder toBuilder () {
@@ -364,6 +380,7 @@ public int hashCode() {
364380 enableGrpcClientMetrics ,
365381 grpcInterceptorProvider ,
366382 blobWriteSessionConfig ,
383+ openTelemetry ,
367384 baseHashCode ());
368385 }
369386
@@ -382,6 +399,7 @@ public boolean equals(Object o) {
382399 && Objects .equals (terminationAwaitDuration , that .terminationAwaitDuration )
383400 && Objects .equals (grpcInterceptorProvider , that .grpcInterceptorProvider )
384401 && Objects .equals (blobWriteSessionConfig , that .blobWriteSessionConfig )
402+ && Objects .equals (openTelemetry , that .openTelemetry )
385403 && this .baseEquals (that );
386404 }
387405
@@ -423,6 +441,7 @@ public static final class Builder extends StorageOptions.Builder {
423441 GrpcStorageDefaults .INSTANCE .grpcInterceptorProvider ();
424442 private BlobWriteSessionConfig blobWriteSessionConfig =
425443 GrpcStorageDefaults .INSTANCE .getDefaultStorageWriterConfig ();
444+ private OpenTelemetry openTelemetry = GrpcStorageDefaults .INSTANCE .getDefaultOpenTelemetry ();
426445
427446 private boolean grpcMetricsManuallyEnabled = false ;
428447
@@ -437,6 +456,7 @@ public static final class Builder extends StorageOptions.Builder {
437456 this .enableGrpcClientMetrics = gso .enableGrpcClientMetrics ;
438457 this .grpcInterceptorProvider = gso .grpcInterceptorProvider ;
439458 this .blobWriteSessionConfig = gso .blobWriteSessionConfig ;
459+ this .openTelemetry = gso .openTelemetry ;
440460 }
441461
442462 /**
@@ -619,6 +639,19 @@ public GrpcStorageOptions.Builder setBlobWriteSessionConfig(
619639 return this ;
620640 }
621641
642+ /**
643+ * Enable OpenTelemetry Tracing and provide an instance for the client to use.
644+ *
645+ * @param openTelemetry User defined instance of OpenTelemetry to be used by the library
646+ * @since 2.47.0 This new api is in preview and is subject to breaking changes.
647+ */
648+ @ BetaApi
649+ public GrpcStorageOptions .Builder setOpenTelemetry (OpenTelemetry openTelemetry ) {
650+ requireNonNull (openTelemetry , "openTelemetry must be non null" );
651+ this .openTelemetry = openTelemetry ;
652+ return this ;
653+ }
654+
622655 /** @since 2.14.0 */
623656 @ Override
624657 public GrpcStorageOptions build () {
@@ -695,6 +728,12 @@ public GrpcInterceptorProvider grpcInterceptorProvider() {
695728 public BlobWriteSessionConfig getDefaultStorageWriterConfig () {
696729 return BlobWriteSessionConfigs .getDefault ();
697730 }
731+
732+ /** @since 2.47.0 This new api is in preview and is subject to breaking changes. */
733+ @ BetaApi
734+ public OpenTelemetry getDefaultOpenTelemetry () {
735+ return OpenTelemetry .noop ();
736+ }
698737 }
699738
700739 /**
@@ -751,22 +790,27 @@ public Storage create(StorageOptions options) {
751790 new InternalZeroCopyGrpcStorageStub (
752791 stubSettings , clientContext , grpcStorageCallableFactory );
753792 StorageClient client = new InternalStorageClient (stub );
754- return new GrpcStorageImpl (
755- grpcStorageOptions ,
756- client ,
757- stub .getObjectMediaResponseMarshaller ,
758- grpcStorageOptions .blobWriteSessionConfig .createFactory (Clock .systemUTC ()),
759- defaultOpts );
793+ GrpcStorageImpl grpcStorage =
794+ new GrpcStorageImpl (
795+ grpcStorageOptions ,
796+ client ,
797+ stub .getObjectMediaResponseMarshaller ,
798+ grpcStorageOptions .blobWriteSessionConfig .createFactory (Clock .systemUTC ()),
799+ defaultOpts );
800+ return OtelStorageDecorator .decorate (
801+ grpcStorage , options .getOpenTelemetry (), Transport .GRPC );
760802 } else {
761803 StorageClient client = StorageClient .create (storageSettings );
762- return new GrpcStorageImpl (
763- grpcStorageOptions ,
764- client ,
765- ResponseContentLifecycleManager .noop (),
766- grpcStorageOptions .blobWriteSessionConfig .createFactory (Clock .systemUTC ()),
767- defaultOpts );
804+ GrpcStorageImpl grpcStorage =
805+ new GrpcStorageImpl (
806+ grpcStorageOptions ,
807+ client ,
808+ ResponseContentLifecycleManager .noop (),
809+ grpcStorageOptions .blobWriteSessionConfig .createFactory (Clock .systemUTC ()),
810+ defaultOpts );
811+ return OtelStorageDecorator .decorate (
812+ grpcStorage , options .getOpenTelemetry (), Transport .GRPC );
768813 }
769-
770814 } catch (IOException e ) {
771815 throw new IllegalStateException (
772816 "Unable to instantiate gRPC com.google.cloud.storage.Storage client." , e );
0 commit comments