Skip to content

Commit 829533a

Browse files
committed
"feat: enable grpc configurator for client-side tracing"
1 parent 4fb9929 commit 829533a

File tree

4 files changed

+116
-29
lines changed

4 files changed

+116
-29
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: 45 additions & 19 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;
@@ -110,9 +112,11 @@ public static class Builder extends ServiceOptions.Builder<Datastore, DatastoreO
110112
private String host;
111113
private TransportOptions transportOptions;
112114

113-
@Nullable private DatastoreOpenTelemetryOptions openTelemetryOptions = null;
115+
@Nullable
116+
private DatastoreOpenTelemetryOptions openTelemetryOptions = null;
114117

115-
private Builder() {}
118+
private Builder() {
119+
}
116120

117121
private Builder(DatastoreOptions options) {
118122
super(options);
@@ -155,8 +159,8 @@ public Builder setHost(String host) {
155159
*
156160
* <p>This functionality is experimental and subject to change.
157161
*
158-
* @param channelProvider A InstantiatingGrpcChannelProvider object that defines the transport
159-
* provider for this client.
162+
* @param channelProvider A InstantiatingGrpcChannelProvider object that defines the
163+
* transport provider for this client.
160164
*/
161165
@BetaApi
162166
public Builder setChannelProvider(TransportChannelProvider channelProvider) {
@@ -172,7 +176,9 @@ public DatastoreOptions build() {
172176
return new DatastoreOptions(this);
173177
}
174178

175-
/** Sets the default namespace to be used by the datastore service. */
179+
/**
180+
* Sets the default namespace to be used by the datastore service.
181+
*/
176182
public Builder setNamespace(String namespace) {
177183
this.namespace = validateNamespace(namespace);
178184
return this;
@@ -222,20 +228,35 @@ private DatastoreOptions(Builder builder) {
222228
throw new IllegalArgumentException(
223229
"Only gRPC transport allows setting of channel provider or credentials provider");
224230
} 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(
231+
if (builder.channelProvider == null) {
232+
/*
233+
The default gRPC connection pool is configured with a minimum of 1 channel.
234+
The maximum channel count automatically defaults to 200 (Defined in gax-grpc).
235+
*/
236+
ChannelPoolSettings datastoreChannelPoolSettings = ChannelPoolSettings.builder()
237+
.setInitialChannelCount(INIT_CHANNEL_COUNT)
238+
.setMinChannelCount(MIN_CHANNEL_COUNT)
239+
.build();
240+
241+
ApiFunction<ManagedChannelBuilder, ManagedChannelBuilder> channelConfigurator =
242+
this.traceUtil.getChannelConfigurator();
243+
if (channelConfigurator == null) {
244+
this.channelProvider =
245+
GrpcTransportOptions.setUpChannelProvider(
246+
DatastoreSettings.defaultGrpcTransportProviderBuilder()
247+
.setChannelPoolSettings(datastoreChannelPoolSettings), this);
248+
} else {
249+
// Intercept the grpc channel calls to add telemetry info.
250+
this.channelProvider =
251+
GrpcTransportOptions.setUpChannelProvider(
231252
DatastoreSettings.defaultGrpcTransportProviderBuilder()
232-
.setChannelPoolSettings(
233-
ChannelPoolSettings.builder()
234-
.setInitialChannelCount(INIT_CHANNEL_COUNT)
235-
.setMinChannelCount(MIN_CHANNEL_COUNT)
236-
.setMaxChannelCount(MAX_CHANNEL_COUNT)
237-
.build()),
253+
.setChannelPoolSettings(datastoreChannelPoolSettings)
254+
.setChannelConfigurator(channelConfigurator),
238255
this);
256+
}
257+
} else {
258+
this.channelProvider = builder.channelProvider;
259+
}
239260
}
240261
}
241262

@@ -256,6 +277,7 @@ protected String getDefaultProject() {
256277
}
257278

258279
private static class DatastoreDefaults implements ServiceDefaults<Datastore, DatastoreOptions> {
280+
259281
private final TransportOptions TRANSPORT_OPTIONS = getDefaultTransportOptionsBuilder().build();
260282

261283
@Override
@@ -286,7 +308,9 @@ public static GrpcTransportOptions getDefaultGrpcTransportOptions() {
286308
return GrpcTransportOptions.newBuilder().build();
287309
}
288310

289-
/** Returns the default namespace to be used by the datastore service. */
311+
/**
312+
* Returns the default namespace to be used by the datastore service.
313+
*/
290314
public String getNamespace() {
291315
return namespace;
292316
}
@@ -295,7 +319,9 @@ public String getDatabaseId() {
295319
return this.databaseId;
296320
}
297321

298-
/** Returns a default {@code DatastoreOptions} instance. */
322+
/**
323+
* Returns a default {@code DatastoreOptions} instance.
324+
*/
299325
public static DatastoreOptions getDefaultInstance() {
300326
return newBuilder().build();
301327
}

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

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,15 @@
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;
4143

4244
/**
43-
* Tracing utility implementation, used to stub out tracing instrumentation when tracing is enabled.
45+
* Tracing utility implementation, used to stub out tracing instrumentation when tracing is
46+
* enabled.
4447
*/
4548
@InternalApi
4649
public class EnabledTraceUtil implements TraceUtil {
@@ -66,14 +69,30 @@ public OpenTelemetry getOpenTelemetry() {
6669
return openTelemetry;
6770
}
6871

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

7694
static class Span implements TraceUtil.Span {
95+
7796
private final io.opentelemetry.api.trace.Span span;
7897
private final String spanName;
7998

@@ -87,13 +106,17 @@ public io.opentelemetry.api.trace.Span getSpan() {
87106
return this.span;
88107
}
89108

90-
/** Ends this span. */
109+
/**
110+
* Ends this span.
111+
*/
91112
@Override
92113
public void end() {
93114
span.end();
94115
}
95116

96-
/** Ends this span in an error. */
117+
/**
118+
* Ends this span in an error.
119+
*/
97120
@Override
98121
public void end(Throwable error) {
99122
span.setStatus(StatusCode.ERROR, error.getMessage());
@@ -137,7 +160,9 @@ public void onSuccess(T result) {
137160
});
138161
}
139162

140-
/** Adds the given event to this span. */
163+
/**
164+
* Adds the given event to this span.
165+
*/
141166
@Override
142167
public TraceUtil.Span addEvent(String name) {
143168
span.addEvent(name);
@@ -198,6 +223,7 @@ public Scope makeCurrent() {
198223
}
199224

200225
static class Scope implements TraceUtil.Scope {
226+
201227
private final io.opentelemetry.context.Scope scope;
202228

203229
Scope(io.opentelemetry.context.Scope scope) {
@@ -211,6 +237,7 @@ public void close() {
211237
}
212238

213239
static class Context implements TraceUtil.Context {
240+
214241
private final io.opentelemetry.context.Context context;
215242

216243
Context(io.opentelemetry.context.Context context) {
@@ -225,7 +252,9 @@ public Scope makeCurrent() {
225252
}
226253
}
227254

228-
/** Applies the current Datastore instance settings as attributes to the current Span */
255+
/**
256+
* Applies the current Datastore instance settings as attributes to the current Span
257+
*/
229258
@Override
230259
public SpanBuilder addSettingsAttributesToCurrentSpan(SpanBuilder spanBuilder) {
231260
spanBuilder =

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

Lines changed: 31 additions & 3 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)
@@ -92,7 +120,7 @@ public void usesEnabledSpan() {
92120
assertThat(traceUtil.getCurrentSpan() instanceof EnabledTraceUtil.Span).isTrue();
93121
assertThat(traceUtil.startSpan("foo") != null).isTrue();
94122
assertThat(
95-
traceUtil.startSpan("foo", traceUtil.getCurrentSpan()) instanceof EnabledTraceUtil.Span)
123+
traceUtil.startSpan("foo", traceUtil.getCurrentSpan()) instanceof EnabledTraceUtil.Span)
96124
.isTrue();
97125
}
98126

0 commit comments

Comments
 (0)