Skip to content

Commit 9e42e01

Browse files
committed
feat(gax): correlate M3 client duration metrics with T3 span exemplars
1 parent 2f08818 commit 9e42e01

3 files changed

Lines changed: 168 additions & 27 deletions

File tree

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

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -91,22 +91,31 @@ public Scope inScope() {
9191

9292
@Override
9393
public void operationSucceeded() {
94-
for (int i = children.size() - 1; i >= 0; i--) {
95-
children.get(i).operationSucceeded();
94+
// Activate ambient span context so child tracers (e.g. metrics) can sample trace exemplars
95+
try (Scope ignored = inScope()) {
96+
for (int i = children.size() - 1; i >= 0; i--) {
97+
children.get(i).operationSucceeded();
98+
}
9699
}
97100
}
98101

99102
@Override
100103
public void operationCancelled() {
101-
for (int i = children.size() - 1; i >= 0; i--) {
102-
children.get(i).operationCancelled();
104+
// Activate ambient span context so child tracers (e.g. metrics) can sample trace exemplars
105+
try (Scope ignored = inScope()) {
106+
for (int i = children.size() - 1; i >= 0; i--) {
107+
children.get(i).operationCancelled();
108+
}
103109
}
104110
}
105111

106112
@Override
107113
public void operationFailed(Throwable error) {
108-
for (int i = children.size() - 1; i >= 0; i--) {
109-
children.get(i).operationFailed(error);
114+
// Activate ambient span context so child tracers (e.g. metrics) can sample trace exemplars
115+
try (Scope ignored = inScope()) {
116+
for (int i = children.size() - 1; i >= 0; i--) {
117+
children.get(i).operationFailed(error);
118+
}
110119
}
111120
}
112121

@@ -134,43 +143,61 @@ public void attemptStarted(Object request, int attemptNumber) {
134143

135144
@Override
136145
public void attemptSucceeded() {
137-
for (int i = children.size() - 1; i >= 0; i--) {
138-
children.get(i).attemptSucceeded();
146+
// Activate ambient span context so child tracers (e.g. metrics) can sample trace exemplars
147+
try (Scope ignored = inScope()) {
148+
for (int i = children.size() - 1; i >= 0; i--) {
149+
children.get(i).attemptSucceeded();
150+
}
139151
}
140152
}
141153

142154
@Override
143155
public void attemptCancelled() {
144-
for (int i = children.size() - 1; i >= 0; i--) {
145-
children.get(i).attemptCancelled();
156+
// Activate ambient span context so child tracers (e.g. metrics) can sample trace exemplars
157+
try (Scope ignored = inScope()) {
158+
for (int i = children.size() - 1; i >= 0; i--) {
159+
children.get(i).attemptCancelled();
160+
}
146161
}
147162
}
148163

149164
@Override
150165
public void attemptFailed(Throwable error, org.threeten.bp.Duration delay) {
151-
for (int i = children.size() - 1; i >= 0; i--) {
152-
children.get(i).attemptFailed(error, delay);
166+
// Activate ambient span context so child tracers (e.g. metrics) can sample trace exemplars
167+
try (Scope ignored = inScope()) {
168+
for (int i = children.size() - 1; i >= 0; i--) {
169+
children.get(i).attemptFailed(error, delay);
170+
}
153171
}
154172
}
155173

156174
@Override
157175
public void attemptFailedDuration(Throwable error, java.time.Duration delay) {
158-
for (int i = children.size() - 1; i >= 0; i--) {
159-
children.get(i).attemptFailedDuration(error, delay);
176+
// Activate ambient span context so child tracers (e.g. metrics) can sample trace exemplars
177+
try (Scope ignored = inScope()) {
178+
for (int i = children.size() - 1; i >= 0; i--) {
179+
children.get(i).attemptFailedDuration(error, delay);
180+
}
160181
}
161182
}
162183

163184
@Override
164185
public void attemptFailedRetriesExhausted(Throwable error) {
165-
for (int i = children.size() - 1; i >= 0; i--) {
166-
children.get(i).attemptFailedRetriesExhausted(error);
186+
// Activate ambient span context so child tracers (e.g. metrics) can sample trace exemplars
187+
try (Scope ignored = inScope()) {
188+
for (int i = children.size() - 1; i >= 0; i--) {
189+
children.get(i).attemptFailedRetriesExhausted(error);
190+
}
167191
}
168192
}
169193

170194
@Override
171195
public void attemptPermanentFailure(Throwable error) {
172-
for (int i = children.size() - 1; i >= 0; i--) {
173-
children.get(i).attemptPermanentFailure(error);
196+
// Activate ambient span context so child tracers (e.g. metrics) can sample trace exemplars
197+
try (Scope ignored = inScope()) {
198+
for (int i = children.size() - 1; i >= 0; i--) {
199+
children.get(i).attemptPermanentFailure(error);
200+
}
174201
}
175202
}
176203

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ void testNewTracerWithParentAndSpanName() {
5959

6060
ApiTracer tracer1 = mock(ApiTracer.class, Mockito.withSettings().withoutAnnotations());
6161
ApiTracer tracer2 = mock(ApiTracer.class, Mockito.withSettings().withoutAnnotations());
62+
when(tracer1.inScope()).thenReturn(() -> {});
63+
when(tracer2.inScope()).thenReturn(() -> {});
6264

6365
when(childFactory1.newTracer(parent, spanName, operationType)).thenReturn(tracer1);
6466
when(childFactory2.newTracer(parent, spanName, operationType)).thenReturn(tracer2);
@@ -81,6 +83,8 @@ void testNewTracerWithApiTracerContext() {
8183

8284
ApiTracer tracer1 = mock(ApiTracer.class, Mockito.withSettings().withoutAnnotations());
8385
ApiTracer tracer2 = mock(ApiTracer.class, Mockito.withSettings().withoutAnnotations());
86+
when(tracer1.inScope()).thenReturn(() -> {});
87+
when(tracer2.inScope()).thenReturn(() -> {});
8488

8589
when(childFactory1.newTracer(parent, context)).thenReturn(tracer1);
8690
when(childFactory2.newTracer(parent, context)).thenReturn(tracer2);
@@ -117,6 +121,8 @@ void testWithContext() {
117121

118122
ApiTracer tracer1 = mock(ApiTracer.class, Mockito.withSettings().withoutAnnotations());
119123
ApiTracer tracer2 = mock(ApiTracer.class, Mockito.withSettings().withoutAnnotations());
124+
when(tracer1.inScope()).thenReturn(() -> {});
125+
when(tracer2.inScope()).thenReturn(() -> {});
120126

121127
when(contextualizedFactory1.newTracer(parent, tracerContext)).thenReturn(tracer1);
122128
when(contextualizedFactory2.newTracer(parent, tracerContext)).thenReturn(tracer2);

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

Lines changed: 117 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -127,27 +127,63 @@ void testInScope_childScopeCloseThrows() {
127127

128128
@Test
129129
void testOperationSucceeded() {
130+
ApiTracer.Scope scope1 =
131+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
132+
ApiTracer.Scope scope2 =
133+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
134+
when(child1.inScope()).thenReturn(scope1);
135+
when(child2.inScope()).thenReturn(scope2);
136+
130137
compositeTracer.operationSucceeded();
131-
InOrder inOrder = inOrder(child2, child1);
138+
139+
InOrder inOrder = inOrder(child1, child2, scope2, scope1);
140+
inOrder.verify(child1).inScope();
141+
inOrder.verify(child2).inScope();
132142
inOrder.verify(child2).operationSucceeded();
133143
inOrder.verify(child1).operationSucceeded();
144+
inOrder.verify(scope2).close();
145+
inOrder.verify(scope1).close();
134146
}
135147

136148
@Test
137149
void testOperationCancelled() {
150+
ApiTracer.Scope scope1 =
151+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
152+
ApiTracer.Scope scope2 =
153+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
154+
when(child1.inScope()).thenReturn(scope1);
155+
when(child2.inScope()).thenReturn(scope2);
156+
138157
compositeTracer.operationCancelled();
139-
InOrder inOrder = inOrder(child2, child1);
158+
159+
InOrder inOrder = inOrder(child1, child2, scope2, scope1);
160+
inOrder.verify(child1).inScope();
161+
inOrder.verify(child2).inScope();
140162
inOrder.verify(child2).operationCancelled();
141163
inOrder.verify(child1).operationCancelled();
164+
inOrder.verify(scope2).close();
165+
inOrder.verify(scope1).close();
142166
}
143167

144168
@Test
145169
void testOperationFailed() {
170+
ApiTracer.Scope scope1 =
171+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
172+
ApiTracer.Scope scope2 =
173+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
174+
when(child1.inScope()).thenReturn(scope1);
175+
when(child2.inScope()).thenReturn(scope2);
176+
146177
Throwable error = new RuntimeException("test error");
147178
compositeTracer.operationFailed(error);
148-
InOrder inOrder = inOrder(child2, child1);
179+
180+
InOrder inOrder = inOrder(child1, child2, scope2, scope1);
181+
inOrder.verify(child1).inScope();
182+
inOrder.verify(child2).inScope();
149183
inOrder.verify(child2).operationFailed(error);
150184
inOrder.verify(child1).operationFailed(error);
185+
inOrder.verify(scope2).close();
186+
inOrder.verify(scope1).close();
151187
}
152188

153189
@Test
@@ -176,57 +212,129 @@ void testAttemptStarted() {
176212

177213
@Test
178214
void testAttemptSucceeded() {
215+
ApiTracer.Scope scope1 =
216+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
217+
ApiTracer.Scope scope2 =
218+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
219+
when(child1.inScope()).thenReturn(scope1);
220+
when(child2.inScope()).thenReturn(scope2);
221+
179222
compositeTracer.attemptSucceeded();
180-
InOrder inOrder = inOrder(child2, child1);
223+
224+
InOrder inOrder = inOrder(child1, child2, scope2, scope1);
225+
inOrder.verify(child1).inScope();
226+
inOrder.verify(child2).inScope();
181227
inOrder.verify(child2).attemptSucceeded();
182228
inOrder.verify(child1).attemptSucceeded();
229+
inOrder.verify(scope2).close();
230+
inOrder.verify(scope1).close();
183231
}
184232

185233
@Test
186234
void testAttemptCancelled() {
235+
ApiTracer.Scope scope1 =
236+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
237+
ApiTracer.Scope scope2 =
238+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
239+
when(child1.inScope()).thenReturn(scope1);
240+
when(child2.inScope()).thenReturn(scope2);
241+
187242
compositeTracer.attemptCancelled();
188-
InOrder inOrder = inOrder(child2, child1);
243+
244+
InOrder inOrder = inOrder(child1, child2, scope2, scope1);
245+
inOrder.verify(child1).inScope();
246+
inOrder.verify(child2).inScope();
189247
inOrder.verify(child2).attemptCancelled();
190248
inOrder.verify(child1).attemptCancelled();
249+
inOrder.verify(scope2).close();
250+
inOrder.verify(scope1).close();
191251
}
192252

193253
@Test
194254
@SuppressWarnings("deprecation")
195255
void testAttemptFailedDeprecated() {
256+
ApiTracer.Scope scope1 =
257+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
258+
ApiTracer.Scope scope2 =
259+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
260+
when(child1.inScope()).thenReturn(scope1);
261+
when(child2.inScope()).thenReturn(scope2);
262+
196263
Throwable error = new RuntimeException("test error");
197264
org.threeten.bp.Duration delay = org.threeten.bp.Duration.ofSeconds(1);
198265
compositeTracer.attemptFailed(error, delay);
199-
InOrder inOrder = inOrder(child2, child1);
266+
267+
InOrder inOrder = inOrder(child1, child2, scope2, scope1);
268+
inOrder.verify(child1).inScope();
269+
inOrder.verify(child2).inScope();
200270
inOrder.verify(child2).attemptFailed(error, delay);
201271
inOrder.verify(child1).attemptFailed(error, delay);
272+
inOrder.verify(scope2).close();
273+
inOrder.verify(scope1).close();
202274
}
203275

204276
@Test
205277
void testAttemptFailedDuration() {
278+
ApiTracer.Scope scope1 =
279+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
280+
ApiTracer.Scope scope2 =
281+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
282+
when(child1.inScope()).thenReturn(scope1);
283+
when(child2.inScope()).thenReturn(scope2);
284+
206285
Throwable error = new RuntimeException("test error");
207286
java.time.Duration delay = java.time.Duration.ofSeconds(1);
208287
compositeTracer.attemptFailedDuration(error, delay);
209-
InOrder inOrder = inOrder(child2, child1);
288+
289+
InOrder inOrder = inOrder(child1, child2, scope2, scope1);
290+
inOrder.verify(child1).inScope();
291+
inOrder.verify(child2).inScope();
210292
inOrder.verify(child2).attemptFailedDuration(error, delay);
211293
inOrder.verify(child1).attemptFailedDuration(error, delay);
294+
inOrder.verify(scope2).close();
295+
inOrder.verify(scope1).close();
212296
}
213297

214298
@Test
215299
void testAttemptFailedRetriesExhausted() {
300+
ApiTracer.Scope scope1 =
301+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
302+
ApiTracer.Scope scope2 =
303+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
304+
when(child1.inScope()).thenReturn(scope1);
305+
when(child2.inScope()).thenReturn(scope2);
306+
216307
Throwable error = new RuntimeException("test error");
217308
compositeTracer.attemptFailedRetriesExhausted(error);
218-
InOrder inOrder = inOrder(child2, child1);
309+
310+
InOrder inOrder = inOrder(child1, child2, scope2, scope1);
311+
inOrder.verify(child1).inScope();
312+
inOrder.verify(child2).inScope();
219313
inOrder.verify(child2).attemptFailedRetriesExhausted(error);
220314
inOrder.verify(child1).attemptFailedRetriesExhausted(error);
315+
inOrder.verify(scope2).close();
316+
inOrder.verify(scope1).close();
221317
}
222318

223319
@Test
224320
void testAttemptPermanentFailure() {
321+
ApiTracer.Scope scope1 =
322+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
323+
ApiTracer.Scope scope2 =
324+
mock(ApiTracer.Scope.class, Mockito.withSettings().withoutAnnotations());
325+
when(child1.inScope()).thenReturn(scope1);
326+
when(child2.inScope()).thenReturn(scope2);
327+
225328
Throwable error = new RuntimeException("test error");
226329
compositeTracer.attemptPermanentFailure(error);
227-
InOrder inOrder = inOrder(child2, child1);
330+
331+
InOrder inOrder = inOrder(child1, child2, scope2, scope1);
332+
inOrder.verify(child1).inScope();
333+
inOrder.verify(child2).inScope();
228334
inOrder.verify(child2).attemptPermanentFailure(error);
229335
inOrder.verify(child1).attemptPermanentFailure(error);
336+
inOrder.verify(scope2).close();
337+
inOrder.verify(scope1).close();
230338
}
231339

232340
@Test

0 commit comments

Comments
 (0)