Skip to content

Commit 97004c8

Browse files
feat: enable grpc configurator for client-side tracing (#1886)
* "feat: enable grpc configurator for client-side tracing" * chore: generate libraries at Tue Jun 17 22:31:00 UTC 2025 * fix unit tests for max channel number * Remove max channel count configurations to fall back to gax-grpc max channel count * fix clirr difference error --------- Co-authored-by: cloud-java-bot <[email protected]>
1 parent a9d6155 commit 97004c8

File tree

6 files changed

+91
-19
lines changed

6 files changed

+91
-19
lines changed

google-cloud-datastore/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@
147147
<artifactId>opentelemetry-context</artifactId>
148148
<version>${opentelemetry.version}</version>
149149
</dependency>
150+
<dependency>
151+
<groupId>io.opentelemetry.instrumentation</groupId>
152+
<artifactId>opentelemetry-grpc-1.6</artifactId>
153+
</dependency>
150154
<!-- END OpenTelemetry -->
151155

152156
<!-- Test dependencies -->

google-cloud-datastore/src/main/java/com/google/cloud/datastore/DatastoreOptions.java

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static com.google.cloud.datastore.Validator.validateNamespace;
2020

21+
import com.google.api.core.ApiFunction;
2122
import com.google.api.core.BetaApi;
2223
import com.google.api.gax.grpc.ChannelPoolSettings;
2324
import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
@@ -35,6 +36,7 @@
3536
import com.google.cloud.http.HttpTransportOptions;
3637
import com.google.common.base.MoreObjects;
3738
import com.google.common.collect.ImmutableSet;
39+
import io.grpc.ManagedChannelBuilder;
3840
import java.io.IOException;
3941
import java.lang.reflect.Method;
4042
import java.util.Objects;
@@ -222,20 +224,37 @@ private DatastoreOptions(Builder builder) {
222224
throw new IllegalArgumentException(
223225
"Only gRPC transport allows setting of channel provider or credentials provider");
224226
} else if (getTransportOptions() instanceof GrpcTransportOptions) {
225-
// For grpc transport options, configure default gRPC Connection pool with minChannelCount = 1
226-
// and maxChannelCount = 4
227-
this.channelProvider =
228-
builder.channelProvider != null
229-
? builder.channelProvider
230-
: GrpcTransportOptions.setUpChannelProvider(
227+
if (builder.channelProvider == null) {
228+
/*
229+
The default gRPC connection pool is configured with a minimum of 1 channel.
230+
The maximum channel count automatically defaults to 200 (Defined in gax-grpc).
231+
*/
232+
ChannelPoolSettings datastoreChannelPoolSettings =
233+
ChannelPoolSettings.builder()
234+
.setInitialChannelCount(INIT_CHANNEL_COUNT)
235+
.setMinChannelCount(MIN_CHANNEL_COUNT)
236+
.build();
237+
238+
ApiFunction<ManagedChannelBuilder, ManagedChannelBuilder> channelConfigurator =
239+
this.traceUtil.getChannelConfigurator();
240+
if (channelConfigurator == null) {
241+
this.channelProvider =
242+
GrpcTransportOptions.setUpChannelProvider(
231243
DatastoreSettings.defaultGrpcTransportProviderBuilder()
232-
.setChannelPoolSettings(
233-
ChannelPoolSettings.builder()
234-
.setInitialChannelCount(INIT_CHANNEL_COUNT)
235-
.setMinChannelCount(MIN_CHANNEL_COUNT)
236-
.setMaxChannelCount(MAX_CHANNEL_COUNT)
237-
.build()),
244+
.setChannelPoolSettings(datastoreChannelPoolSettings),
238245
this);
246+
} else {
247+
// Intercept the grpc channel calls to add telemetry info.
248+
this.channelProvider =
249+
GrpcTransportOptions.setUpChannelProvider(
250+
DatastoreSettings.defaultGrpcTransportProviderBuilder()
251+
.setChannelPoolSettings(datastoreChannelPoolSettings)
252+
.setChannelConfigurator(channelConfigurator),
253+
this);
254+
}
255+
} else {
256+
this.channelProvider = builder.channelProvider;
257+
}
239258
}
240259
}
241260

@@ -256,6 +275,7 @@ protected String getDefaultProject() {
256275
}
257276

258277
private static class DatastoreDefaults implements ServiceDefaults<Datastore, DatastoreOptions> {
278+
259279
private final TransportOptions TRANSPORT_OPTIONS = getDefaultTransportOptionsBuilder().build();
260280

261281
@Override

google-cloud-datastore/src/main/java/com/google/cloud/datastore/spi/v1/GrpcDatastoreRpc.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public GrpcDatastoreRpc(DatastoreOptions datastoreOptions) throws IOException {
7575
? getClientContextForEmulator(datastoreOptions)
7676
: getClientContext(datastoreOptions);
7777

78-
/* For grpc transport options, configure default gRPC Connection pool with minChannelCount = 1 and maxChannelCount = 4 */
78+
/* For grpc transport options, configure default gRPC Connection pool with minChannelCount = 1 */
7979
DatastoreStubSettings datastoreStubSettings =
8080
DatastoreStubSettings.newBuilder(clientContext)
8181
.applyToAllUnaryMethods(retrySettingSetter(datastoreOptions))
@@ -85,7 +85,6 @@ public GrpcDatastoreRpc(DatastoreOptions datastoreOptions) throws IOException {
8585
ChannelPoolSettings.builder()
8686
.setInitialChannelCount(DatastoreOptions.INIT_CHANNEL_COUNT)
8787
.setMinChannelCount(DatastoreOptions.MIN_CHANNEL_COUNT)
88-
.setMaxChannelCount(DatastoreOptions.MAX_CHANNEL_COUNT)
8988
.build())
9089
.build())
9190
.build();

google-cloud-datastore/src/main/java/com/google/cloud/datastore/telemetry/EnabledTraceUtil.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
import io.opentelemetry.api.trace.SpanKind;
3636
import io.opentelemetry.api.trace.StatusCode;
3737
import io.opentelemetry.api.trace.Tracer;
38+
import io.opentelemetry.api.trace.TracerProvider;
39+
import io.opentelemetry.instrumentation.grpc.v1_6.GrpcTelemetry;
3840
import java.util.Map;
3941
import javax.annotation.Nonnull;
4042
import javax.annotation.Nullable;
@@ -66,14 +68,30 @@ public OpenTelemetry getOpenTelemetry() {
6668
return openTelemetry;
6769
}
6870

71+
// The gRPC channel configurator that intercepts gRPC calls for tracing purposes.
72+
public class OpenTelemetryGrpcChannelConfigurator
73+
implements ApiFunction<ManagedChannelBuilder, ManagedChannelBuilder> {
74+
75+
@Override
76+
public ManagedChannelBuilder apply(ManagedChannelBuilder managedChannelBuilder) {
77+
GrpcTelemetry grpcTelemetry = GrpcTelemetry.create(getOpenTelemetry());
78+
return managedChannelBuilder.intercept(grpcTelemetry.newClientInterceptor());
79+
}
80+
}
81+
6982
@Override
7083
@Nullable
7184
public ApiFunction<ManagedChannelBuilder, ManagedChannelBuilder> getChannelConfigurator() {
72-
// TODO(jimit) Update this to return a gRPC Channel Configurator after gRPC upgrade.
73-
return null;
85+
// Note: using `==` rather than `.equals` since OpenTelemetry has only 1 static instance of
86+
// `TracerProvider.noop`.
87+
if (openTelemetry.getTracerProvider() == TracerProvider.noop()) {
88+
return null;
89+
}
90+
return new OpenTelemetryGrpcChannelConfigurator();
7491
}
7592

7693
static class Span implements TraceUtil.Span {
94+
7795
private final io.opentelemetry.api.trace.Span span;
7896
private final String spanName;
7997

@@ -198,6 +216,7 @@ public Scope makeCurrent() {
198216
}
199217

200218
static class Scope implements TraceUtil.Scope {
219+
201220
private final io.opentelemetry.context.Scope scope;
202221

203222
Scope(io.opentelemetry.context.Scope scope) {
@@ -211,6 +230,7 @@ public void close() {
211230
}
212231

213232
static class Context implements TraceUtil.Context {
233+
214234
private final io.opentelemetry.context.Context context;
215235

216236
Context(io.opentelemetry.context.Context context) {

google-cloud-datastore/src/test/java/com/google/cloud/datastore/DatastoreOptionsTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public class DatastoreOptionsTest {
4141
private static final String PROJECT_ID = "project-id";
4242
private static final String DATABASE_ID = "database-id";
4343
private static final int PORT = 8080;
44+
private static final int DEFAULT_MAX_CHANNEL_COUNT = 200;
4445
private DatastoreRpcFactory datastoreRpcFactory;
4546
private DatastoreRpc datastoreRpc;
4647
private DatastoreOptions.Builder options;
@@ -119,7 +120,7 @@ public void testGrpcDefaultChannelConfigurations() {
119120
.getChannelPoolSettings();
120121
assertEquals(channelPoolSettings.getInitialChannelCount(), DatastoreOptions.INIT_CHANNEL_COUNT);
121122
assertEquals(channelPoolSettings.getMinChannelCount(), DatastoreOptions.MIN_CHANNEL_COUNT);
122-
assertEquals(channelPoolSettings.getMaxChannelCount(), DatastoreOptions.MAX_CHANNEL_COUNT);
123+
assertEquals(channelPoolSettings.getMaxChannelCount(), DEFAULT_MAX_CHANNEL_COUNT);
123124
}
124125

125126
@Test

google-cloud-datastore/src/test/java/com/google/cloud/datastore/telemetry/EnabledTraceUtilTest.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,12 @@ public void usesOpenTelemetryFromOptions() {
6666
@Test
6767
public void usesGlobalOpenTelemetryIfOpenTelemetryInstanceNotProvided() {
6868
OpenTelemetrySdk ignored = OpenTelemetrySdk.builder().buildAndRegisterGlobal();
69-
DatastoreOptions firestoreOptions =
69+
DatastoreOptions datastoreOptions =
7070
getBaseOptions()
7171
.setOpenTelemetryOptions(
7272
DatastoreOpenTelemetryOptions.newBuilder().setTracingEnabled(true).build())
7373
.build();
74-
EnabledTraceUtil traceUtil = new EnabledTraceUtil(firestoreOptions);
74+
EnabledTraceUtil traceUtil = new EnabledTraceUtil(datastoreOptions);
7575
assertThat(traceUtil.getOpenTelemetry()).isEqualTo(GlobalOpenTelemetry.get());
7676
}
7777

@@ -80,6 +80,34 @@ public void enabledTraceUtilProvidesChannelConfigurator() {
8080
assertThat(newEnabledTraceUtil().getChannelConfigurator()).isNull();
8181
}
8282

83+
@Test
84+
public void openTelemetryInstanceRegistersGrpcChannelConfigurator() {
85+
OpenTelemetrySdk myOpenTelemetrySdk = OpenTelemetrySdk.builder().build();
86+
DatastoreOptions firestoreOptions =
87+
getBaseOptions()
88+
.setOpenTelemetryOptions(
89+
DatastoreOpenTelemetryOptions.newBuilder()
90+
.setTracingEnabled(true)
91+
.setOpenTelemetry(myOpenTelemetrySdk)
92+
.build())
93+
.build();
94+
EnabledTraceUtil traceUtil = new EnabledTraceUtil(firestoreOptions);
95+
assertThat(traceUtil.getChannelConfigurator()).isNotNull();
96+
}
97+
98+
@Test
99+
public void globalOpenTelemetryRegistersGrpcChannelConfigurator() {
100+
101+
OpenTelemetrySdk.builder().buildAndRegisterGlobal();
102+
DatastoreOptions datastoreOptions =
103+
getBaseOptions()
104+
.setOpenTelemetryOptions(
105+
DatastoreOpenTelemetryOptions.newBuilder().setTracingEnabled(true).build())
106+
.build();
107+
EnabledTraceUtil traceUtil = new EnabledTraceUtil(datastoreOptions);
108+
assertThat(traceUtil.getChannelConfigurator()).isNotNull();
109+
}
110+
83111
@Test
84112
public void usesEnabledContext() {
85113
assertThat(newEnabledTraceUtil().getCurrentContext() instanceof EnabledTraceUtil.Context)

0 commit comments

Comments
 (0)