@@ -94,13 +94,13 @@ class CompletedAttemptMetric:
9494 """
9595
9696 start_time : datetime .datetime
97- duration : float
97+ duration_ms : float
9898 end_status : StatusCode
99- first_response_latency : float | None = None
100- gfe_latency : float | None = None
101- application_blocking_time : float = 0.0
102- backoff_before_attempt : float = 0.0
103- grpc_throttling_time : float = 0.0
99+ first_response_latency_ms : float | None = None
100+ gfe_latency_ms : float | None = None
101+ application_blocking_time_ms : float = 0.0
102+ backoff_before_attempt_ms : float = 0.0
103+ grpc_throttling_time_ms : float = 0.0
104104
105105
106106@dataclass (frozen = True )
@@ -112,13 +112,13 @@ class CompletedOperationMetric:
112112
113113 op_type : OperationType
114114 start_time : datetime .datetime
115- duration : float
115+ duration_ms : float
116116 completed_attempts : list [CompletedAttemptMetric ]
117117 final_status : StatusCode
118118 cluster_id : str
119119 zone : str
120120 is_streaming : bool
121- flow_throttling_time : float = 0.0
121+ flow_throttling_time_ms : float = 0.0
122122
123123
124124@dataclass
@@ -130,19 +130,19 @@ class ActiveAttemptMetric:
130130
131131 # keep both clock time and monotonic timestamps for active attempts
132132 start_time : TimeTuple = field (default_factory = TimeTuple )
133- # the time it takes to recieve the first response from the server
133+ # the time it takes to recieve the first response from the server, in milliseconds
134134 # currently only tracked for ReadRows
135- first_response_latency : float | None = None
136- # the time taken by the backend. Taken from response header
137- gfe_latency : float | None = None
138- # time waiting on user to process the response
135+ first_response_latency_ms : float | None = None
136+ # the time taken by the backend, in milliseconds . Taken from response header
137+ gfe_latency_ms : float | None = None
138+ # time waiting on user to process the response, in milliseconds
139139 # currently only relevant for ReadRows
140- application_blocking_time : float = 0.0
141- # backoff time is added to application_blocking_time
142- backoff_before_attempt : float = 0.0
143- # time waiting on grpc channel
140+ application_blocking_time_ms : float = 0.0
141+ # backoff time is added to application_blocking_time_ms
142+ backoff_before_attempt_ms : float = 0.0
143+ # time waiting on grpc channel, in milliseconds
144144 # TODO: capture grpc_throttling_time
145- grpc_throttling_time : float = 0.0
145+ grpc_throttling_time_ms : float = 0.0
146146
147147
148148@dataclass
@@ -163,8 +163,8 @@ class ActiveOperationMetric:
163163 is_streaming : bool = False # only True for read_rows operations
164164 was_completed : bool = False
165165 handlers : list [MetricsHandler ] = field (default_factory = list )
166- # time waiting on flow control
167- flow_throttling_time : float = 0.0
166+ # time waiting on flow control, in milliseconds
167+ flow_throttling_time_ms : float = 0.0
168168
169169 @property
170170 def state (self ) -> OperationState :
@@ -208,11 +208,12 @@ def start_attempt(self) -> None:
208208 # find backoff value
209209 if self .backoff_generator and len (self .completed_attempts ) > 0 :
210210 # find the attempt's backoff by sending attempt number to generator
211- backoff = self .backoff_generator .send (len (self .completed_attempts ) - 1 )
211+ # generator will return the backoff time in seconds, so convert to ms
212+ backoff_ms = self .backoff_generator .send (len (self .completed_attempts ) - 1 ) * 1000
212213 else :
213- backoff = 0
214+ backoff_ms = 0
214215
215- self .active_attempt = ActiveAttemptMetric (backoff_before_attempt = backoff )
216+ self .active_attempt = ActiveAttemptMetric (backoff_before_attempt_ms = backoff_ms )
216217
217218 def add_response_metadata (self , metadata : dict [str , bytes | str ]) -> None :
218219 """
@@ -250,8 +251,7 @@ def add_response_metadata(self, metadata: dict[str, bytes | str]) -> None:
250251 if timing_header :
251252 timing_data = SERVER_TIMING_REGEX .match (timing_header )
252253 if timing_data and self .active_attempt :
253- # convert from milliseconds to seconds
254- self .active_attempt .gfe_latency = float (timing_data .group (1 )) / 1000
254+ self .active_attempt .gfe_latency_ms = float (timing_data .group (1 ))
255255
256256 @staticmethod
257257 @lru_cache (maxsize = 32 )
@@ -286,11 +286,12 @@ def attempt_first_response(self) -> None:
286286 return self ._handle_error (
287287 INVALID_STATE_ERROR .format ("attempt_first_response" , self .state )
288288 )
289- if self .active_attempt .first_response_latency is not None :
289+ if self .active_attempt .first_response_latency_ms is not None :
290290 return self ._handle_error ("Attempt already received first response" )
291- self .active_attempt .first_response_latency = (
291+ # convert duration to milliseconds
292+ self .active_attempt .first_response_latency_ms = (
292293 time .monotonic () - self .active_attempt .start_time .monotonic
293- )
294+ ) * 1000
294295
295296 def end_attempt_with_status (self , status : StatusCode | Exception ) -> None :
296297 """
@@ -309,15 +310,15 @@ def end_attempt_with_status(self, status: StatusCode | Exception) -> None:
309310
310311 new_attempt = CompletedAttemptMetric (
311312 start_time = self .active_attempt .start_time .utc ,
312- first_response_latency = self .active_attempt .first_response_latency ,
313- duration = time .monotonic () - self .active_attempt .start_time .monotonic ,
313+ first_response_latency_ms = self .active_attempt .first_response_latency_ms ,
314+ duration_ms = ( time .monotonic () - self .active_attempt .start_time .monotonic ) * 1000 ,
314315 end_status = self ._exc_to_status (status )
315316 if isinstance (status , Exception )
316317 else status ,
317- gfe_latency = self .active_attempt .gfe_latency ,
318- application_blocking_time = self .active_attempt .application_blocking_time ,
319- backoff_before_attempt = self .active_attempt .backoff_before_attempt ,
320- grpc_throttling_time = self .active_attempt .grpc_throttling_time ,
318+ gfe_latency_ms = self .active_attempt .gfe_latency_ms ,
319+ application_blocking_time_ms = self .active_attempt .application_blocking_time_ms ,
320+ backoff_before_attempt_ms = self .active_attempt .backoff_before_attempt_ms ,
321+ grpc_throttling_time_ms = self .active_attempt .grpc_throttling_time_ms ,
321322 )
322323 self .completed_attempts .append (new_attempt )
323324 self .active_attempt = None
@@ -351,12 +352,12 @@ def end_with_status(self, status: StatusCode | Exception) -> None:
351352 op_type = self .op_type ,
352353 start_time = self .start_time .utc ,
353354 completed_attempts = self .completed_attempts ,
354- duration = time .monotonic () - self .start_time .monotonic ,
355+ duration_ms = ( time .monotonic () - self .start_time .monotonic ) * 1000 ,
355356 final_status = final_status ,
356357 cluster_id = self .cluster_id or DEFAULT_CLUSTER_ID ,
357358 zone = self .zone or DEFAULT_ZONE ,
358359 is_streaming = self .is_streaming ,
359- flow_throttling_time = self .flow_throttling_time ,
360+ flow_throttling_time_ms = self .flow_throttling_time_ms ,
360361 )
361362 for handler in self .handlers :
362363 handler .on_operation_complete (finalized )
0 commit comments