diff --git a/java-firestore/google-cloud-firestore/pom.xml b/java-firestore/google-cloud-firestore/pom.xml
index a96df01e18a3..5c03162d83c0 100644
--- a/java-firestore/google-cloud-firestore/pom.xml
+++ b/java-firestore/google-cloud-firestore/pom.xml
@@ -363,6 +363,36 @@
+
+
+ otel-grpc-old
+
+
+
+ io.opentelemetry.instrumentation
+ opentelemetry-grpc-1.6
+ 2.1.0-alpha
+
+
+
+
+
+ otel-grpc-new
+
+
+
+ io.opentelemetry.instrumentation
+ opentelemetry-grpc-1.6
+ 2.25.0-alpha
+
+
+
+
java17-test
diff --git a/java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/telemetry/EnabledTraceUtil.java b/java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/telemetry/EnabledTraceUtil.java
index 863012b4e5cc..0919c65f9bb2 100644
--- a/java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/telemetry/EnabledTraceUtil.java
+++ b/java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/telemetry/EnabledTraceUtil.java
@@ -23,6 +23,7 @@
import com.google.api.core.InternalApi;
import com.google.cloud.firestore.FirestoreOptions;
import com.google.common.base.Throwables;
+import io.grpc.ClientInterceptor;
import io.grpc.ManagedChannelBuilder;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry;
@@ -34,6 +35,8 @@
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.TracerProvider;
import io.opentelemetry.instrumentation.grpc.v1_6.GrpcTelemetry;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -73,13 +76,44 @@ public OpenTelemetry getOpenTelemetry() {
return openTelemetry;
}
+ // See https://github.com/googleapis/google-cloud-java/issues/13095
+ private static final Method GRPC_CLIENT_INTERCEPTOR_METHOD = resolveGrpcClientInterceptorMethod();
+
+ private static Method resolveGrpcClientInterceptorMethod() {
+ try {
+ return GrpcTelemetry.class.getMethod("createClientInterceptor");
+ } catch (NoSuchMethodException ignored) {
+ // Fall back to the pre-2.25.0 method name.
+ }
+ try {
+ return GrpcTelemetry.class.getMethod("newClientInterceptor");
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException(
+ "Neither GrpcTelemetry#createClientInterceptor nor GrpcTelemetry#newClientInterceptor"
+ + " is available on the classpath. Incompatible"
+ + " opentelemetry-instrumentation-grpc-1.6 version.",
+ e);
+ }
+ }
+
+ private static ClientInterceptor newGrpcClientInterceptor(GrpcTelemetry grpcTelemetry) {
+ try {
+ return (ClientInterceptor) GRPC_CLIENT_INTERCEPTOR_METHOD.invoke(grpcTelemetry);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ } catch (InvocationTargetException e) {
+ Throwables.throwIfUnchecked(e.getCause());
+ throw new RuntimeException(e.getCause());
+ }
+ }
+
// The gRPC channel configurator that intercepts gRPC calls for tracing purposes.
public class OpenTelemetryGrpcChannelConfigurator
implements ApiFunction {
@Override
public ManagedChannelBuilder apply(ManagedChannelBuilder managedChannelBuilder) {
GrpcTelemetry grpcTelemetry = GrpcTelemetry.create(getOpenTelemetry());
- return managedChannelBuilder.intercept(grpcTelemetry.newClientInterceptor());
+ return managedChannelBuilder.intercept(newGrpcClientInterceptor(grpcTelemetry));
}
}
diff --git a/java-firestore/google-cloud-firestore/src/test/java/com/google/cloud/firestore/telemetry/EnabledTraceUtilTest.java b/java-firestore/google-cloud-firestore/src/test/java/com/google/cloud/firestore/telemetry/EnabledTraceUtilTest.java
index d3fb7e216787..61f347228f6c 100644
--- a/java-firestore/google-cloud-firestore/src/test/java/com/google/cloud/firestore/telemetry/EnabledTraceUtilTest.java
+++ b/java-firestore/google-cloud-firestore/src/test/java/com/google/cloud/firestore/telemetry/EnabledTraceUtilTest.java
@@ -17,8 +17,10 @@
import static com.google.common.truth.Truth.assertThat;
+import com.google.api.core.ApiFunction;
import com.google.cloud.firestore.FirestoreOpenTelemetryOptions;
import com.google.cloud.firestore.FirestoreOptions;
+import io.grpc.ManagedChannelBuilder;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.TracerProvider;
import io.opentelemetry.sdk.OpenTelemetrySdk;
@@ -111,6 +113,28 @@ public void openTelemetryInstanceRegistersGrpcChannelConfigurator() {
assertThat(traceUtil.getChannelConfigurator()).isNotNull();
}
+ // Exercises the reflection fallback that resolves either
+ // GrpcTelemetry#createClientInterceptor (>= 2.25.0) or #newClientInterceptor (< 2.25.0).
+ // See https://github.com/googleapis/google-cloud-java/issues/13095
+ @Test
+ public void channelConfiguratorAppliesInterceptorAcrossOtelGrpcVersions() {
+ OpenTelemetrySdk myOpenTelemetrySdk = OpenTelemetrySdk.builder().build();
+ FirestoreOptions firestoreOptions =
+ getBaseOptions()
+ .setOpenTelemetryOptions(
+ FirestoreOpenTelemetryOptions.newBuilder()
+ .setOpenTelemetry(myOpenTelemetrySdk)
+ .build())
+ .build();
+ EnabledTraceUtil traceUtil = new EnabledTraceUtil(firestoreOptions);
+ ApiFunction configurator =
+ traceUtil.getChannelConfigurator();
+ assertThat(configurator).isNotNull();
+
+ ManagedChannelBuilder> builder = ManagedChannelBuilder.forAddress("localhost", 9999);
+ assertThat(configurator.apply(builder)).isNotNull();
+ }
+
@Test
public void usesEnabledContext() {
assertThat(defaultEnabledTraceUtil().currentContext() instanceof EnabledTraceUtil.Context)