@@ -129,8 +129,9 @@ public final ClientStream newStream(
129
129
if (state .shutdownStatus != null ) {
130
130
return new FailingClientStream (state .shutdownStatus , tracers );
131
131
}
132
+ PickResult pickResult = null ;
132
133
if (state .lastPicker != null ) {
133
- PickResult pickResult = state .lastPicker .pickSubchannel (args );
134
+ pickResult = state .lastPicker .pickSubchannel (args );
134
135
callOptions = args .getCallOptions ();
135
136
// User code provided authority takes precedence over the LB provided one.
136
137
if (callOptions .getAuthority () == null
@@ -156,7 +157,7 @@ public final ClientStream newStream(
156
157
synchronized (lock ) {
157
158
PickerState newerState = pickerState ;
158
159
if (state == newerState ) {
159
- return createPendingStream (args , tracers );
160
+ return createPendingStream (args , tracers , pickResult );
160
161
}
161
162
state = newerState ;
162
163
}
@@ -171,9 +172,12 @@ public final ClientStream newStream(
171
172
* schedule tasks on syncContext.
172
173
*/
173
174
@ GuardedBy ("lock" )
174
- private PendingStream createPendingStream (
175
- PickSubchannelArgs args , ClientStreamTracer [] tracers ) {
175
+ private PendingStream createPendingStream (PickSubchannelArgs args , ClientStreamTracer [] tracers ,
176
+ PickResult pickResult ) {
176
177
PendingStream pendingStream = new PendingStream (args , tracers );
178
+ if (args .getCallOptions ().isWaitForReady () && pickResult != null && pickResult .hasResult ()) {
179
+ pendingStream .lastPickStatus = pickResult .getStatus ();
180
+ }
177
181
pendingStreams .add (pendingStream );
178
182
if (getPendingStreamsCount () == 1 ) {
179
183
syncContext .executeLater (reportTransportInUse );
@@ -293,6 +297,9 @@ final void reprocess(@Nullable SubchannelPicker picker) {
293
297
for (final PendingStream stream : toProcess ) {
294
298
PickResult pickResult = picker .pickSubchannel (stream .args );
295
299
CallOptions callOptions = stream .args .getCallOptions ();
300
+ if (callOptions .isWaitForReady () && pickResult .hasResult ()) {
301
+ stream .lastPickStatus = pickResult .getStatus ();
302
+ }
296
303
final ClientTransport transport = GrpcUtil .getTransportFromPickResult (pickResult ,
297
304
callOptions .isWaitForReady ());
298
305
if (transport != null ) {
@@ -349,6 +356,7 @@ private class PendingStream extends DelayedStream {
349
356
private final PickSubchannelArgs args ;
350
357
private final Context context = Context .current ();
351
358
private final ClientStreamTracer [] tracers ;
359
+ private volatile Status lastPickStatus ;
352
360
353
361
private PendingStream (PickSubchannelArgs args , ClientStreamTracer [] tracers ) {
354
362
this .args = args ;
@@ -405,6 +413,10 @@ protected void onEarlyCancellation(Status reason) {
405
413
public void appendTimeoutInsight (InsightBuilder insight ) {
406
414
if (args .getCallOptions ().isWaitForReady ()) {
407
415
insight .append ("wait_for_ready" );
416
+ Status status = lastPickStatus ;
417
+ if (status != null && !status .isOk ()) {
418
+ insight .appendKeyValue ("Last Pick Failure" , status );
419
+ }
408
420
}
409
421
super .appendTimeoutInsight (insight );
410
422
}
0 commit comments