3535import io .grpc .ManagedChannel ;
3636import io .grpc .ManagedChannelBuilder ;
3737import io .grpc .Metadata ;
38+ import io .grpc .Metadata .Key ;
3839import io .grpc .MethodDescriptor ;
3940import io .grpc .Status ;
40- import io .grpc .StatusRuntimeException ;
4141import java .time .Duration ;
4242import java .util .List ;
4343import java .util .Optional ;
5858public class DataChannel extends ManagedChannel {
5959 private static final Logger LOGGER = LoggerFactory .getLogger (DataChannel .class );
6060
61+ private static final Metadata .Key <String > GFE_DEBUG_REQ_HEADER =
62+ Key .of ("X-Return-Encrypted-Headers" , Metadata .ASCII_STRING_MARSHALLER );
63+ private static final Metadata .Key <String > GFE_DEBUG_RESP_HEADER =
64+ Key .of ("X-Encrypted-Debug-Headers" , Metadata .ASCII_STRING_MARSHALLER );
65+
6166 private static final Duration WARM_PERIOD = Duration .ofMinutes (3 );
6267 private static final Duration MAX_JITTER = Duration .ofSeconds (10 );
6368
@@ -152,10 +157,11 @@ private void warm() {
152157 future .get ();
153158 successCount ++;
154159 } catch (ExecutionException e ) {
155- // All permenant errors are ignored and treated as a success
160+ // All permanent errors are ignored and treated as a success
156161 // The priming request for that generated the error will be dropped
157- if (e .getCause () instanceof StatusRuntimeException ) {
158- StatusRuntimeException se = (StatusRuntimeException ) e .getCause ();
162+ if (e .getCause () instanceof PingAndWarmException ) {
163+ PingAndWarmException se = (PingAndWarmException ) e .getCause ();
164+
159165 switch (se .getStatus ().getCode ()) {
160166 case INTERNAL :
161167 case PERMISSION_DENIED :
@@ -168,8 +174,15 @@ private void warm() {
168174 default :
169175 // noop
170176 }
177+ LOGGER .warn (
178+ "Failed to prime channel with request: {}, status: {}, debug response headers: {}" ,
179+ request ,
180+ se .getStatus (),
181+ Optional .ofNullable (se .getDebugHeaders ()).orElse ("<missing>" ));
182+ } else {
183+ LOGGER .warn ("Unexpected failure priming channel with request: {}" , request , e .getCause ());
171184 }
172- LOGGER . warn ( "Failed to prime channel with request: {}" , request , e . getCause ());
185+
173186 failures ++;
174187 } catch (InterruptedException e ) {
175188 throw new RuntimeException ("Interrupted while priming channel with request: " + request , e );
@@ -182,7 +195,9 @@ private void warm() {
182195
183196 private ListenableFuture <PingAndWarmResponse > sendPingAndWarm (PrimingKey primingKey ) {
184197 Metadata metadata = primingKey .composeMetadata ();
198+ metadata .put (GFE_DEBUG_REQ_HEADER , "gfe_response_only" );
185199 PingAndWarmRequest request = primingKey .composeProto ();
200+ request = request .toBuilder ().setName (request .getName ()).build ();
186201
187202 CallLabels callLabels = CallLabels .create (BigtableGrpc .getPingAndWarmMethod (), metadata );
188203 Tracer tracer = new Tracer (metrics , callLabels );
@@ -199,6 +214,8 @@ private ListenableFuture<PingAndWarmResponse> sendPingAndWarm(PrimingKey priming
199214 SettableFuture <PingAndWarmResponse > f = SettableFuture .create ();
200215 call .start (
201216 new Listener <>() {
217+ String debugHeaders = null ;
218+
202219 @ Override
203220 public void onMessage (PingAndWarmResponse response ) {
204221 if (!f .set (response )) {
@@ -207,14 +224,22 @@ public void onMessage(PingAndWarmResponse response) {
207224 }
208225 }
209226
227+ @ Override
228+ public void onHeaders (Metadata headers ) {
229+ debugHeaders = headers .get (GFE_DEBUG_RESP_HEADER );
230+ }
231+
210232 @ Override
211233 public void onClose (Status status , Metadata trailers ) {
212234 tracer .onCallFinished (status );
213235
214236 if (status .isOk ()) {
215- f .setException (new IllegalStateException ("PingAndWarm was missing a response" ));
237+ f .setException (
238+ new PingAndWarmException (
239+ "PingAndWarm was missing a response" , debugHeaders , trailers , status ));
216240 } else {
217- f .setException (status .asRuntimeException ());
241+ f .setException (
242+ new PingAndWarmException ("PingAndWarm failed" , debugHeaders , trailers , status ));
218243 }
219244 }
220245 },
@@ -226,6 +251,33 @@ public void onClose(Status status, Metadata trailers) {
226251 return f ;
227252 }
228253
254+ static class PingAndWarmException extends RuntimeException {
255+
256+ private final String debugHeaders ;
257+ private final Metadata trailers ;
258+ private final Status status ;
259+
260+ public PingAndWarmException (
261+ String message , String debugHeaders , Metadata trailers , Status status ) {
262+ super (String .format ("PingAndWarm failed, status: " + status ));
263+ this .debugHeaders = debugHeaders ;
264+ this .trailers = trailers ;
265+ this .status = status ;
266+ }
267+
268+ public String getDebugHeaders () {
269+ return debugHeaders ;
270+ }
271+
272+ public Metadata getTrailers () {
273+ return trailers ;
274+ }
275+
276+ public Status getStatus () {
277+ return status ;
278+ }
279+ }
280+
229281 @ Override
230282 public ManagedChannel shutdown () {
231283 final boolean closing ;
0 commit comments