Skip to content

Commit dd889ea

Browse files
authored
feat: introductory beta level support for OpenTelemetry tracing on c.g.c.storage.Storage methods (#2837)
1 parent 1863c65 commit dd889ea

File tree

11 files changed

+2230
-19
lines changed

11 files changed

+2230
-19
lines changed

‎google-cloud-storage/clirr-ignored-differences.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,17 @@
9696
<method>boolean equals(java.lang.Object)</method>
9797
</difference>
9898

99+
<difference>
100+
<differenceType>7013</differenceType>
101+
<className>com/google/cloud/storage/StorageOptions$Builder</className>
102+
<method>com.google.cloud.storage.StorageOptions$Builder setOpenTelemetry(io.opentelemetry.api.OpenTelemetry)</method>
103+
</difference>
104+
105+
<difference>
106+
<differenceType>7013</differenceType>
107+
<className>com/google/cloud/storage/StorageOptions</className>
108+
<method>io.opentelemetry.api.OpenTelemetry getOpenTelemetry()</method>
109+
</difference>
110+
111+
99112
</differences>

‎google-cloud-storage/pom.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@
8383
<groupId>io.opencensus</groupId>
8484
<artifactId>opencensus-api</artifactId>
8585
</dependency>
86+
<dependency>
87+
<groupId>io.opentelemetry</groupId>
88+
<artifactId>opentelemetry-context</artifactId>
89+
</dependency>
8690
<dependency>
8791
<groupId>com.google.api.grpc</groupId>
8892
<artifactId>proto-google-iam-v1</artifactId>
@@ -205,6 +209,11 @@
205209
<artifactId>grpc-googleapis</artifactId>
206210
<scope>runtime</scope>
207211
</dependency>
212+
<dependency>
213+
<groupId>io.opentelemetry</groupId>
214+
<artifactId>opentelemetry-sdk-trace</artifactId>
215+
<scope>test</scope>
216+
</dependency>
208217

209218
<!--
210219
We're not using this directly, however there appears to be some resolution

‎google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageOptions.java

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,11 @@
8181
import io.grpc.MethodDescriptor;
8282
import io.grpc.Status;
8383
import io.grpc.protobuf.ProtoUtils;
84+
import io.opentelemetry.api.OpenTelemetry;
8485
import java.io.Closeable;
8586
import java.io.IOException;
8687
import java.io.InputStream;
88+
import java.io.ObjectInputStream;
8789
import java.io.Serializable;
8890
import java.net.URI;
8991
import 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);

‎google-cloud-storage/src/main/java/com/google/cloud/storage/HttpStorageOptions.java

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.google.cloud.storage.spi.v1.StorageRpc;
3939
import com.google.common.base.MoreObjects;
4040
import com.google.common.collect.ImmutableSet;
41+
import io.opentelemetry.api.OpenTelemetry;
4142
import java.io.IOException;
4243
import java.io.ObjectInputStream;
4344
import java.io.Serializable;
@@ -59,6 +60,8 @@ public class HttpStorageOptions extends StorageOptions {
5960
private transient RetryDependenciesAdapter retryDepsAdapter;
6061
private final BlobWriteSessionConfig blobWriteSessionConfig;
6162

63+
private transient OpenTelemetry openTelemetry;
64+
6265
private HttpStorageOptions(Builder builder, StorageDefaults serviceDefaults) {
6366
super(builder, serviceDefaults);
6467
this.retryAlgorithmManager =
@@ -67,6 +70,7 @@ private HttpStorageOptions(Builder builder, StorageDefaults serviceDefaults) {
6770
builder.storageRetryStrategy, defaults().getStorageRetryStrategy()));
6871
retryDepsAdapter = new RetryDependenciesAdapter();
6972
blobWriteSessionConfig = builder.blobWriteSessionConfig;
73+
openTelemetry = builder.openTelemetry;
7074
}
7175

7276
@Override
@@ -84,14 +88,22 @@ StorageRpc getStorageRpcV1() {
8488
return (StorageRpc) getRpc();
8589
}
8690

91+
/** @since 2.47.0 This new api is in preview and is subject to breaking changes. */
92+
@BetaApi
93+
@Override
94+
public OpenTelemetry getOpenTelemetry() {
95+
return openTelemetry;
96+
}
97+
8798
@Override
8899
public HttpStorageOptions.Builder toBuilder() {
89100
return new HttpStorageOptions.Builder(this);
90101
}
91102

92103
@Override
93104
public int hashCode() {
94-
return Objects.hash(retryAlgorithmManager, blobWriteSessionConfig, baseHashCode());
105+
return Objects.hash(
106+
retryAlgorithmManager, blobWriteSessionConfig, openTelemetry, baseHashCode());
95107
}
96108

97109
@Override
@@ -105,12 +117,14 @@ public boolean equals(Object o) {
105117
HttpStorageOptions that = (HttpStorageOptions) o;
106118
return Objects.equals(retryAlgorithmManager, that.retryAlgorithmManager)
107119
&& Objects.equals(blobWriteSessionConfig, that.blobWriteSessionConfig)
120+
&& Objects.equals(openTelemetry, that.openTelemetry)
108121
&& this.baseEquals(that);
109122
}
110123

111124
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
112125
in.defaultReadObject();
113126
this.retryDepsAdapter = new RetryDependenciesAdapter();
127+
this.openTelemetry = HttpStorageOptions.getDefaultInstance().getOpenTelemetry();
114128
}
115129

116130
public static HttpStorageOptions.Builder newBuilder() {
@@ -135,6 +149,7 @@ public static class Builder extends StorageOptions.Builder {
135149
private StorageRetryStrategy storageRetryStrategy;
136150
private BlobWriteSessionConfig blobWriteSessionConfig =
137151
HttpStorageDefaults.INSTANCE.getDefaultStorageWriterConfig();
152+
private OpenTelemetry openTelemetry = HttpStorageDefaults.INSTANCE.getDefaultOpenTelemetry();
138153

139154
Builder() {}
140155

@@ -143,6 +158,7 @@ public static class Builder extends StorageOptions.Builder {
143158
HttpStorageOptions hso = (HttpStorageOptions) options;
144159
this.storageRetryStrategy = hso.retryAlgorithmManager.retryStrategy;
145160
this.blobWriteSessionConfig = hso.blobWriteSessionConfig;
161+
this.openTelemetry = hso.getOpenTelemetry();
146162
}
147163

148164
@Override
@@ -268,6 +284,19 @@ public HttpStorageOptions build() {
268284
}
269285
return options;
270286
}
287+
288+
/**
289+
* Enable OpenTelemetry Tracing and provide an instance for the client to use.
290+
*
291+
* @param openTelemetry User defined instance of OpenTelemetry to be used by the library
292+
* @since 2.47.0 This new api is in preview and is subject to breaking changes.
293+
*/
294+
@BetaApi
295+
public HttpStorageOptions.Builder setOpenTelemetry(OpenTelemetry openTelemetry) {
296+
requireNonNull(openTelemetry, "openTelemetry must be non null");
297+
this.openTelemetry = openTelemetry;
298+
return this;
299+
}
271300
}
272301

273302
public static final class HttpStorageDefaults extends StorageDefaults {
@@ -301,6 +330,12 @@ public StorageRetryStrategy getStorageRetryStrategy() {
301330
public BlobWriteSessionConfig getDefaultStorageWriterConfig() {
302331
return BlobWriteSessionConfigs.getDefault();
303332
}
333+
334+
/** @since 2.47.0 This new api is in preview and is subject to breaking changes. */
335+
@BetaApi
336+
public OpenTelemetry getDefaultOpenTelemetry() {
337+
return OpenTelemetry.noop();
338+
}
304339
}
305340

306341
/**
@@ -341,8 +376,12 @@ public Storage create(StorageOptions options) {
341376
HttpStorageOptions httpStorageOptions = (HttpStorageOptions) options;
342377
Clock clock = Clock.systemUTC();
343378
try {
344-
return new StorageImpl(
345-
httpStorageOptions, httpStorageOptions.blobWriteSessionConfig.createFactory(clock));
379+
StorageImpl storage =
380+
new StorageImpl(
381+
httpStorageOptions,
382+
httpStorageOptions.blobWriteSessionConfig.createFactory(clock));
383+
return OtelStorageDecorator.decorate(
384+
storage, httpStorageOptions.getOpenTelemetry(), Transport.HTTP);
346385
} catch (IOException e) {
347386
throw new IllegalStateException(
348387
"Unable to instantiate HTTP com.google.cloud.storage.Storage client.", e);

0 commit comments

Comments
 (0)