Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
e01ca06
feat(observability): add no-op implementation of tracing
diegomarquezp Jan 8, 2026
d3f61d1
chore: add otel tracing recorder
diegomarquezp Jan 8, 2026
cf98e86
chore: add javadocs
diegomarquezp Jan 8, 2026
523c301
chore: adjust tests and conform more closely to metrics counterpart.
diegomarquezp Jan 8, 2026
d9534bd
chore: expand imports in otel it
diegomarquezp Jan 8, 2026
196d591
Update gax-java/gax/src/main/java/com/google/api/gax/tracing/OpenTele…
diegomarquezp Jan 8, 2026
ea075d3
test: use tracer provider in ItOtelMetrics
diegomarquezp Jan 8, 2026
2997153
Merge branch 'observability/tracing-noop' of https://github.com/googl…
diegomarquezp Jan 8, 2026
2c26971
chore: format
diegomarquezp Jan 8, 2026
1a76c29
chore: generate libraries at Thu Jan 8 19:39:27 UTC 2026
cloud-java-bot Jan 8, 2026
8a0f855
chore: add dummy tracing metric
diegomarquezp Jan 9, 2026
dc3ed42
chore: refine tracing IT
diegomarquezp Jan 9, 2026
5287f82
feat: add composite api tracer
diegomarquezp Jan 9, 2026
ce2d85b
test: use global config for tracing
diegomarquezp Jan 9, 2026
d6341cc
chore: restore metrics it
diegomarquezp Jan 9, 2026
a9c70ab
chore: format
diegomarquezp Jan 12, 2026
69a7fa4
Merge branch 'observability/tracing-noop' of https://github.com/googl…
diegomarquezp Jan 12, 2026
a6716b4
chore: format ii
diegomarquezp Jan 12, 2026
99bfd5b
chore: generate libraries at Mon Jan 12 21:30:41 UTC 2026
cloud-java-bot Jan 12, 2026
7b5709b
Merge branch 'observability/tracing-noop' of https://github.com/googl…
diegomarquezp Jan 13, 2026
6259b86
fix: Create a single S2AChannelCredentials per application (#3989)
rmehta19 Jan 9, 2026
61c1671
feat: add org.json:json to third-party-dependencies pom (#4047)
chingor13 Jan 9, 2026
069bc77
build: Update macOS version in nightly workflow (#4048)
diegomarquezp Jan 12, 2026
f5f94d8
chore(deps): update upper bound dependencies file (#4052)
diegomarquezp Jan 12, 2026
64685b5
deps: update google.http-client.version to 2.0.3 (#4054)
diegomarquezp Jan 12, 2026
7869ed9
chore: update googleapis commit at Wed Dec 10 02:37:02 UTC 2025 (#4013)
cloud-java-bot Jan 12, 2026
5218acb
chore(main): release 2.65.0 (#4058)
release-please[bot] Jan 13, 2026
7686f7f
build: Skip clirr check for protobuf 4.x upgrade (#4061)
blakeli0 Jan 13, 2026
af882ca
docs: Update docs for GoogleCredentialsProvider#setScopesToApply (#4057)
blakeli0 Jan 13, 2026
7575f5c
chore(main): release 2.65.1-SNAPSHOT (#4060)
release-please[bot] Jan 13, 2026
7d98fcc
build: Skip clirr check for downstream libraries (#4062)
blakeli0 Jan 13, 2026
24f7fc5
chore: Update protobuf runtime version to 4.33.4 in downstream checks…
blakeli0 Jan 13, 2026
cee4ad5
chore(main): release 2.65.1 (#4063)
release-please[bot] Jan 13, 2026
7aa0ea5
chore: cleanup release-please config (#4002)
diegomarquezp Jan 15, 2026
7f90d28
chore: generate libraries at Thu Jan 8 19:39:27 UTC 2026
cloud-java-bot Jan 8, 2026
d0b2eb3
chore: simplify implementation (no C3)
diegomarquezp Jan 21, 2026
ce9df43
Merge remote-tracking branch 'origin/main' into observability/tracing…
diegomarquezp Jan 21, 2026
b063a8d
chore: generate libraries at Wed Jan 21 20:06:59 UTC 2026
cloud-java-bot Jan 21, 2026
5da1d58
Merge branch 'observability/tracing-noop' of https://github.com/googl…
diegomarquezp Jan 23, 2026
8ffb32a
chore: adapt units in gax
diegomarquezp Jan 23, 2026
e3b2cda
chore: new option artifact-name for generator
diegomarquezp Jan 23, 2026
92d56e7
chore: add artifact name property to ClientContext and StubSettings
diegomarquezp Jan 23, 2026
5082240
chore: modify TracingTracerFactory
diegomarquezp Jan 23, 2026
e8d98b0
chore: remove initialization in client context
diegomarquezp Jan 26, 2026
87a3f8c
Merge remote-tracking branch 'origin/main' into observability/tracing…
diegomarquezp Jan 26, 2026
20461c1
chore: configure tracer factory in client context
diegomarquezp Jan 26, 2026
40b74bd
chore: format
diegomarquezp Jan 26, 2026
d1967f7
chore: introduce span context
diegomarquezp Jan 26, 2026
f626d4b
chore: adjust compilation issues and format
diegomarquezp Jan 26, 2026
e9fe905
chore: add scope
diegomarquezp Jan 27, 2026
09d1539
test: adjust goldens for pubsub
diegomarquezp Jan 27, 2026
a240c29
chore: suppress resource closed warning
diegomarquezp Jan 27, 2026
2334254
feat: generate with artifact_name
diegomarquezp Jan 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ public GapicClass generate(GapicContext context, Service service) {
service, serviceConfig, methodSettingsMemberVarExprs, messageTypes, typeStore))
.setMethods(
createClassMethods(
context,
service,
methodSettingsMemberVarExprs,
deprecatedSettingVarNames,
Expand Down Expand Up @@ -1033,6 +1034,7 @@ private static Expr createPagedListResponseFactoryAssignExpr(
}

private List<MethodDefinition> createClassMethods(
GapicContext context,
Service service,
Map<String, VariableExpr> methodSettingsMemberVarExprs,
Set<String> deprecatedSettingVarNames,
Expand All @@ -1043,7 +1045,7 @@ private List<MethodDefinition> createClassMethods(
createMethodSettingsGetterMethods(
methodSettingsMemberVarExprs, deprecatedSettingVarNames, internalSettingVarNames));
javaMethods.add(createCreateStubMethod(service, typeStore));
javaMethods.addAll(createDefaultHelperAndGetterMethods(service, typeStore));
javaMethods.addAll(createDefaultHelperAndGetterMethods(context, service, typeStore));
javaMethods.addAll(
createNewBuilderMethods(
service,
Expand Down Expand Up @@ -1185,7 +1187,7 @@ private MethodDefinition createCreateStubMethod(Service service, TypeStore typeS
}

private List<MethodDefinition> createDefaultHelperAndGetterMethods(
Service service, TypeStore typeStore) {
GapicContext context, Service service, TypeStore typeStore) {
List<MethodDefinition> javaMethods = new ArrayList<>();
TypeNode returnType;

Expand All @@ -1206,6 +1208,21 @@ private List<MethodDefinition> createDefaultHelperAndGetterMethods(
.build());
}

// Create the getArtifactName method.
if (context.artifactName().isPresent()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The copyright year in the newly added code block is set to 2026. Please update this to the current year, 2024, to maintain consistency with the project's copyright practices.

returnType = TypeNode.STRING;
javaMethods.add(
MethodDefinition.builder()
.setIsOverride(true)
.setScope(ScopeNode.PROTECTED)
.setIsStatic(false)
.setReturnType(returnType)
.setName("getArtifactName")
.setReturnExpr(
ValueExpr.withValue(StringObjectValue.withValue(context.artifactName().get())))
.build());
}

// Create the defaultExecutorProviderBuilder method.
returnType =
TypeNode.withReference(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ public abstract class GapicContext {

public abstract boolean restNumericEnumsEnabled();

public abstract Optional<String> artifactName();

public GapicMetadata gapicMetadata() {
return gapicMetadata;
}
Expand Down Expand Up @@ -130,6 +132,8 @@ public Builder setHelperResourceNames(Set<ResourceName> helperResourceNames) {

public abstract Builder setTransport(Transport transport);

public abstract Builder setArtifactName(Optional<String> artifactName);

abstract ImmutableMap<String, ResourceName> resourceNames();

abstract ImmutableMap<String, ResourceName> helperResourceNames();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ public static GapicContext parse(CodeGeneratorRequest request) {
Optional<GapicLanguageSettings> languageSettingsOpt =
GapicLanguageSettingsParser.parse(gapicYamlConfigPathOpt);
Optional<String> transportOpt = PluginArgumentParser.parseTransport(request);
Optional<String> artifactNameOpt = PluginArgumentParser.parseArtifactName(request);

boolean willGenerateMetadata = PluginArgumentParser.hasMetadataFlag(request);
boolean willGenerateNumericEnum = PluginArgumentParser.hasNumericEnumFlag(request);
Expand Down Expand Up @@ -253,6 +254,7 @@ public static GapicContext parse(CodeGeneratorRequest request) {
.setServiceYamlProto(serviceYamlProtoOpt.orElse(null))
.setTransport(transport)
.setRestNumericEnumsEnabled(willGenerateNumericEnum)
.setArtifactName(artifactNameOpt)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class PluginArgumentParser {
private static final String EQUALS = "=";

// Synced to rules_java_gapic/java_gapic.bzl.
@VisibleForTesting static final String KEY_ARTIFACT_NAME = "artifact-name";
@VisibleForTesting static final String KEY_GRPC_SERVICE_CONFIG = "grpc-service-config";
@VisibleForTesting static final String KEY_GAPIC_CONFIG = "gapic-config";
@VisibleForTesting static final String KEY_METADATA = "metadata";
Expand Down Expand Up @@ -53,6 +54,10 @@ static Optional<String> parseTransport(CodeGeneratorRequest request) {
return parseConfigArgument(request.getParameter(), KEY_TRANSPORT);
}

static Optional<String> parseArtifactName(CodeGeneratorRequest request) {
return parseConfigArgument(request.getParameter(), KEY_ARTIFACT_NAME);
}

static boolean hasMetadataFlag(CodeGeneratorRequest request) {
return hasFlag(request.getParameter(), KEY_METADATA);
}
Expand Down
1 change: 1 addition & 0 deletions gax-java/dependencies.properties
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ maven.com_google_api_grpc_grpc_google_common_protos=com.google.api.grpc:grpc-goo
maven.com_google_auth_google_auth_library_oauth2_http=com.google.auth:google-auth-library-oauth2-http:1.42.1
maven.com_google_auth_google_auth_library_credentials=com.google.auth:google-auth-library-credentials:1.42.1
maven.io_opentelemetry_opentelemetry_api=io.opentelemetry:opentelemetry-api:1.47.0
maven.io_opentelemetry_opentelemetry_context=io.opentelemetry:opentelemetry-context:1.47.0
maven.io_opencensus_opencensus_api=io.opencensus:opencensus-api:0.31.1
maven.io_opencensus_opencensus_contrib_grpc_metrics=io.opencensus:opencensus-contrib-grpc-metrics:0.31.1
maven.io_opencensus_opencensus_contrib_http_util=io.opencensus:opencensus-contrib-http-util:0.31.1
Expand Down
1 change: 1 addition & 0 deletions gax-java/gax/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ _COMPILE_DEPS = [
"@com_google_errorprone_error_prone_annotations//jar",
"@com_google_guava_guava//jar",
"@io_opentelemetry_opentelemetry_api//jar",
"@io_opentelemetry_opentelemetry_context//jar",
"@io_opencensus_opencensus_api//jar",
"@io_opencensus_opencensus_contrib_http_util//jar",
"@io_grpc_grpc_java//context:context",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,13 @@ public static ClientContext create(StubSettings settings) throws IOException {
backgroundResources.add(watchdog);
}

ApiTracerFactory tracerFactory = settings.getTracerFactory();
if (!Strings.isNullOrEmpty(settings.getArtifactName())) {
tracerFactory =
tracerFactory.withAttributes(
ImmutableMap.of("gcp.client.artifact", settings.getArtifactName()));
}

return newBuilder()
.setBackgroundResources(backgroundResources.build())
.setExecutor(backgroundExecutor)
Expand All @@ -284,7 +291,7 @@ public static ClientContext create(StubSettings settings) throws IOException {
.setQuotaProjectId(settings.getQuotaProjectId())
.setStreamWatchdog(watchdog)
.setStreamWatchdogCheckIntervalDuration(settings.getStreamWatchdogCheckIntervalDuration())
.setTracerFactory(settings.getTracerFactory())
.setTracerFactory(tracerFactory)
.setEndpointContext(endpointContext)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,16 @@ protected String getServiceName() {
return "";
}

/**
* Marked with Internal Api and meant to be overridden by the generated subclasses. This getter is
* used to set the artifactName to the ClientContext. The value in generated StubSettings
* subclasses comes from the build configuration.
*/
@InternalApi
protected String getArtifactName() {
return "";
}

/**
* @return the fully resolved universe domain used by the client
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import com.google.api.core.InternalApi;
import com.google.api.core.InternalExtensionOnly;
import java.util.Map;

/**
* A factory to create new instances of {@link ApiTracer}s.
Expand Down Expand Up @@ -61,4 +62,14 @@ enum OperationType {
* @param operationType the type of operation that the tracer will trace
*/
ApiTracer newTracer(ApiTracer parent, SpanName spanName, OperationType operationType);

/**
* Returns a new {@link ApiTracerFactory} that will add the given attributes to all tracers
* created by the factory.
*
* @param attributes the attributes to add to all tracers
*/
default ApiTracerFactory withAttributes(Map<String, String> attributes) {
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright 2026 Google LLC
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The copyright year in this new file is 2026. Please update it to 2024.

*
* 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;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanBuilder;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;

import java.util.Map;

/**
* 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 Tracer tracer;

public OpenTelemetryTracingRecorder(OpenTelemetry openTelemetry) {
this.tracer = openTelemetry.getTracer("gax-java");
}

@Override
@SuppressWarnings("MustBeClosedChecker") // Scope is closed later in the lifecycle
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The @SuppressWarnings("MustBeClosedChecker") annotation should ideally be accompanied by a comment explaining why it is safe to suppress this warning in this specific context. This helps future maintainers understand the rationale and ensures that resource leaks are not inadvertently introduced.

public SpanHandle startSpan(String name, Map<String, String> attributes) {
SpanBuilder spanBuilder =
tracer.spanBuilder(name).setSpanKind(SpanKind.CLIENT); // Mark as a network-facing call

if (attributes != null) {
attributes.forEach((k, v) -> spanBuilder.setAttribute(k, v));
}

Span span = spanBuilder.startSpan();
// makeCurrent() puts this span into the thread-local storage
Scope scope = span.makeCurrent();

return new OtelSpanHandle(span, scope);
}

private static class OtelSpanHandle implements SpanHandle {
private final Span span;
private final Scope scope;

private OtelSpanHandle(Span span, Scope scope) {
this.span = span;
this.scope = scope;
}

@Override
public void end() {
scope.close(); // Remove from thread-local storage
span.end();
}

@Override
public void recordError(Throwable error) {
span.recordException(error);
span.setStatus(StatusCode.ERROR);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 2026 Google LLC
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The copyright year in this new file is 2026. Please update it to 2024.

*
* 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 java.util.HashMap;
import java.util.Map;

@BetaApi
@InternalApi
public class OpenTelemetryTracingTracer implements ApiTracer {
private final TracingRecorder recorder;
private final Map<String, String> attributes;
private TracingRecorder.SpanHandle operationHandle;
private TracingRecorder.SpanHandle attemptHandle;

public OpenTelemetryTracingTracer(TracingRecorder recorder, String methodName) {
this.recorder = recorder;
this.attributes = new HashMap<>();
this.attributes.put("method", methodName);

// Start the long-lived operation span
this.operationHandle = recorder.startSpan(methodName + "/operation", attributes);
}

@Override
public void attemptStarted(Object request, int attemptNumber) {
// Start the specific attempt span
this.attemptHandle = recorder.startSpan(this.attributes.get("method") + "/attempt", attributes);
}

@Override
public void attemptSucceeded() {
if (attemptHandle != null) {
attemptHandle.end();
}
}

@Override
public void operationSucceeded() {
operationHandle.end();
}

@Override
public void operationFailed(Throwable error) {
operationHandle.recordError(error);
operationHandle.end();
}

public void addAttributes(Map<String, String> attributes) {
this.attributes.putAll(attributes);
}
}
Loading
Loading