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,63 @@ 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 = parseServerTimingHeader (serverTiming );
141+ gfeLatency = serverTimingMetrics .get (GFE_TIMING_HEADER );
142+ afeLatency = serverTimingMetrics .get (AFE_TIMING_HEADER );
143+ } catch (NumberFormatException e ) {
144+ LOGGER .log (LEVEL , "Invalid server-timing object in header: {0}" , serverTiming );
145+ }
146+ } catch (Throwable throwable ) {
147+ LOGGER .log (
148+ Level .WARNING , "Error processing headers in HeaderInterceptor" , throwable );
149+ } finally {
150+ super .onHeaders (metadata );
132151 }
133-
134- super .onHeaders (metadata );
135152 }
136153
137154 @ Override
138155 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 <>();
145156 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 ());
157+ // Record Built-in Metrics
158+ boolean isDirectPathUsed = AltsContextUtil .check (getAttributes ());
159+ boolean isAfeEnabled = GapicSpannerRpc .isEnableAFEServerTiming ();
160+ recordSpan (span , requestId , gfeLatency , afeLatency );
161+ recordCustomMetrics (tagContext , attributes , isDirectPathUsed , gfeLatency );
162+ Map <String , String > builtInMetricsAttributes = new HashMap <>();
163+ try {
164+ builtInMetricsAttributes =
165+ new HashMap <>(getBuiltInMetricAttributes (key , databaseName ));
166+ } catch (ExecutionException e ) {
167+ LOGGER .log (
168+ LEVEL , "Unable to get built-in metric attributes {0}" , e .getMessage ());
169+ }
170+ if (status .isOk ()) {
171+ recordFirstResponseLatency (requestId , startedAtNanos , firstResponseRecorded );
172+ }
173+ recordBuiltInMetrics (
174+ compositeTracer ,
175+ builtInMetricsAttributes ,
176+ requestId ,
177+ isDirectPathUsed ,
178+ isAfeEnabled ,
179+ gfeLatency ,
180+ afeLatency );
181+ } catch (Throwable throwable ) {
182+ LOGGER .log (Level .WARNING , "Error recording metrics in onClose" , throwable );
183+ } finally {
184+ RequestIdTargetTracker .remove (requestId );
185+ super .onClose (status , trailers );
151186 }
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 );
163187 }
164188 },
165189 headers );
@@ -172,11 +196,14 @@ public void onClose(Status status, Metadata trailers) {
172196 }
173197
174198 private void recordCustomMetrics (
175- TagContext tagContext , Attributes attributes , Boolean isDirectPathUsed ) {
199+ TagContext tagContext ,
200+ Attributes attributes ,
201+ Boolean isDirectPathUsed ,
202+ @ Nullable Float gfeLatency ) {
176203 // Record OpenCensus and Custom OpenTelemetry Metrics
177204 MeasureMap measureMap = STATS_RECORDER .newMeasureMap ();
178205
179- if (!isDirectPathUsed ) {
206+ if (!Boolean . TRUE . equals ( isDirectPathUsed ) ) {
180207 if (gfeLatency != null ) {
181208 long gfeVal = gfeLatency .longValue ();
182209 measureMap .put (SPANNER_GFE_LATENCY , gfeVal );
@@ -191,31 +218,45 @@ private void recordCustomMetrics(
191218 measureMap .record (tagContext );
192219 }
193220
194- private void recordSpan (Span span , String requestId ) {
221+ private void recordSpan (
222+ @ Nullable Span span ,
223+ @ Nullable String requestId ,
224+ @ Nullable Float gfeLatency ,
225+ @ Nullable Float afeLatency ) {
195226 if (span != null ) {
196227 if (gfeLatency != null ) {
197228 span .setAttribute ("gfe_latency" , gfeLatency .toString ());
198229 }
199230 if (afeLatency != null ) {
200231 span .setAttribute ("afe_latency" , afeLatency .toString ());
201232 }
202- span .setAttribute (XGoogSpannerRequestId .REQUEST_ID_HEADER_NAME , requestId );
233+ if (requestId != null ) {
234+ span .setAttribute (XGoogSpannerRequestId .REQUEST_ID_HEADER_NAME , requestId );
235+ }
203236 }
204237 }
205238
206239 private void recordBuiltInMetrics (
207- CompositeTracer compositeTracer ,
240+ @ Nullable CompositeTracer compositeTracer ,
208241 Map <String , String > builtInMetricsAttributes ,
209- String requestId ,
242+ @ Nullable String requestId ,
210243 Boolean isDirectPathUsed ,
211- Boolean isAfeEnabled ) {
244+ Boolean isAfeEnabled ,
245+ @ Nullable Float gfeLatency ,
246+ @ Nullable Float afeLatency ) {
212247 if (compositeTracer != null ) {
213- builtInMetricsAttributes .put (BuiltInMetricsConstant .REQUEST_ID_KEY .getKey (), requestId );
248+ if (requestId != null ) {
249+ builtInMetricsAttributes .put (BuiltInMetricsConstant .REQUEST_ID_KEY .getKey (), requestId );
250+ }
214251 builtInMetricsAttributes .put (
215- BuiltInMetricsConstant .DIRECT_PATH_USED_KEY .getKey (), Boolean .toString (isDirectPathUsed ));
252+ BuiltInMetricsConstant .DIRECT_PATH_USED_KEY .getKey (),
253+ Boolean .toString (Boolean .TRUE .equals (isDirectPathUsed )));
216254 compositeTracer .addAttributes (builtInMetricsAttributes );
217255 compositeTracer .recordServerTimingHeaderMetrics (
218- gfeLatency , afeLatency , isDirectPathUsed , isAfeEnabled );
256+ gfeLatency ,
257+ afeLatency ,
258+ Boolean .TRUE .equals (isDirectPathUsed ),
259+ Boolean .TRUE .equals (isAfeEnabled ));
219260 }
220261 }
221262
0 commit comments