diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/OpenTelemetryTracingRecorder.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/OpenTelemetryTracingRecorder.java
new file mode 100644
index 0000000000..9d3409c3bc
--- /dev/null
+++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/OpenTelemetryTracingRecorder.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.api.gax.tracing;
+
+import com.google.api.core.BetaApi;
+import com.google.api.core.InternalApi;
+import io.opentelemetry.api.OpenTelemetry;
+
+/**
+ * OpenTelemetry implementation of recording traces. This implementation collects the measurements
+ * related to the lifecyle of an RPC.
+ */
+@BetaApi
+@InternalApi
+public class OpenTelemetryTracingRecorder implements TracingRecorder {
+ private final OpenTelemetry openTelemetry;
+ private final String serviceName;
+
+ /**
+ * Creates a new instance of OpenTelemetryTracingRecorder.
+ *
+ * @param openTelemetry OpenTelemetry instance
+ * @param serviceName Service Name
+ */
+ public OpenTelemetryTracingRecorder(OpenTelemetry openTelemetry, String serviceName) {
+ this.openTelemetry = openTelemetry;
+ this.serviceName = serviceName;
+ }
+}
diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/TracingRecorder.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/TracingRecorder.java
new file mode 100644
index 0000000000..afb7ff6078
--- /dev/null
+++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/TracingRecorder.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.api.gax.tracing;
+
+import com.google.api.core.BetaApi;
+import com.google.api.core.InternalApi;
+
+/**
+ * Provides an interface for tracing recording. The implementer is expected to use an observability
+ * framework, e.g. OpenTelemetry. There should be only one instance of TracingRecorder per client,
+ * all the methods in this class are expected to be called from multiple threads, hence the
+ * implementation must be thread safe.
+ */
+@BetaApi
+@InternalApi
+public interface TracingRecorder {
+ // Minimal working feature: noop implementation for now.
+}
diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/TracingTracer.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/TracingTracer.java
new file mode 100644
index 0000000000..c5ea38a9b1
--- /dev/null
+++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/TracingTracer.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.api.gax.tracing;
+
+import com.google.api.core.BetaApi;
+import com.google.api.core.InternalApi;
+
+/**
+ * This class computes generic traces that can be observed in the lifecycle of an RPC operation. The
+ * responsibility of recording traces should delegate to {@link TracingRecorder}, hence this class
+ * should not have any knowledge about the observability framework used for tracing recording.
+ */
+@BetaApi
+@InternalApi
+public class TracingTracer extends BaseApiTracer {
+ private final TracingRecorder tracingRecorder;
+
+ public TracingTracer(TracingRecorder tracingRecorder) {
+ this.tracingRecorder = tracingRecorder;
+ }
+}
diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/TracingTracerFactory.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/TracingTracerFactory.java
new file mode 100644
index 0000000000..750947b67d
--- /dev/null
+++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/TracingTracerFactory.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.api.gax.tracing;
+
+import com.google.api.core.BetaApi;
+import com.google.api.core.InternalApi;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+
+/**
+ * A {@link ApiTracerFactory} to build instances of {@link TracingTracer}.
+ *
+ *
This class wraps the {@link TracingRecorder} and pass it to {@link TracingTracer}. It will be
+ * used to record traces in {@link TracingTracer}.
+ *
+ *
This class is expected to be initialized once during client initialization.
+ */
+@BetaApi
+@InternalApi
+public class TracingTracerFactory implements ApiTracerFactory {
+ protected TracingRecorder tracingRecorder;
+
+ /** Mapping of client attributes that are set for every TracingTracer */
+ private final Map attributes;
+
+ /** Creates a TracingTracerFactory with no additional client level attributes. */
+ public TracingTracerFactory(TracingRecorder tracingRecorder) {
+ this(tracingRecorder, ImmutableMap.of());
+ }
+
+ /**
+ * Pass in a Map of client level attributes which will be added to every single TracingTracer
+ * created from the ApiTracerFactory.
+ */
+ public TracingTracerFactory(TracingRecorder tracingRecorder, Map attributes) {
+ this.tracingRecorder = tracingRecorder;
+ this.attributes = ImmutableMap.copyOf(attributes);
+ }
+
+ @Override
+ public ApiTracer newTracer(ApiTracer parent, SpanName spanName, OperationType operationType) {
+ if (!TracingUtils.isTracingEnabled()) {
+ return BaseApiTracer.getInstance();
+ }
+ return new TracingTracer(tracingRecorder);
+ }
+}
diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/TracingUtils.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/TracingUtils.java
new file mode 100644
index 0000000000..161f93f558
--- /dev/null
+++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/TracingUtils.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.api.gax.tracing;
+
+import com.google.api.core.InternalApi;
+import com.google.common.annotations.VisibleForTesting;
+
+/** Internal utility class to manage tracing configuration. */
+@InternalApi
+public class TracingUtils {
+ static final String GOOGLE_CLOUD_ENABLE_TRACING = "GOOGLE_CLOUD_ENABLE_TRACING";
+
+ private TracingUtils() {}
+
+ /**
+ * Returns true if tracing is enabled via the GOOGLE_CLOUD_ENABLE_TRACING environment variable or
+ * system property.
+ */
+ public static boolean isTracingEnabled() {
+ String enableTracing = System.getProperty(GOOGLE_CLOUD_ENABLE_TRACING);
+ if (enableTracing == null) {
+ enableTracing = System.getenv(GOOGLE_CLOUD_ENABLE_TRACING);
+ }
+ return isTracingEnabled(enableTracing);
+ }
+
+ @VisibleForTesting
+ static boolean isTracingEnabled(String envValue) {
+ return "true".equalsIgnoreCase(envValue);
+ }
+}
diff --git a/gax-java/gax/src/test/java/com/google/api/gax/tracing/TracingTracerFactoryTest.java b/gax-java/gax/src/test/java/com/google/api/gax/tracing/TracingTracerFactoryTest.java
new file mode 100644
index 0000000000..9169b14abd
--- /dev/null
+++ b/gax-java/gax/src/test/java/com/google/api/gax/tracing/TracingTracerFactoryTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.api.gax.tracing;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+
+import com.google.api.gax.tracing.ApiTracerFactory.OperationType;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class TracingTracerFactoryTest {
+ private TracingRecorder tracingRecorder;
+ private TracingTracerFactory factory;
+ private ApiTracer parent;
+ private SpanName spanName;
+
+ @BeforeEach
+ void setUp() {
+ tracingRecorder = mock(TracingRecorder.class);
+ factory = new TracingTracerFactory(tracingRecorder);
+ parent = mock(ApiTracer.class);
+ spanName = mock(SpanName.class);
+ }
+
+ @AfterEach
+ void tearDown() {
+ System.clearProperty("GOOGLE_CLOUD_ENABLE_TRACING");
+ }
+
+ @Test
+ void testNewTracer_enabled() {
+ System.setProperty("GOOGLE_CLOUD_ENABLE_TRACING", "true");
+ ApiTracer tracer = factory.newTracer(parent, spanName, OperationType.Unary);
+ assertThat(tracer).isInstanceOf(TracingTracer.class);
+ }
+
+ @Test
+ void testNewTracer_disabled() {
+ System.setProperty("GOOGLE_CLOUD_ENABLE_TRACING", "false");
+ ApiTracer tracer = factory.newTracer(parent, spanName, OperationType.Unary);
+ assertThat(tracer).isSameInstanceAs(BaseApiTracer.getInstance());
+ }
+
+ @Test
+ void testNewTracer_defaultDisabled() {
+ ApiTracer tracer = factory.newTracer(parent, spanName, OperationType.Unary);
+ assertThat(tracer).isSameInstanceAs(BaseApiTracer.getInstance());
+ }
+}
diff --git a/gax-java/gax/src/test/java/com/google/api/gax/tracing/TracingTracerTest.java b/gax-java/gax/src/test/java/com/google/api/gax/tracing/TracingTracerTest.java
new file mode 100644
index 0000000000..f8506d9f06
--- /dev/null
+++ b/gax-java/gax/src/test/java/com/google/api/gax/tracing/TracingTracerTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.api.gax.tracing;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+class TracingTracerTest {
+
+ @Test
+ void testConstructor() {
+ TracingRecorder recorder = Mockito.mock(TracingRecorder.class);
+ TracingTracer tracer = new TracingTracer(recorder);
+ assertThat(tracer).isNotNull();
+ }
+}
diff --git a/gax-java/gax/src/test/java/com/google/api/gax/tracing/TracingUtilsTest.java b/gax-java/gax/src/test/java/com/google/api/gax/tracing/TracingUtilsTest.java
new file mode 100644
index 0000000000..9449fc571f
--- /dev/null
+++ b/gax-java/gax/src/test/java/com/google/api/gax/tracing/TracingUtilsTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.api.gax.tracing;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+class TracingUtilsTest {
+
+ @Test
+ void testIsTracingEnabled_defaultToFalse() {
+ assertThat(TracingUtils.isTracingEnabled(null)).isFalse();
+ }
+
+ @Test
+ void testIsTracingEnabled_true() {
+ assertThat(TracingUtils.isTracingEnabled("true")).isTrue();
+ assertThat(TracingUtils.isTracingEnabled("TRUE")).isTrue();
+ }
+
+ @Test
+ void testIsTracingEnabled_false() {
+ assertThat(TracingUtils.isTracingEnabled("false")).isFalse();
+ assertThat(TracingUtils.isTracingEnabled("random")).isFalse();
+ assertThat(TracingUtils.isTracingEnabled("")).isFalse();
+ }
+}
diff --git a/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelMetrics.java b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelMetrics.java
index 06f46deee8..8fb7348851 100644
--- a/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelMetrics.java
+++ b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelMetrics.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2024 Google LLC
+ * Copyright 2026 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -30,6 +30,7 @@
package com.google.showcase.v1beta1.it;
+import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import com.google.api.client.http.javanet.NetHttpTransport;
@@ -42,9 +43,17 @@
import com.google.api.gax.rpc.StatusCode.Code;
import com.google.api.gax.rpc.UnaryCallable;
import com.google.api.gax.rpc.UnavailableException;
+import com.google.api.gax.tracing.ApiTracer;
+import com.google.api.gax.tracing.ApiTracerFactory;
+import com.google.api.gax.tracing.BaseApiTracer;
import com.google.api.gax.tracing.MetricsTracer;
import com.google.api.gax.tracing.MetricsTracerFactory;
import com.google.api.gax.tracing.OpenTelemetryMetricsRecorder;
+import com.google.api.gax.tracing.OpenTelemetryTracingRecorder;
+import com.google.api.gax.tracing.SpanName;
+import com.google.api.gax.tracing.TracingRecorder;
+import com.google.api.gax.tracing.TracingTracer;
+import com.google.api.gax.tracing.TracingTracerFactory;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@@ -72,6 +81,7 @@
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.metrics.data.PointData;
import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader;
+import io.opentelemetry.sdk.trace.SdkTracerProvider;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
@@ -146,12 +156,18 @@ private OpenTelemetryMetricsRecorder createOtelMetricsRecorder(
InMemoryMetricReader inMemoryMetricReader) {
SdkMeterProvider sdkMeterProvider =
SdkMeterProvider.builder().registerMetricReader(inMemoryMetricReader).build();
-
OpenTelemetry openTelemetry =
OpenTelemetrySdk.builder().setMeterProvider(sdkMeterProvider).build();
return new OpenTelemetryMetricsRecorder(openTelemetry, SERVICE_NAME);
}
+ private OpenTelemetryTracingRecorder createOtelTracingRecorder() {
+ SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder().build();
+ OpenTelemetry openTelemetry =
+ OpenTelemetrySdk.builder().setTracerProvider(sdkTracerProvider).build();
+ return new OpenTelemetryTracingRecorder(openTelemetry, SERVICE_NAME);
+ }
+
@BeforeEach
void setup() throws Exception {
inMemoryMetricReader = InMemoryMetricReader.create();
@@ -167,6 +183,8 @@ void setup() throws Exception {
@AfterEach
void cleanup() throws InterruptedException, IOException {
+ System.clearProperty("GOOGLE_CLOUD_ENABLE_TRACING");
+
inMemoryMetricReader.close();
inMemoryMetricReader.shutdown();
@@ -919,4 +937,28 @@ void grpcOpenTelemetryImplementation_setSampledToLocalTracing_methodFullNameIsRe
echoClient.close();
echoClient.awaitTermination(TestClientInitializer.AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS);
}
+
+ @Test
+ void testTracingFeatureFlag() {
+ // Test tracing disabled
+ System.setProperty("GOOGLE_CLOUD_ENABLE_TRACING", "false");
+ TracingRecorder recorder = createOtelTracingRecorder();
+ TracingTracerFactory factory = new TracingTracerFactory(recorder);
+ ApiTracer tracer =
+ factory.newTracer(
+ BaseApiTracer.getInstance(),
+ SpanName.of("EchoClient", "Echo"),
+ ApiTracerFactory.OperationType.Unary);
+ assertThat(tracer).isNotInstanceOf(TracingTracer.class);
+ assertThat(tracer).isSameInstanceAs(BaseApiTracer.getInstance());
+
+ // Test tracing enabled
+ System.setProperty("GOOGLE_CLOUD_ENABLE_TRACING", "true");
+ tracer =
+ factory.newTracer(
+ BaseApiTracer.getInstance(),
+ SpanName.of("EchoClient", "Echo"),
+ ApiTracerFactory.OperationType.Unary);
+ assertThat(tracer).isInstanceOf(TracingTracer.class);
+ }
}