1616
1717package com .google .cloud .spanner ;
1818
19+ import com .google .api .gax .rpc .ApiException ;
20+ import com .google .api .gax .rpc .StatusCode ;
21+ import com .google .api .gax .tracing .ApiTracer ;
1922import com .google .api .gax .tracing .MethodName ;
2023import com .google .api .gax .tracing .MetricsTracer ;
2124import java .util .HashMap ;
2225import java .util .Map ;
26+ import java .util .concurrent .CancellationException ;
27+ import javax .annotation .Nullable ;
2328
2429/**
2530 * Implements built-in metrics tracer.
2631 *
2732 * <p>This class extends the {@link MetricsTracer} which computes generic metrics that can be
2833 * observed in the lifecycle of an RPC operation.
2934 */
30- class BuiltInMetricsTracer extends MetricsTracer {
35+ class BuiltInMetricsTracer extends MetricsTracer implements ApiTracer {
3136
3237 private final BuiltInMetricsRecorder builtInOpenTelemetryMetricsRecorder ;
3338 // These are RPC specific attributes and pertain to a specific API Trace
3439 private final Map <String , String > attributes = new HashMap <>();
3540
41+ private Long gfeLatency = null ;
42+
3643 BuiltInMetricsTracer (
3744 MethodName methodName , BuiltInMetricsRecorder builtInOpenTelemetryMetricsRecorder ) {
3845 super (methodName , builtInOpenTelemetryMetricsRecorder );
3946 this .builtInOpenTelemetryMetricsRecorder = builtInOpenTelemetryMetricsRecorder ;
4047 this .attributes .put (METHOD_ATTRIBUTE , methodName .toString ());
4148 }
4249
43- void recordGFELatency (double gfeLatency ) {
44- this .builtInOpenTelemetryMetricsRecorder .recordGFELatency (gfeLatency , this .attributes );
50+ /**
51+ * Adds an annotation that the attempt succeeded. Successful attempt add "OK" value to the status
52+ * attribute key.
53+ */
54+ @ Override
55+ public void attemptSucceeded () {
56+ super .attemptSucceeded ();
57+ if (gfeLatency != null ) {
58+ attributes .put (STATUS_ATTRIBUTE , StatusCode .Code .OK .toString ());
59+ builtInOpenTelemetryMetricsRecorder .recordGFELatency (gfeLatency , attributes );
60+ }
61+ }
62+
63+ /**
64+ * Add an annotation that the attempt was cancelled by the user. Cancelled attempt add "CANCELLED"
65+ * to the status attribute key.
66+ */
67+ @ Override
68+ public void attemptCancelled () {
69+ super .attemptCancelled ();
70+ if (gfeLatency != null ) {
71+ attributes .put (STATUS_ATTRIBUTE , StatusCode .Code .CANCELLED .toString ());
72+ builtInOpenTelemetryMetricsRecorder .recordGFELatency (gfeLatency , attributes );
73+ }
74+ }
75+
76+ /**
77+ * Adds an annotation that the attempt failed, but another attempt will be made after the delay.
78+ *
79+ * @param error the error that caused the attempt to fail.
80+ * @param delay the amount of time to wait before the next attempt will start.
81+ * <p>Failed attempt extracts the error from the throwable and adds it to the status attribute
82+ * key.
83+ */
84+ @ Override
85+ public void attemptFailedDuration (Throwable error , java .time .Duration delay ) {
86+ super .attemptFailedDuration (error , delay );
87+ if (gfeLatency != null ) {
88+ attributes .put (STATUS_ATTRIBUTE , extractStatus (error ));
89+ builtInOpenTelemetryMetricsRecorder .recordGFELatency (gfeLatency , attributes );
90+ }
91+ }
92+
93+ /**
94+ * Adds an annotation that the attempt failed and that no further attempts will be made because
95+ * retry limits have been reached. This extracts the error from the throwable and adds it to the
96+ * status attribute key.
97+ *
98+ * @param error the last error received before retries were exhausted.
99+ */
100+ @ Override
101+ public void attemptFailedRetriesExhausted (Throwable error ) {
102+ super .attemptFailedRetriesExhausted (error );
103+ if (gfeLatency != null ) {
104+ attributes .put (STATUS_ATTRIBUTE , extractStatus (error ));
105+ builtInOpenTelemetryMetricsRecorder .recordGFELatency (gfeLatency , attributes );
106+ }
107+ }
108+
109+ /**
110+ * Adds an annotation that the attempt failed and that no further attempts will be made because
111+ * the last error was not retryable. This extracts the error from the throwable and adds it to the
112+ * status attribute key.
113+ *
114+ * @param error the error that caused the final attempt to fail.
115+ */
116+ @ Override
117+ public void attemptPermanentFailure (Throwable error ) {
118+ super .attemptPermanentFailure (error );
119+ if (gfeLatency != null ) {
120+ attributes .put (STATUS_ATTRIBUTE , extractStatus (error ));
121+ builtInOpenTelemetryMetricsRecorder .recordGFELatency (gfeLatency , attributes );
122+ }
123+ }
124+
125+ void recordGFELatency (Long gfeLatency ) {
126+ this .gfeLatency = gfeLatency ;
45127 }
46128
47129 @ Override
@@ -55,4 +137,20 @@ public void addAttributes(String key, String value) {
55137 super .addAttributes (key , value );
56138 this .attributes .put (key , value );
57139 }
140+
141+ private static String extractStatus (@ Nullable Throwable error ) {
142+ final String statusString ;
143+
144+ if (error == null ) {
145+ return StatusCode .Code .OK .toString ();
146+ } else if (error instanceof CancellationException ) {
147+ statusString = StatusCode .Code .CANCELLED .toString ();
148+ } else if (error instanceof ApiException ) {
149+ statusString = ((ApiException ) error ).getStatusCode ().getCode ().toString ();
150+ } else {
151+ statusString = StatusCode .Code .UNKNOWN .toString ();
152+ }
153+
154+ return statusString ;
155+ }
58156}
0 commit comments