Skip to content

Commit becdb01

Browse files
authored
Merge branch 'main' into docs-auth-impersonated-quota-project-12604
2 parents 32b05d0 + 0c481bd commit becdb01

7 files changed

Lines changed: 98 additions & 18 deletions

File tree

‎.github/requirements.txt‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ requests==2.33.0 \
108108
--hash=sha256:3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b \
109109
--hash=sha256:c7ebc5e8b0f21837386ad0e1c8fe8b829fa5f544d8df3b2253bff14ef29d7652
110110
# via -r requirements.in
111-
urllib3==2.6.3 \
112-
--hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \
113-
--hash=sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4
111+
urllib3==2.8.0 \
112+
--hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3 \
113+
--hash=sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63
114114
# via requests

‎sdk-platform-java/gax-java/gax-grpc/pom.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@
158158
<artifactId>maven-surefire-plugin</artifactId>
159159
<configuration>
160160
<!-- These tests require an Env Var to be set. Use -PenvVarTest to ONLY run these tests -->
161-
<test>!InstantiatingGrpcChannelProviderTest#testLogDirectPathMisconfig_AttemptDirectPathNotSetAndAttemptDirectPathXdsSetViaEnv_warns,!InstantiatingGrpcChannelProviderTest#canUseDirectPath_directPathEnvVarNotSet_attemptDirectPathIsTrue,InstantiatingGrpcChannelProviderTest#testLogDirectPathMisconfigWrongCredential</test>
161+
<test>!InstantiatingGrpcChannelProviderTest#testLogDirectPathMisconfig_AttemptDirectPathNotSetAndAttemptDirectPathXdsSetViaEnv_warns,!InstantiatingGrpcChannelProviderTest#canUseDirectPath_directPathEnvVarNotSet_attemptDirectPathIsTrue</test>
162162
<!-- <test>!InstantiatingGrpcChannelProviderTest#testLogDirectPathMisconfig_AttemptDirectPathNotSetAndAttemptDirectPathXdsSetViaEnv_warns</test> -->
163163
</configuration>
164164
</plugin>

‎sdk-platform-java/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcLoggingInterceptorTest.java‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232

3333
import static org.mockito.ArgumentMatchers.any;
3434
import static org.mockito.Mockito.mock;
35-
import static org.mockito.Mockito.spy;
3635
import static org.mockito.Mockito.verify;
3736
import static org.mockito.Mockito.when;
3837

@@ -83,7 +82,7 @@ void testInterceptor_basic() {
8382
void testInterceptor_responseListener() {
8483
when(channel.newCall(Mockito.<MethodDescriptor<String, Integer>>any(), any(CallOptions.class)))
8584
.thenReturn(call);
86-
GrpcLoggingInterceptor interceptor = spy(new GrpcLoggingInterceptor());
85+
GrpcLoggingInterceptor interceptor = new GrpcLoggingInterceptor();
8786
Channel intercepted = ClientInterceptors.intercept(channel, interceptor);
8887
@SuppressWarnings("unchecked")
8988
ClientCall.Listener<Integer> listener = mock(ClientCall.Listener.class);

‎sdk-platform-java/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,7 @@ void testLogDirectPathMisconfigWrongCredential() throws Exception {
710710
InstantiatingGrpcChannelProvider.newBuilder()
711711
.setAttemptDirectPathXds()
712712
.setAttemptDirectPath(true)
713+
.setEnvProvider(name -> null)
713714
.setHeaderProvider(
714715
mock(HeaderProvider.class, Mockito.withSettings().withoutAnnotations()))
715716
.setExecutor(mock(Executor.class))

‎sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/tracing/OpenTelemetryTracingTracer.java‎

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ class OpenTelemetryTracingTracer implements ApiTracer {
5252
private final Map<String, Object> attemptAttributes;
5353
private final String attemptSpanName;
5454
private final ApiTracerContext apiTracerContext;
55+
// Captures the active trace context from the calling thread at RPC initiation.
56+
// This allows attempt spans—including retries dispatched on background threads—to
57+
// link back to the original parent trace.
58+
private final io.opentelemetry.context.Context parentContext;
5559
private @Nullable Span attemptSpan;
5660

5761
@Override
@@ -82,6 +86,7 @@ public void injectTraceContext(java.util.Map<String, String> carrier) {
8286
this.apiTracerContext = apiTracerContext;
8387
this.attemptSpanName = resolveAttemptSpanName(apiTracerContext);
8488
this.attemptAttributes = new HashMap<>();
89+
this.parentContext = io.opentelemetry.context.Context.current();
8590
buildAttributes();
8691
}
8792

@@ -100,6 +105,7 @@ public void injectTraceContext(java.util.Map<String, String> carrier) {
100105
this.attemptSpanName = attemptSpanName;
101106
this.apiTracerContext = apiTracerContext;
102107
this.attemptAttributes = new HashMap<>();
108+
this.parentContext = io.opentelemetry.context.Context.current();
103109
buildAttributes();
104110
}
105111

@@ -142,12 +148,47 @@ public void attemptStarted(Object request, int attemptNumber) {
142148
// Attempt spans are of the CLIENT kind
143149
spanBuilder.setSpanKind(SpanKind.CLIENT);
144150

151+
// Link attempt span to parent context
152+
spanBuilder.setParent(parentContext);
153+
145154
// Pass the combined attributes to the new SpanBuilder method
146155
spanBuilder.setAllAttributes(ObservabilityUtils.toOtelAttributes(currentAttemptAttributes));
147156

148157
this.attemptSpan = spanBuilder.startSpan();
149158
}
150159

160+
/**
161+
* Signals that the overall logical operation succeeded.
162+
*
163+
* <p>Closes any remaining in-flight attempt span.
164+
*/
165+
@Override
166+
public void operationSucceeded() {
167+
recordErrorAndEndAttempt(null);
168+
}
169+
170+
/**
171+
* Signals that the overall logical operation was cancelled.
172+
*
173+
* <p>Closes any remaining in-flight attempt span with a {@link CancellationException}.
174+
*/
175+
@Override
176+
public void operationCancelled() {
177+
recordErrorAndEndAttempt(new CancellationException());
178+
}
179+
180+
/**
181+
* Signals that the overall logical operation failed permanently.
182+
*
183+
* <p>Closes any remaining in-flight attempt span with the provided error details.
184+
*
185+
* @param error the cause of the operation failure
186+
*/
187+
@Override
188+
public void operationFailed(Throwable error) {
189+
recordErrorAndEndAttempt(error);
190+
}
191+
151192
@Override
152193
public void attemptSucceeded() {
153194
recordErrorAndEndAttempt(null);
@@ -215,10 +256,16 @@ public void attemptPermanentFailure(Throwable error) {
215256
recordErrorAndEndAttempt(error);
216257
}
217258

259+
/**
260+
* Records error details and ends the current attempt span.
261+
*
262+
* @param error the exception associated with the attempt failure, or {@code null} if successful
263+
*/
218264
private void recordErrorAndEndAttempt(@Nullable Throwable error) {
219265
if (attemptSpan == null) {
220266
return;
221267
}
268+
222269
Map<String, Object> responseAttributes =
223270
ObservabilityUtils.getResponseAttributes(error, this.apiTracerContext.transport());
224271
if (!responseAttributes.isEmpty()) {
@@ -230,14 +277,6 @@ private void recordErrorAndEndAttempt(@Nullable Throwable error) {
230277
ObservabilityAttributes.STATUS_MESSAGE_ATTRIBUTE, error.getMessage());
231278
}
232279

233-
endAttempt();
234-
}
235-
236-
private void endAttempt() {
237-
if (attemptSpan == null) {
238-
return;
239-
}
240-
241280
attemptSpan.end();
242281
attemptSpan = null;
243282
}

‎sdk-platform-java/gax-java/gax/src/test/java/com/google/api/gax/tracing/OpenTelemetryTracingTracerFactoryTest.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ void setUp() {
7575
when(openTelemetry.getTracer(anyString())).thenReturn(tracer);
7676
when(tracer.spanBuilder(anyString())).thenReturn(spanBuilder);
7777
when(spanBuilder.setSpanKind(any())).thenReturn(spanBuilder);
78+
when(spanBuilder.setParent(any())).thenReturn(spanBuilder);
7879
when(spanBuilder.setAllAttributes(any(Attributes.class))).thenReturn(spanBuilder);
7980
when(spanBuilder.startSpan()).thenReturn(span);
8081

‎sdk-platform-java/gax-java/gax/src/test/java/com/google/api/gax/tracing/OpenTelemetryTracingTracerTest.java‎

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import static org.mockito.ArgumentMatchers.any;
3434
import static org.mockito.ArgumentMatchers.anyString;
3535
import static org.mockito.ArgumentMatchers.eq;
36+
import static org.mockito.Mockito.lenient;
3637
import static org.mockito.Mockito.never;
3738
import static org.mockito.Mockito.verify;
3839
import static org.mockito.Mockito.when;
@@ -69,10 +70,11 @@ class OpenTelemetryTracingTracerTest {
6970

7071
@BeforeEach
7172
void setUp() {
72-
when(tracer.spanBuilder(anyString())).thenReturn(spanBuilder);
73-
when(spanBuilder.setSpanKind(any(SpanKind.class))).thenReturn(spanBuilder);
74-
when(spanBuilder.setAllAttributes(any(Attributes.class))).thenReturn(spanBuilder);
75-
when(spanBuilder.startSpan()).thenReturn(span);
73+
lenient().when(tracer.spanBuilder(anyString())).thenReturn(spanBuilder);
74+
lenient().when(spanBuilder.setSpanKind(any(SpanKind.class))).thenReturn(spanBuilder);
75+
lenient().when(spanBuilder.setParent(any())).thenReturn(spanBuilder);
76+
lenient().when(spanBuilder.setAllAttributes(any(Attributes.class))).thenReturn(spanBuilder);
77+
lenient().when(spanBuilder.startSpan()).thenReturn(span);
7678
openTelemetryTracingTracer =
7779
new OpenTelemetryTracingTracer(tracer, ApiTracerContext.empty(), ATTEMPT_SPAN_NAME);
7880
}
@@ -680,4 +682,42 @@ void testInjectTraceContext_addsHeaders() {
680682
assertThat(carrier.get("traceparent")).contains("00000000000000000000000000000001");
681683
assertThat(carrier.get("traceparent")).contains("0000000000000002");
682684
}
685+
686+
@Test
687+
void testAttemptStarted_setsParentToParentContext() {
688+
openTelemetryTracingTracer.attemptStarted(new Object(), 1);
689+
verify(spanBuilder).setParent(any(io.opentelemetry.context.Context.class));
690+
}
691+
692+
@Test
693+
void testOperationSucceeded_endsActiveAttemptSpan() {
694+
openTelemetryTracingTracer.attemptStarted(new Object(), 1);
695+
openTelemetryTracingTracer.operationSucceeded();
696+
697+
verify(span).end();
698+
}
699+
700+
@Test
701+
void testOperationFailed_endsActiveAttemptSpanWithErrorAttributes() {
702+
openTelemetryTracingTracer.attemptStarted(new Object(), 1);
703+
openTelemetryTracingTracer.operationFailed(new RuntimeException("operation failed"));
704+
705+
verify(span).setAttribute(ObservabilityAttributes.STATUS_MESSAGE_ATTRIBUTE, "operation failed");
706+
verify(span).end();
707+
}
708+
709+
@Test
710+
void testOperationCancelled_endsActiveAttemptSpanWithCancellation() {
711+
openTelemetryTracingTracer.attemptStarted(new Object(), 1);
712+
openTelemetryTracingTracer.operationCancelled();
713+
714+
ArgumentCaptor<Attributes> attrsCaptor = ArgumentCaptor.forClass(Attributes.class);
715+
verify(span).setAllAttributes(attrsCaptor.capture());
716+
verify(span).end();
717+
718+
assertThat(attrsCaptor.getValue().asMap())
719+
.containsEntry(
720+
AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE),
721+
"CANCELLED");
722+
}
683723
}

0 commit comments

Comments
 (0)