Skip to content

Commit 1eac825

Browse files
committed
fix(firestore): support opentelemetry-instrumentation-grpc 2.25.0+
1 parent a88c83f commit 1eac825

3 files changed

Lines changed: 89 additions & 1 deletion

File tree

java-firestore/google-cloud-firestore/pom.xml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,36 @@
363363
</dependency>
364364
</dependencies>
365365
</profile>
366+
<!--
367+
Matrix-test profiles for opentelemetry-instrumentation-grpc-1.6.
368+
GrpcTelemetry.newClientInterceptor() was renamed createClientInterceptor();
369+
these profiles run tests under both APIs to verify the reflection-based fallback.
370+
See https://github.com/googleapis/google-cloud-java/issues/13095
371+
-->
372+
<profile>
373+
<id>otel-grpc-old</id>
374+
<dependencyManagement>
375+
<dependencies>
376+
<dependency>
377+
<groupId>io.opentelemetry.instrumentation</groupId>
378+
<artifactId>opentelemetry-grpc-1.6</artifactId>
379+
<version>2.1.0-alpha</version>
380+
</dependency>
381+
</dependencies>
382+
</dependencyManagement>
383+
</profile>
384+
<profile>
385+
<id>otel-grpc-new</id>
386+
<dependencyManagement>
387+
<dependencies>
388+
<dependency>
389+
<groupId>io.opentelemetry.instrumentation</groupId>
390+
<artifactId>opentelemetry-grpc-1.6</artifactId>
391+
<version>2.25.0-alpha</version>
392+
</dependency>
393+
</dependencies>
394+
</dependencyManagement>
395+
</profile>
366396
<profile>
367397
<!-- JDK17 set up for tests in src/test-jdk17 -->
368398
<id>java17-test</id>

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

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.google.api.core.InternalApi;
2424
import com.google.cloud.firestore.FirestoreOptions;
2525
import com.google.common.base.Throwables;
26+
import io.grpc.ClientInterceptor;
2627
import io.grpc.ManagedChannelBuilder;
2728
import io.opentelemetry.api.GlobalOpenTelemetry;
2829
import io.opentelemetry.api.OpenTelemetry;
@@ -34,6 +35,8 @@
3435
import io.opentelemetry.api.trace.Tracer;
3536
import io.opentelemetry.api.trace.TracerProvider;
3637
import io.opentelemetry.instrumentation.grpc.v1_6.GrpcTelemetry;
38+
import java.lang.reflect.InvocationTargetException;
39+
import java.lang.reflect.Method;
3740
import java.util.Map;
3841
import javax.annotation.Nonnull;
3942
import javax.annotation.Nullable;
@@ -73,13 +76,44 @@ public OpenTelemetry getOpenTelemetry() {
7376
return openTelemetry;
7477
}
7578

79+
// See https://github.com/googleapis/google-cloud-java/issues/13095
80+
private static final Method GRPC_CLIENT_INTERCEPTOR_METHOD = resolveGrpcClientInterceptorMethod();
81+
82+
private static Method resolveGrpcClientInterceptorMethod() {
83+
try {
84+
return GrpcTelemetry.class.getMethod("createClientInterceptor");
85+
} catch (NoSuchMethodException ignored) {
86+
// Fall back to the pre-2.25.0 method name.
87+
}
88+
try {
89+
return GrpcTelemetry.class.getMethod("newClientInterceptor");
90+
} catch (NoSuchMethodException e) {
91+
throw new IllegalStateException(
92+
"Neither GrpcTelemetry#createClientInterceptor nor GrpcTelemetry#newClientInterceptor"
93+
+ " is available on the classpath. Incompatible"
94+
+ " opentelemetry-instrumentation-grpc-1.6 version.",
95+
e);
96+
}
97+
}
98+
99+
private static ClientInterceptor newGrpcClientInterceptor(GrpcTelemetry grpcTelemetry) {
100+
try {
101+
return (ClientInterceptor) GRPC_CLIENT_INTERCEPTOR_METHOD.invoke(grpcTelemetry);
102+
} catch (IllegalAccessException e) {
103+
throw new IllegalStateException(e);
104+
} catch (InvocationTargetException e) {
105+
Throwables.throwIfUnchecked(e.getCause());
106+
throw new RuntimeException(e.getCause());
107+
}
108+
}
109+
76110
// The gRPC channel configurator that intercepts gRPC calls for tracing purposes.
77111
public class OpenTelemetryGrpcChannelConfigurator
78112
implements ApiFunction<ManagedChannelBuilder, ManagedChannelBuilder> {
79113
@Override
80114
public ManagedChannelBuilder apply(ManagedChannelBuilder managedChannelBuilder) {
81115
GrpcTelemetry grpcTelemetry = GrpcTelemetry.create(getOpenTelemetry());
82-
return managedChannelBuilder.intercept(grpcTelemetry.newClientInterceptor());
116+
return managedChannelBuilder.intercept(newGrpcClientInterceptor(grpcTelemetry));
83117
}
84118
}
85119

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717

1818
import static com.google.common.truth.Truth.assertThat;
1919

20+
import com.google.api.core.ApiFunction;
2021
import com.google.cloud.firestore.FirestoreOpenTelemetryOptions;
2122
import com.google.cloud.firestore.FirestoreOptions;
23+
import io.grpc.ManagedChannelBuilder;
2224
import io.opentelemetry.api.GlobalOpenTelemetry;
2325
import io.opentelemetry.api.trace.TracerProvider;
2426
import io.opentelemetry.sdk.OpenTelemetrySdk;
@@ -111,6 +113,28 @@ public void openTelemetryInstanceRegistersGrpcChannelConfigurator() {
111113
assertThat(traceUtil.getChannelConfigurator()).isNotNull();
112114
}
113115

116+
// Exercises the reflection fallback that resolves either
117+
// GrpcTelemetry#createClientInterceptor (>= 2.25.0) or #newClientInterceptor (< 2.25.0).
118+
// See https://github.com/googleapis/google-cloud-java/issues/13095
119+
@Test
120+
public void channelConfiguratorAppliesInterceptorAcrossOtelGrpcVersions() {
121+
OpenTelemetrySdk myOpenTelemetrySdk = OpenTelemetrySdk.builder().build();
122+
FirestoreOptions firestoreOptions =
123+
getBaseOptions()
124+
.setOpenTelemetryOptions(
125+
FirestoreOpenTelemetryOptions.newBuilder()
126+
.setOpenTelemetry(myOpenTelemetrySdk)
127+
.build())
128+
.build();
129+
EnabledTraceUtil traceUtil = new EnabledTraceUtil(firestoreOptions);
130+
ApiFunction<ManagedChannelBuilder, ManagedChannelBuilder> configurator =
131+
traceUtil.getChannelConfigurator();
132+
assertThat(configurator).isNotNull();
133+
134+
ManagedChannelBuilder<?> builder = ManagedChannelBuilder.forAddress("localhost", 9999);
135+
assertThat(configurator.apply(builder)).isNotNull();
136+
}
137+
114138
@Test
115139
public void usesEnabledContext() {
116140
assertThat(defaultEnabledTraceUtil().currentContext() instanceof EnabledTraceUtil.Context)

0 commit comments

Comments
 (0)