2424import static org .junit .Assert .assertThrows ;
2525import static org .junit .Assert .assertTrue ;
2626import static org .junit .Assert .fail ;
27+ import static org .junit .Assume .assumeFalse ;
28+ import static org .junit .Assume .assumeTrue ;
2729
2830import com .google .api .gax .longrunning .OperationTimedPollAlgorithm ;
2931import com .google .api .gax .retrying .RetrySettings ;
3032import com .google .api .gax .tracing .ApiTracerFactory ;
31- import com .google .api .gax .tracing .MetricsTracerFactory ;
32- import com .google .api .gax .tracing .OpenTelemetryMetricsRecorder ;
3333import com .google .cloud .NoCredentials ;
3434import com .google .cloud .spanner .MockSpannerServiceImpl .SimulatedExecutionTime ;
3535import com .google .cloud .spanner .MockSpannerServiceImpl .StatementResult ;
5050import io .opentelemetry .sdk .metrics .data .MetricData ;
5151import io .opentelemetry .sdk .testing .exporter .InMemoryMetricReader ;
5252import java .io .IOException ;
53+ import java .lang .reflect .Field ;
5354import java .net .InetSocketAddress ;
5455import java .time .Duration ;
5556import java .util .Collection ;
6566
6667@ RunWith (JUnit4 .class )
6768public class OpenTelemetryBuiltInMetricsTracerTest extends AbstractNettyMockServerTest {
68-
6969 private static final Statement SELECT_RANDOM = Statement .of ("SELECT * FROM random" );
70-
7170 private static final Statement UPDATE_RANDOM = Statement .of ("UPDATE random SET foo=1 WHERE id=1" );
7271 private static InMemoryMetricReader metricReader ;
73-
74- private static OpenTelemetry openTelemetry ;
75-
76- private static Map <String , String > attributes ;
77-
78- private static Attributes expectedCommonBaseAttributes ;
79- private static Attributes expectedCommonRequestAttributes ;
80- private static ApiTracerFactory metricsTracerFactory ;
72+ private static Map <String , String > attributes =
73+ BuiltInMetricsProvider .INSTANCE .createClientAttributes ();
74+ private static Attributes expectedCommonBaseAttributes =
75+ Attributes .builder ()
76+ .put (BuiltInMetricsConstant .CLIENT_NAME_KEY , "spanner-java/" )
77+ .put (BuiltInMetricsConstant .CLIENT_UID_KEY , attributes .get ("client_uid" ))
78+ .put (BuiltInMetricsConstant .INSTANCE_ID_KEY , "i" )
79+ .put (BuiltInMetricsConstant .DATABASE_KEY , "d" )
80+ .put (BuiltInMetricsConstant .DIRECT_PATH_ENABLED_KEY , "false" )
81+ .build ();;
82+ private static Attributes expectedCommonRequestAttributes =
83+ Attributes .builder ().put (BuiltInMetricsConstant .DIRECT_PATH_USED_KEY , "false" ).build ();;
8184
8285 private static final long MIN_LATENCY = 0 ;
8386
8487 private DatabaseClient client ;
8588
86- @ BeforeClass
87- public static void setup () {
89+ public ApiTracerFactory createMetricsTracerFactory () {
8890 metricReader = InMemoryMetricReader .create ();
8991
90- BuiltInMetricsProvider provider = BuiltInMetricsProvider .INSTANCE ;
91-
9292 SdkMeterProviderBuilder meterProvider =
9393 SdkMeterProvider .builder ().registerMetricReader (metricReader );
94-
9594 BuiltInMetricsConstant .getAllViews ().forEach (meterProvider ::registerView );
95+ OpenTelemetry openTelemetry =
96+ OpenTelemetrySdk .builder ().setMeterProvider (meterProvider .build ()).build ();
9697
97- String client_name = "spanner-java/" ;
98- openTelemetry = OpenTelemetrySdk .builder ().setMeterProvider (meterProvider .build ()).build ();
99- attributes = provider .createClientAttributes ();
100-
101- expectedCommonBaseAttributes =
102- Attributes .builder ()
103- .put (BuiltInMetricsConstant .CLIENT_NAME_KEY , client_name )
104- .put (BuiltInMetricsConstant .CLIENT_UID_KEY , attributes .get ("client_uid" ))
105- .put (BuiltInMetricsConstant .INSTANCE_ID_KEY , "i" )
106- .put (BuiltInMetricsConstant .DATABASE_KEY , "d" )
107- .put (BuiltInMetricsConstant .DIRECT_PATH_ENABLED_KEY , "false" )
108- .build ();
109-
110- expectedCommonRequestAttributes =
111- Attributes .builder ().put (BuiltInMetricsConstant .DIRECT_PATH_USED_KEY , "false" ).build ();
112- metricsTracerFactory =
113- new BuiltInMetricsTracerFactory (
114- new BuiltInMetricsRecorder (openTelemetry , BuiltInMetricsConstant .METER_NAME ),
115- attributes );
98+ return new BuiltInMetricsTracerFactory (
99+ new BuiltInMetricsRecorder (openTelemetry , BuiltInMetricsConstant .METER_NAME ), attributes );
116100 }
117101
118102 @ BeforeClass
@@ -123,9 +107,9 @@ public static void setupResults() {
123107 }
124108
125109 @ After
126- public void clearRequests () {
110+ public void clearRequests () throws IOException {
127111 mockSpanner .clearRequests ();
128- metricReader .forceFlush ();
112+ metricReader .close ();
129113 }
130114
131115 @ Override
@@ -159,7 +143,7 @@ public void createSpannerInstance() {
159143 // Setting this to false so that Spanner Options does not register Metrics Tracer
160144 // factory again.
161145 .setBuiltInMetricsEnabled (false )
162- .setApiTracerFactory (metricsTracerFactory )
146+ .setApiTracerFactory (createMetricsTracerFactory () )
163147 .build ()
164148 .getService ();
165149 client = spanner .getDatabaseClient (DatabaseId .of ("test-project" , "i" , "d" ));
@@ -209,11 +193,92 @@ public void testMetricsSingleUseQuery() {
209193 long gfeLatencyValue = getAggregatedValue (gfeLatencyMetricData , expectedAttributes );
210194 assertEquals (fakeServerTiming .get (), gfeLatencyValue , 0 );
211195
196+ assertFalse (
197+ checkIfMetricExists (metricReader , BuiltInMetricsConstant .GFE_CONNECTIVITY_ERROR_NAME ));
212198 assertFalse (checkIfMetricExists (metricReader , BuiltInMetricsConstant .AFE_LATENCIES_NAME ));
213199 assertFalse (
214200 checkIfMetricExists (metricReader , BuiltInMetricsConstant .AFE_CONNECTIVITY_ERROR_NAME ));
215201 }
216202
203+ private boolean isJava8 () {
204+ return JavaVersionUtil .getJavaMajorVersion () == 8 ;
205+ }
206+
207+ private boolean isWindows () {
208+ return System .getProperty ("os.name" ).toLowerCase ().contains ("windows" );
209+ }
210+
211+ @ Test
212+ public void testMetricsSingleUseQueryWithAfeEnabled () throws Exception {
213+ assumeTrue (isJava8 () && !isWindows ());
214+ assumeFalse (System .getenv ().containsKey ("SPANNER_DISABLE_AFE_SERVER_TIMING" ));
215+
216+ Class <?> classOfMap = System .getenv ().getClass ();
217+ Field field = classOfMap .getDeclaredField ("m" );
218+ field .setAccessible (true );
219+ Map <String , String > writeableEnvironmentVariables =
220+ (Map <String , String >) field .get (System .getenv ());
221+
222+ try {
223+ writeableEnvironmentVariables .put ("SPANNER_DISABLE_AFE_SERVER_TIMING" , "true" );
224+
225+ Stopwatch stopwatch = Stopwatch .createStarted ();
226+ try (ResultSet resultSet = client .singleUse ().executeQuery (SELECT_RANDOM )) {
227+ assertTrue (resultSet .next ());
228+ assertFalse (resultSet .next ());
229+ }
230+
231+ long elapsed = stopwatch .elapsed (TimeUnit .MILLISECONDS );
232+ Attributes expectedAttributes =
233+ expectedCommonBaseAttributes
234+ .toBuilder ()
235+ .putAll (expectedCommonRequestAttributes )
236+ .put (BuiltInMetricsConstant .STATUS_KEY , "OK" )
237+ .put (BuiltInMetricsConstant .METHOD_KEY , "Spanner.ExecuteStreamingSql" )
238+ .build ();
239+
240+ MetricData operationLatencyMetricData =
241+ getMetricData (metricReader , BuiltInMetricsConstant .OPERATION_LATENCIES_NAME );
242+ assertNotNull (operationLatencyMetricData );
243+ long operationLatencyValue =
244+ getAggregatedValue (operationLatencyMetricData , expectedAttributes );
245+ assertThat (operationLatencyValue ).isIn (Range .closed (MIN_LATENCY , elapsed ));
246+
247+ MetricData attemptLatencyMetricData =
248+ getMetricData (metricReader , BuiltInMetricsConstant .ATTEMPT_LATENCIES_NAME );
249+ assertNotNull (attemptLatencyMetricData );
250+ long attemptLatencyValue = getAggregatedValue (attemptLatencyMetricData , expectedAttributes );
251+ assertThat (attemptLatencyValue ).isIn (Range .closed (MIN_LATENCY , elapsed ));
252+
253+ MetricData operationCountMetricData =
254+ getMetricData (metricReader , BuiltInMetricsConstant .OPERATION_COUNT_NAME );
255+ assertNotNull (operationCountMetricData );
256+ assertThat (getAggregatedValue (operationCountMetricData , expectedAttributes )).isEqualTo (1 );
257+
258+ MetricData attemptCountMetricData =
259+ getMetricData (metricReader , BuiltInMetricsConstant .ATTEMPT_COUNT_NAME );
260+ assertNotNull (attemptCountMetricData );
261+ assertThat (getAggregatedValue (attemptCountMetricData , expectedAttributes )).isEqualTo (1 );
262+
263+ MetricData gfeLatencyMetricData =
264+ getMetricData (metricReader , BuiltInMetricsConstant .GFE_LATENCIES_NAME );
265+ long gfeLatencyValue = getAggregatedValue (gfeLatencyMetricData , expectedAttributes );
266+ assertEquals (fakeServerTiming .get (), gfeLatencyValue , 0 );
267+
268+ assertFalse (
269+ checkIfMetricExists (metricReader , BuiltInMetricsConstant .GFE_CONNECTIVITY_ERROR_NAME ));
270+
271+ MetricData afeLatencyMetricData =
272+ getMetricData (metricReader , BuiltInMetricsConstant .AFE_LATENCIES_NAME );
273+ long afeLatencyValue = getAggregatedValue (afeLatencyMetricData , expectedAttributes );
274+ assertEquals (fakeAFEServerTiming .get (), afeLatencyValue , 0 );
275+ assertFalse (
276+ checkIfMetricExists (metricReader , BuiltInMetricsConstant .AFE_CONNECTIVITY_ERROR_NAME ));
277+ } finally {
278+ writeableEnvironmentVariables .remove ("GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS" );
279+ }
280+ }
281+
217282 @ Test
218283 public void testMetricsWithGaxRetryUnaryRpc () {
219284 Stopwatch stopwatch = Stopwatch .createStarted ();
@@ -284,10 +349,6 @@ public void testNoNetworkConnection() {
284349 return null ;
285350 });
286351
287- ApiTracerFactory metricsTracerFactory =
288- new MetricsTracerFactory (
289- new OpenTelemetryMetricsRecorder (openTelemetry , BuiltInMetricsConstant .METER_NAME ),
290- attributes );
291352 Spanner spanner =
292353 builder
293354 .setProjectId ("test-project" )
@@ -305,7 +366,7 @@ public void testNoNetworkConnection() {
305366 // Setting this to false so that Spanner Options does not register Metrics Tracer
306367 // factory again.
307368 .setBuiltInMetricsEnabled (false )
308- .setApiTracerFactory (metricsTracerFactory )
369+ .setApiTracerFactory (createMetricsTracerFactory () )
309370 .build ()
310371 .getService ();
311372 String instance = "i" ;
@@ -370,7 +431,7 @@ public void testNoServerTimingHeader() throws IOException, InterruptedException
370431 // Setting this to false so that Spanner Options does not register Metrics Tracer
371432 // factory again.
372433 .setBuiltInMetricsEnabled (false )
373- .setApiTracerFactory (metricsTracerFactory )
434+ .setApiTracerFactory (createMetricsTracerFactory () )
374435 .build ()
375436 .getService ();
376437 DatabaseClient databaseClientNoHeader =
@@ -391,6 +452,8 @@ public void testNoServerTimingHeader() throws IOException, InterruptedException
391452 MetricData gfeConnectivityMetricData =
392453 getMetricData (metricReader , BuiltInMetricsConstant .GFE_CONNECTIVITY_ERROR_NAME );
393454 assertThat (getAggregatedValue (gfeConnectivityMetricData , expectedAttributes )).isEqualTo (1 );
455+ assertFalse (checkIfMetricExists (metricReader , BuiltInMetricsConstant .AFE_LATENCIES_NAME ));
456+ assertFalse (checkIfMetricExists (metricReader , BuiltInMetricsConstant .GFE_LATENCIES_NAME ));
394457 assertFalse (
395458 checkIfMetricExists (metricReader , BuiltInMetricsConstant .AFE_CONNECTIVITY_ERROR_NAME ));
396459 spannerNoHeader .close ();
0 commit comments