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" , "false" );
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