Skip to content

Commit

Permalink
feat: introductory beta level support for OpenTelemetry tracing on c.…
Browse files Browse the repository at this point in the history
…g.c.storage.Storage methods (#2837)
  • Loading branch information
sydney-munro authored Jan 6, 2025
1 parent 1863c65 commit dd889ea
Show file tree
Hide file tree
Showing 11 changed files with 2,230 additions and 19 deletions.
13 changes: 13 additions & 0 deletions google-cloud-storage/clirr-ignored-differences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,17 @@
<method>boolean equals(java.lang.Object)</method>
</difference>

<difference>
<differenceType>7013</differenceType>
<className>com/google/cloud/storage/StorageOptions$Builder</className>
<method>com.google.cloud.storage.StorageOptions$Builder setOpenTelemetry(io.opentelemetry.api.OpenTelemetry)</method>
</difference>

<difference>
<differenceType>7013</differenceType>
<className>com/google/cloud/storage/StorageOptions</className>
<method>io.opentelemetry.api.OpenTelemetry getOpenTelemetry()</method>
</difference>


</differences>
9 changes: 9 additions & 0 deletions google-cloud-storage/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@
<groupId>io.opencensus</groupId>
<artifactId>opencensus-api</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-context</artifactId>
</dependency>
<dependency>
<groupId>com.google.api.grpc</groupId>
<artifactId>proto-google-iam-v1</artifactId>
Expand Down Expand Up @@ -205,6 +209,11 @@
<artifactId>grpc-googleapis</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-trace</artifactId>
<scope>test</scope>
</dependency>

<!--
We're not using this directly, however there appears to be some resolution
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,11 @@
import io.grpc.MethodDescriptor;
import io.grpc.Status;
import io.grpc.protobuf.ProtoUtils;
import io.opentelemetry.api.OpenTelemetry;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.net.URI;
import java.nio.ByteBuffer;
Expand Down Expand Up @@ -119,6 +121,7 @@ public final class GrpcStorageOptions extends StorageOptions
private final boolean grpcClientMetricsManuallyEnabled;
private final GrpcInterceptorProvider grpcInterceptorProvider;
private final BlobWriteSessionConfig blobWriteSessionConfig;
private transient OpenTelemetry openTelemetry;

private GrpcStorageOptions(Builder builder, GrpcStorageDefaults serviceDefaults) {
super(builder, serviceDefaults);
Expand All @@ -135,6 +138,7 @@ private GrpcStorageOptions(Builder builder, GrpcStorageDefaults serviceDefaults)
this.grpcClientMetricsManuallyEnabled = builder.grpcMetricsManuallyEnabled;
this.grpcInterceptorProvider = builder.grpcInterceptorProvider;
this.blobWriteSessionConfig = builder.blobWriteSessionConfig;
this.openTelemetry = builder.openTelemetry;
}

@Override
Expand All @@ -157,6 +161,11 @@ StorageSettings getStorageSettings() throws IOException {
return resolveSettingsAndOpts().x();
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
this.openTelemetry = HttpStorageOptions.getDefaultInstance().getOpenTelemetry();
}

/**
* We have to perform several introspections and detections to cross-wire/support several features
* that are either gapic primitives, ServiceOption primitives or GCS semantic requirements.
Expand Down Expand Up @@ -349,6 +358,13 @@ private Tuple<StorageSettings, Opts<UserProject>> resolveSettingsAndOpts() throw
return Tuple.of(builder.build(), defaultOpts);
}

/** @since 2.47.0 This new api is in preview and is subject to breaking changes. */
@BetaApi
@Override
public OpenTelemetry getOpenTelemetry() {
return openTelemetry;
}

/** @since 2.14.0 */
@Override
public GrpcStorageOptions.Builder toBuilder() {
Expand All @@ -364,6 +380,7 @@ public int hashCode() {
enableGrpcClientMetrics,
grpcInterceptorProvider,
blobWriteSessionConfig,
openTelemetry,
baseHashCode());
}

Expand All @@ -382,6 +399,7 @@ public boolean equals(Object o) {
&& Objects.equals(terminationAwaitDuration, that.terminationAwaitDuration)
&& Objects.equals(grpcInterceptorProvider, that.grpcInterceptorProvider)
&& Objects.equals(blobWriteSessionConfig, that.blobWriteSessionConfig)
&& Objects.equals(openTelemetry, that.openTelemetry)
&& this.baseEquals(that);
}

Expand Down Expand Up @@ -423,6 +441,7 @@ public static final class Builder extends StorageOptions.Builder {
GrpcStorageDefaults.INSTANCE.grpcInterceptorProvider();
private BlobWriteSessionConfig blobWriteSessionConfig =
GrpcStorageDefaults.INSTANCE.getDefaultStorageWriterConfig();
private OpenTelemetry openTelemetry = GrpcStorageDefaults.INSTANCE.getDefaultOpenTelemetry();

private boolean grpcMetricsManuallyEnabled = false;

Expand All @@ -437,6 +456,7 @@ public static final class Builder extends StorageOptions.Builder {
this.enableGrpcClientMetrics = gso.enableGrpcClientMetrics;
this.grpcInterceptorProvider = gso.grpcInterceptorProvider;
this.blobWriteSessionConfig = gso.blobWriteSessionConfig;
this.openTelemetry = gso.openTelemetry;
}

/**
Expand Down Expand Up @@ -619,6 +639,19 @@ public GrpcStorageOptions.Builder setBlobWriteSessionConfig(
return this;
}

/**
* Enable OpenTelemetry Tracing and provide an instance for the client to use.
*
* @param openTelemetry User defined instance of OpenTelemetry to be used by the library
* @since 2.47.0 This new api is in preview and is subject to breaking changes.
*/
@BetaApi
public GrpcStorageOptions.Builder setOpenTelemetry(OpenTelemetry openTelemetry) {
requireNonNull(openTelemetry, "openTelemetry must be non null");
this.openTelemetry = openTelemetry;
return this;
}

/** @since 2.14.0 */
@Override
public GrpcStorageOptions build() {
Expand Down Expand Up @@ -695,6 +728,12 @@ public GrpcInterceptorProvider grpcInterceptorProvider() {
public BlobWriteSessionConfig getDefaultStorageWriterConfig() {
return BlobWriteSessionConfigs.getDefault();
}

/** @since 2.47.0 This new api is in preview and is subject to breaking changes. */
@BetaApi
public OpenTelemetry getDefaultOpenTelemetry() {
return OpenTelemetry.noop();
}
}

/**
Expand Down Expand Up @@ -751,22 +790,27 @@ public Storage create(StorageOptions options) {
new InternalZeroCopyGrpcStorageStub(
stubSettings, clientContext, grpcStorageCallableFactory);
StorageClient client = new InternalStorageClient(stub);
return new GrpcStorageImpl(
grpcStorageOptions,
client,
stub.getObjectMediaResponseMarshaller,
grpcStorageOptions.blobWriteSessionConfig.createFactory(Clock.systemUTC()),
defaultOpts);
GrpcStorageImpl grpcStorage =
new GrpcStorageImpl(
grpcStorageOptions,
client,
stub.getObjectMediaResponseMarshaller,
grpcStorageOptions.blobWriteSessionConfig.createFactory(Clock.systemUTC()),
defaultOpts);
return OtelStorageDecorator.decorate(
grpcStorage, options.getOpenTelemetry(), Transport.GRPC);
} else {
StorageClient client = StorageClient.create(storageSettings);
return new GrpcStorageImpl(
grpcStorageOptions,
client,
ResponseContentLifecycleManager.noop(),
grpcStorageOptions.blobWriteSessionConfig.createFactory(Clock.systemUTC()),
defaultOpts);
GrpcStorageImpl grpcStorage =
new GrpcStorageImpl(
grpcStorageOptions,
client,
ResponseContentLifecycleManager.noop(),
grpcStorageOptions.blobWriteSessionConfig.createFactory(Clock.systemUTC()),
defaultOpts);
return OtelStorageDecorator.decorate(
grpcStorage, options.getOpenTelemetry(), Transport.GRPC);
}

} catch (IOException e) {
throw new IllegalStateException(
"Unable to instantiate gRPC com.google.cloud.storage.Storage client.", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.google.cloud.storage.spi.v1.StorageRpc;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableSet;
import io.opentelemetry.api.OpenTelemetry;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
Expand All @@ -59,6 +60,8 @@ public class HttpStorageOptions extends StorageOptions {
private transient RetryDependenciesAdapter retryDepsAdapter;
private final BlobWriteSessionConfig blobWriteSessionConfig;

private transient OpenTelemetry openTelemetry;

private HttpStorageOptions(Builder builder, StorageDefaults serviceDefaults) {
super(builder, serviceDefaults);
this.retryAlgorithmManager =
Expand All @@ -67,6 +70,7 @@ private HttpStorageOptions(Builder builder, StorageDefaults serviceDefaults) {
builder.storageRetryStrategy, defaults().getStorageRetryStrategy()));
retryDepsAdapter = new RetryDependenciesAdapter();
blobWriteSessionConfig = builder.blobWriteSessionConfig;
openTelemetry = builder.openTelemetry;
}

@Override
Expand All @@ -84,14 +88,22 @@ StorageRpc getStorageRpcV1() {
return (StorageRpc) getRpc();
}

/** @since 2.47.0 This new api is in preview and is subject to breaking changes. */
@BetaApi
@Override
public OpenTelemetry getOpenTelemetry() {
return openTelemetry;
}

@Override
public HttpStorageOptions.Builder toBuilder() {
return new HttpStorageOptions.Builder(this);
}

@Override
public int hashCode() {
return Objects.hash(retryAlgorithmManager, blobWriteSessionConfig, baseHashCode());
return Objects.hash(
retryAlgorithmManager, blobWriteSessionConfig, openTelemetry, baseHashCode());
}

@Override
Expand All @@ -105,12 +117,14 @@ public boolean equals(Object o) {
HttpStorageOptions that = (HttpStorageOptions) o;
return Objects.equals(retryAlgorithmManager, that.retryAlgorithmManager)
&& Objects.equals(blobWriteSessionConfig, that.blobWriteSessionConfig)
&& Objects.equals(openTelemetry, that.openTelemetry)
&& this.baseEquals(that);
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
this.retryDepsAdapter = new RetryDependenciesAdapter();
this.openTelemetry = HttpStorageOptions.getDefaultInstance().getOpenTelemetry();
}

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

Builder() {}

Expand All @@ -143,6 +158,7 @@ public static class Builder extends StorageOptions.Builder {
HttpStorageOptions hso = (HttpStorageOptions) options;
this.storageRetryStrategy = hso.retryAlgorithmManager.retryStrategy;
this.blobWriteSessionConfig = hso.blobWriteSessionConfig;
this.openTelemetry = hso.getOpenTelemetry();
}

@Override
Expand Down Expand Up @@ -268,6 +284,19 @@ public HttpStorageOptions build() {
}
return options;
}

/**
* Enable OpenTelemetry Tracing and provide an instance for the client to use.
*
* @param openTelemetry User defined instance of OpenTelemetry to be used by the library
* @since 2.47.0 This new api is in preview and is subject to breaking changes.
*/
@BetaApi
public HttpStorageOptions.Builder setOpenTelemetry(OpenTelemetry openTelemetry) {
requireNonNull(openTelemetry, "openTelemetry must be non null");
this.openTelemetry = openTelemetry;
return this;
}
}

public static final class HttpStorageDefaults extends StorageDefaults {
Expand Down Expand Up @@ -301,6 +330,12 @@ public StorageRetryStrategy getStorageRetryStrategy() {
public BlobWriteSessionConfig getDefaultStorageWriterConfig() {
return BlobWriteSessionConfigs.getDefault();
}

/** @since 2.47.0 This new api is in preview and is subject to breaking changes. */
@BetaApi
public OpenTelemetry getDefaultOpenTelemetry() {
return OpenTelemetry.noop();
}
}

/**
Expand Down Expand Up @@ -341,8 +376,12 @@ public Storage create(StorageOptions options) {
HttpStorageOptions httpStorageOptions = (HttpStorageOptions) options;
Clock clock = Clock.systemUTC();
try {
return new StorageImpl(
httpStorageOptions, httpStorageOptions.blobWriteSessionConfig.createFactory(clock));
StorageImpl storage =
new StorageImpl(
httpStorageOptions,
httpStorageOptions.blobWriteSessionConfig.createFactory(clock));
return OtelStorageDecorator.decorate(
storage, httpStorageOptions.getOpenTelemetry(), Transport.HTTP);
} catch (IOException e) {
throw new IllegalStateException(
"Unable to instantiate HTTP com.google.cloud.storage.Storage client.", e);
Expand Down
Loading

0 comments on commit dd889ea

Please sign in to comment.