@@ -185,159 +185,216 @@ def test_generate_client_uid(self):
185185 )
186186 assert re .match (expected_pattern , uid )
187187
188- @pytest .mark .parametrize (
189- "op_type,is_streaming,first_response_latency_ns,attempts_count" ,
190- [
191- (OperationType .READ_ROWS , True , 12345 , 0 ),
192- (OperationType .READ_ROWS , True , None , 2 ),
193- (OperationType .MUTATE_ROW , False , None , 3 ),
194- (
195- OperationType .SAMPLE_ROW_KEYS ,
196- False ,
197- 12345 ,
198- 1 ,
199- ), # first_response_latency should be ignored
200- ],
201- )
202- def test_on_operation_complete (
203- self , op_type , is_streaming , first_response_latency_ns , attempts_count
204- ):
205- mock_instruments = mock .Mock (
206- operation_latencies = mock .Mock (),
207- first_response_latencies = mock .Mock (),
208- retry_count = mock .Mock (),
209- )
188+ def test_on_operation_complete_operation_latencies (self ):
189+ mock_instruments = mock .Mock (operation_latencies = mock .Mock ())
210190 handler = self ._make_one (
211191 instance_id = "inst" , table_id = "table" , instruments = mock_instruments
212192 )
213- attempts = [mock .Mock () for _ in range (attempts_count )]
214193 op = CompletedOperationMetric (
215- op_type = op_type ,
194+ op_type = OperationType . READ_ROWS ,
216195 uuid = "test-uuid" ,
217196 duration_ns = 1234567 ,
218- completed_attempts = attempts ,
197+ completed_attempts = [] ,
219198 final_status = StatusCode .OK ,
220199 cluster_id = "cluster" ,
221200 zone = "zone" ,
222- is_streaming = is_streaming ,
223- first_response_latency_ns = first_response_latency_ns ,
201+ is_streaming = True ,
224202 )
225-
226203 handler .on_operation_complete (op )
227-
228204 expected_labels = {
229205 "method" : op .op_type .value ,
230206 "status" : op .final_status .name ,
231207 "resource_zone" : op .zone ,
232208 "resource_cluster" : op .cluster_id ,
233209 ** handler .shared_labels ,
234210 }
235-
236- # check operation_latencies
237211 mock_instruments .operation_latencies .record .assert_called_once_with (
238212 op .duration_ns / 1e6 ,
239- {"streaming" : str (is_streaming ), ** expected_labels },
213+ {"streaming" : str (op . is_streaming ), ** expected_labels },
240214 )
241215
242- # check first_response_latencies
243- if (
244- op_type == OperationType .READ_ROWS
245- and first_response_latency_ns is not None
246- ):
216+ @pytest .mark .parametrize (
217+ "op_type,first_response_latency_ns,should_record" ,
218+ [
219+ (OperationType .READ_ROWS , 12345 , True ),
220+ (OperationType .READ_ROWS , None , False ),
221+ (OperationType .MUTATE_ROW , 12345 , False ),
222+ ],
223+ )
224+ def test_on_operation_complete_first_response_latencies (
225+ self , op_type , first_response_latency_ns , should_record
226+ ):
227+ mock_instruments = mock .Mock (first_response_latencies = mock .Mock ())
228+ handler = self ._make_one (
229+ instance_id = "inst" , table_id = "table" , instruments = mock_instruments
230+ )
231+ op = CompletedOperationMetric (
232+ op_type = op_type ,
233+ uuid = "test-uuid" ,
234+ duration_ns = 1234567 ,
235+ completed_attempts = [],
236+ final_status = StatusCode .OK ,
237+ cluster_id = "cluster" ,
238+ zone = "zone" ,
239+ is_streaming = True ,
240+ first_response_latency_ns = first_response_latency_ns ,
241+ )
242+ handler .on_operation_complete (op )
243+ if should_record :
244+ expected_labels = {
245+ "method" : op .op_type .value ,
246+ "status" : op .final_status .name ,
247+ "resource_zone" : op .zone ,
248+ "resource_cluster" : op .cluster_id ,
249+ ** handler .shared_labels ,
250+ }
247251 mock_instruments .first_response_latencies .record .assert_called_once_with (
248252 first_response_latency_ns / 1e6 , expected_labels
249253 )
250254 else :
251255 mock_instruments .first_response_latencies .record .assert_not_called ()
252256
253- # check retry_count
257+ @pytest .mark .parametrize ("attempts_count" , [0 , 1 , 5 ])
258+ def test_on_operation_complete_retry_count (self , attempts_count ):
259+ mock_instruments = mock .Mock (retry_count = mock .Mock ())
260+ handler = self ._make_one (
261+ instance_id = "inst" , table_id = "table" , instruments = mock_instruments
262+ )
263+ attempts = [mock .Mock ()] * attempts_count
264+ op = CompletedOperationMetric (
265+ op_type = OperationType .READ_ROWS ,
266+ uuid = "test-uuid" ,
267+ duration_ns = 1234567 ,
268+ completed_attempts = attempts ,
269+ final_status = StatusCode .OK ,
270+ cluster_id = "cluster" ,
271+ zone = "zone" ,
272+ is_streaming = True ,
273+ )
274+ handler .on_operation_complete (op )
254275 if attempts :
276+ expected_labels = {
277+ "method" : op .op_type .value ,
278+ "status" : op .final_status .name ,
279+ "resource_zone" : op .zone ,
280+ "resource_cluster" : op .cluster_id ,
281+ ** handler .shared_labels ,
282+ }
255283 mock_instruments .retry_count .add .assert_called_once_with (
256284 len (attempts ) - 1 , expected_labels
257285 )
258286 else :
259287 mock_instruments .retry_count .add .assert_not_called ()
260288
289+ def test_on_attempt_complete_attempt_latencies (self ):
290+ mock_instruments = mock .Mock (attempt_latencies = mock .Mock ())
291+ handler = self ._make_one (
292+ instance_id = "inst" , table_id = "table" , instruments = mock_instruments
293+ )
294+ attempt = CompletedAttemptMetric (duration_ns = 1234567 , end_status = StatusCode .OK )
295+ op = ActiveOperationMetric (
296+ op_type = OperationType .READ_ROWS ,
297+ zone = "zone" ,
298+ cluster_id = "cluster" ,
299+ is_streaming = True ,
300+ )
301+ handler .on_attempt_complete (attempt , op )
302+ expected_labels = {
303+ "method" : op .op_type .value ,
304+ "resource_zone" : op .zone ,
305+ "resource_cluster" : op .cluster_id ,
306+ ** handler .shared_labels ,
307+ }
308+ mock_instruments .attempt_latencies .record .assert_called_once_with (
309+ attempt .duration_ns / 1e6 ,
310+ {
311+ "streaming" : str (op .is_streaming ),
312+ "status" : attempt .end_status .name ,
313+ ** expected_labels ,
314+ },
315+ )
316+
261317 @pytest .mark .parametrize (
262- "zone,cluster,gfe_latency_ns,is_first_attempt,flow_throttling_ns" ,
263- [
264- ("zone" , "cluster" , 12345 , True , 54321 ),
265- (None , None , None , False , 0 ),
266- ("zone" , "cluster" , 0 , True , 0 ), # gfe_latency_ns is 0
267- ],
318+ "is_first_attempt,flow_throttling_ns" ,
319+ [(True , 54321 ), (False , 0 ), (True , 0 )],
268320 )
269- def test_on_attempt_complete (
270- self , zone , cluster , gfe_latency_ns , is_first_attempt , flow_throttling_ns
321+ def test_on_attempt_complete_throttling_latencies (
322+ self , is_first_attempt , flow_throttling_ns
271323 ):
272- mock_instruments = mock .Mock (
273- attempt_latencies = mock .Mock (),
274- throttling_latencies = mock .Mock (),
275- application_latencies = mock .Mock (),
276- server_latencies = mock .Mock (),
277- connectivity_error_count = mock .Mock (),
278- )
324+ mock_instruments = mock .Mock (throttling_latencies = mock .Mock ())
279325 handler = self ._make_one (
280326 instance_id = "inst" , table_id = "table" , instruments = mock_instruments
281327 )
282328 attempt = CompletedAttemptMetric (
283329 duration_ns = 1234567 ,
284330 end_status = StatusCode .OK ,
285- gfe_latency_ns = gfe_latency_ns ,
286- application_blocking_time_ns = 234567 ,
287- backoff_before_attempt_ns = 345678 ,
288331 grpc_throttling_time_ns = 456789 ,
289332 )
290333 op = ActiveOperationMetric (
291334 op_type = OperationType .READ_ROWS ,
292- zone = zone ,
293- cluster_id = cluster ,
294- is_streaming = True ,
295335 flow_throttling_time_ns = flow_throttling_ns ,
296336 )
297337 if not is_first_attempt :
298338 op .completed_attempts .append (mock .Mock ())
299-
300339 handler .on_attempt_complete (attempt , op )
301-
302- expected_labels = {
303- "method" : op .op_type .value ,
304- "resource_zone" : zone or DEFAULT_ZONE ,
305- "resource_cluster" : cluster or DEFAULT_CLUSTER_ID ,
306- ** handler .shared_labels ,
307- }
308- status = attempt .end_status .name
309- is_streaming = str (op .is_streaming )
310-
311- # check attempt_latencies
312- mock_instruments .attempt_latencies .record .assert_called_once_with (
313- attempt .duration_ns / 1e6 ,
314- {"streaming" : is_streaming , "status" : status , ** expected_labels },
315- )
316-
317- # check throttling_latencies
318340 expected_throttling = attempt .grpc_throttling_time_ns / 1e6
319341 if is_first_attempt :
320342 expected_throttling += flow_throttling_ns / 1e6
321343 mock_instruments .throttling_latencies .record .assert_called_once_with (
322- pytest .approx (expected_throttling ), expected_labels
344+ pytest .approx (expected_throttling ), mock . ANY
323345 )
324346
325- # check application_latencies
347+ def test_on_attempt_complete_application_latencies (self ):
348+ mock_instruments = mock .Mock (application_latencies = mock .Mock ())
349+ handler = self ._make_one (
350+ instance_id = "inst" , table_id = "table" , instruments = mock_instruments
351+ )
352+ attempt = CompletedAttemptMetric (
353+ duration_ns = 1234567 ,
354+ end_status = StatusCode .OK ,
355+ application_blocking_time_ns = 234567 ,
356+ backoff_before_attempt_ns = 345678 ,
357+ )
358+ op = ActiveOperationMetric (op_type = OperationType .READ_ROWS )
359+ handler .on_attempt_complete (attempt , op )
326360 mock_instruments .application_latencies .record .assert_called_once_with (
327361 (attempt .application_blocking_time_ns + attempt .backoff_before_attempt_ns )
328362 / 1e6 ,
329- expected_labels ,
363+ mock . ANY ,
330364 )
331365
332- # check server_latencies or connectivity_error_count
333- if gfe_latency_ns is not None :
366+ @pytest .mark .parametrize (
367+ "gfe_latency_ns,should_record_server_latency" ,
368+ [(12345 , True ), (None , False ), (0 , True )],
369+ )
370+ def test_on_attempt_complete_server_latencies_and_connectivity_error (
371+ self , gfe_latency_ns , should_record_server_latency
372+ ):
373+ mock_instruments = mock .Mock (
374+ server_latencies = mock .Mock (), connectivity_error_count = mock .Mock ()
375+ )
376+ handler = self ._make_one (
377+ instance_id = "inst" , table_id = "table" , instruments = mock_instruments
378+ )
379+ attempt = CompletedAttemptMetric (
380+ duration_ns = 1234567 ,
381+ end_status = StatusCode .OK ,
382+ gfe_latency_ns = gfe_latency_ns ,
383+ )
384+ op = ActiveOperationMetric (
385+ op_type = OperationType .READ_ROWS ,
386+ zone = "zone" ,
387+ cluster_id = "cluster" ,
388+ is_streaming = True ,
389+ )
390+ handler .on_attempt_complete (attempt , op )
391+ if should_record_server_latency :
334392 mock_instruments .server_latencies .record .assert_called_once_with (
335- gfe_latency_ns / 1e6 ,
336- {"streaming" : is_streaming , "status" : status , ** expected_labels },
393+ gfe_latency_ns / 1e6 , mock .ANY
337394 )
338395 mock_instruments .connectivity_error_count .add .assert_not_called ()
339396 else :
340397 mock_instruments .server_latencies .record .assert_not_called ()
341398 mock_instruments .connectivity_error_count .add .assert_called_once_with (
342- 1 , { "status" : status , ** expected_labels }
343- )
399+ 1 , mock . ANY
400+ )
0 commit comments