2525import static com .google .cloud .spanner .spi .v1 .SpannerRpcViews .SPANNER_GFE_LATENCY ;
2626
2727import com .google .api .gax .tracing .ApiTracer ;
28- import com .google .cloud .spanner .*;
28+ import com .google .cloud .spanner .BuiltInMetricsConstant ;
29+ import com .google .cloud .spanner .CompositeTracer ;
30+ import com .google .cloud .spanner .SpannerExceptionFactory ;
31+ import com .google .cloud .spanner .SpannerRpcMetrics ;
32+ import com .google .cloud .spanner .XGoogSpannerRequestId ;
2933import com .google .common .cache .Cache ;
3034import com .google .common .cache .CacheBuilder ;
3135import com .google .spanner .admin .database .v1 .DatabaseName ;
32- import io .grpc .*;
36+ import io .grpc .CallOptions ;
37+ import io .grpc .Channel ;
38+ import io .grpc .ClientCall ;
39+ import io .grpc .ClientInterceptor ;
3340import io .grpc .ForwardingClientCall .SimpleForwardingClientCall ;
3441import io .grpc .ForwardingClientCallListener .SimpleForwardingClientCallListener ;
42+ import io .grpc .Metadata ;
43+ import io .grpc .MethodDescriptor ;
44+ import io .grpc .Status ;
3545import io .grpc .alts .AltsContextUtil ;
3646import io .opencensus .stats .MeasureMap ;
3747import io .opencensus .stats .Stats ;
5262import java .util .logging .Logger ;
5363import java .util .regex .Matcher ;
5464import java .util .regex .Pattern ;
65+ import javax .annotation .Nullable ;
5566
5667/**
5768 * Intercepts all gRPC calls to extract server-timing header. Captures GFE Latency and GFE Header
@@ -89,8 +100,6 @@ class HeaderInterceptor implements ClientInterceptor {
89100 private static final Logger LOGGER = Logger .getLogger (HeaderInterceptor .class .getName ());
90101 private static final Level LEVEL = Level .INFO ;
91102 private final SpannerRpcMetrics spannerRpcMetrics ;
92- private Float gfeLatency ;
93- private Float afeLatency ;
94103
95104 HeaderInterceptor (SpannerRpcMetrics spannerRpcMetrics ) {
96105 this .spannerRpcMetrics = spannerRpcMetrics ;
@@ -118,48 +127,65 @@ public void start(Listener<RespT> responseListener, Metadata headers) {
118127
119128 super .start (
120129 new SimpleForwardingClientCallListener <RespT >(responseListener ) {
130+ private Float gfeLatency ;
131+ private Float afeLatency ;
132+
121133 @ Override
122134 public void onHeaders (Metadata metadata ) {
123- recordFirstResponseLatency (requestId , startedAtNanos , firstResponseRecorded );
124- String serverTiming = metadata .get (SERVER_TIMING_HEADER_KEY );
125135 try {
126- // Get gfe and afe Latency value
127- Map <String , Float > serverTimingMetrics = parseServerTimingHeader (serverTiming );
128- gfeLatency = serverTimingMetrics .get (GFE_TIMING_HEADER );
129- afeLatency = serverTimingMetrics .get (AFE_TIMING_HEADER );
130- } catch (NumberFormatException e ) {
131- LOGGER .log (LEVEL , "Invalid server-timing object in header: {}" , serverTiming );
136+ recordFirstResponseLatency (requestId , startedAtNanos , firstResponseRecorded );
137+ String serverTiming = metadata .get (SERVER_TIMING_HEADER_KEY );
138+ try {
139+ // Get gfe and afe Latency value
140+ Map <String , Float > serverTimingMetrics =
141+ parseServerTimingHeader (serverTiming );
142+ gfeLatency = serverTimingMetrics .get (GFE_TIMING_HEADER );
143+ afeLatency = serverTimingMetrics .get (AFE_TIMING_HEADER );
144+ } catch (NumberFormatException e ) {
145+ LOGGER .log (
146+ LEVEL , "Invalid server-timing object in header: {0}" , serverTiming );
147+ }
148+ } catch (Throwable throwable ) {
149+ LOGGER .log (
150+ Level .WARNING , "Error processing headers in HeaderInterceptor" , throwable );
151+ } finally {
152+ super .onHeaders (metadata );
132153 }
133-
134- super .onHeaders (metadata );
135154 }
136155
137156 @ Override
138157 public void onClose (Status status , Metadata trailers ) {
139- // Record Built-in Metrics
140- boolean isDirectPathUsed = AltsContextUtil .check (getAttributes ());
141- boolean isAfeEnabled = GapicSpannerRpc .isEnableAFEServerTiming ();
142- recordSpan (span , requestId );
143- recordCustomMetrics (tagContext , attributes , isDirectPathUsed );
144- Map <String , String > builtInMetricsAttributes = new HashMap <>();
145158 try {
146- builtInMetricsAttributes =
147- new HashMap <>(getBuiltInMetricAttributes (key , databaseName ));
148- } catch (ExecutionException e ) {
149- LOGGER .log (
150- LEVEL , "Unable to get built-in metric attributes {}" , e .getMessage ());
159+ // Record Built-in Metrics
160+ boolean isDirectPathUsed = AltsContextUtil .check (getAttributes ());
161+ boolean isAfeEnabled = GapicSpannerRpc .isEnableAFEServerTiming ();
162+ recordSpan (span , requestId , gfeLatency , afeLatency );
163+ recordCustomMetrics (tagContext , attributes , isDirectPathUsed , gfeLatency );
164+ Map <String , String > builtInMetricsAttributes = new HashMap <>();
165+ try {
166+ builtInMetricsAttributes =
167+ new HashMap <>(getBuiltInMetricAttributes (key , databaseName ));
168+ } catch (ExecutionException e ) {
169+ LOGGER .log (
170+ LEVEL , "Unable to get built-in metric attributes {0}" , e .getMessage ());
171+ }
172+ if (status .isOk ()) {
173+ recordFirstResponseLatency (requestId , startedAtNanos , firstResponseRecorded );
174+ }
175+ recordBuiltInMetrics (
176+ compositeTracer ,
177+ builtInMetricsAttributes ,
178+ requestId ,
179+ isDirectPathUsed ,
180+ isAfeEnabled ,
181+ gfeLatency ,
182+ afeLatency );
183+ } catch (Throwable throwable ) {
184+ LOGGER .log (Level .WARNING , "Error recording metrics in onClose" , throwable );
185+ } finally {
186+ RequestIdTargetTracker .remove (requestId );
187+ super .onClose (status , trailers );
151188 }
152- if (status .isOk ()) {
153- recordFirstResponseLatency (requestId , startedAtNanos , firstResponseRecorded );
154- }
155- recordBuiltInMetrics (
156- compositeTracer ,
157- builtInMetricsAttributes ,
158- requestId ,
159- isDirectPathUsed ,
160- isAfeEnabled );
161- RequestIdTargetTracker .remove (requestId );
162- super .onClose (status , trailers );
163189 }
164190 },
165191 headers );
@@ -172,11 +198,14 @@ public void onClose(Status status, Metadata trailers) {
172198 }
173199
174200 private void recordCustomMetrics (
175- TagContext tagContext , Attributes attributes , Boolean isDirectPathUsed ) {
201+ TagContext tagContext ,
202+ Attributes attributes ,
203+ Boolean isDirectPathUsed ,
204+ @ Nullable Float gfeLatency ) {
176205 // Record OpenCensus and Custom OpenTelemetry Metrics
177206 MeasureMap measureMap = STATS_RECORDER .newMeasureMap ();
178207
179- if (!isDirectPathUsed ) {
208+ if (!Boolean . TRUE . equals ( isDirectPathUsed ) ) {
180209 if (gfeLatency != null ) {
181210 long gfeVal = gfeLatency .longValue ();
182211 measureMap .put (SPANNER_GFE_LATENCY , gfeVal );
@@ -191,31 +220,45 @@ private void recordCustomMetrics(
191220 measureMap .record (tagContext );
192221 }
193222
194- private void recordSpan (Span span , String requestId ) {
223+ private void recordSpan (
224+ @ Nullable Span span ,
225+ @ Nullable String requestId ,
226+ @ Nullable Float gfeLatency ,
227+ @ Nullable Float afeLatency ) {
195228 if (span != null ) {
196229 if (gfeLatency != null ) {
197230 span .setAttribute ("gfe_latency" , gfeLatency .toString ());
198231 }
199232 if (afeLatency != null ) {
200233 span .setAttribute ("afe_latency" , afeLatency .toString ());
201234 }
202- span .setAttribute (XGoogSpannerRequestId .REQUEST_ID_HEADER_NAME , requestId );
235+ if (requestId != null ) {
236+ span .setAttribute (XGoogSpannerRequestId .REQUEST_ID_HEADER_NAME , requestId );
237+ }
203238 }
204239 }
205240
206241 private void recordBuiltInMetrics (
207- CompositeTracer compositeTracer ,
242+ @ Nullable CompositeTracer compositeTracer ,
208243 Map <String , String > builtInMetricsAttributes ,
209- String requestId ,
244+ @ Nullable String requestId ,
210245 Boolean isDirectPathUsed ,
211- Boolean isAfeEnabled ) {
246+ Boolean isAfeEnabled ,
247+ @ Nullable Float gfeLatency ,
248+ @ Nullable Float afeLatency ) {
212249 if (compositeTracer != null ) {
213- builtInMetricsAttributes .put (BuiltInMetricsConstant .REQUEST_ID_KEY .getKey (), requestId );
250+ if (requestId != null ) {
251+ builtInMetricsAttributes .put (BuiltInMetricsConstant .REQUEST_ID_KEY .getKey (), requestId );
252+ }
214253 builtInMetricsAttributes .put (
215- BuiltInMetricsConstant .DIRECT_PATH_USED_KEY .getKey (), Boolean .toString (isDirectPathUsed ));
254+ BuiltInMetricsConstant .DIRECT_PATH_USED_KEY .getKey (),
255+ Boolean .toString (Boolean .TRUE .equals (isDirectPathUsed )));
216256 compositeTracer .addAttributes (builtInMetricsAttributes );
217257 compositeTracer .recordServerTimingHeaderMetrics (
218- gfeLatency , afeLatency , isDirectPathUsed , isAfeEnabled );
258+ gfeLatency ,
259+ afeLatency ,
260+ Boolean .TRUE .equals (isDirectPathUsed ),
261+ Boolean .TRUE .equals (isAfeEnabled ));
219262 }
220263 }
221264
0 commit comments