1515# This file is automatically generated by CrossSync. Do not edit manually.
1616
1717from __future__ import annotations
18+ import time
1819from functools import wraps
1920from google .cloud .bigtable .data ._metrics .data_model import (
2021 OPERATION_INTERCEPTOR_METADATA_KEY ,
@@ -42,7 +43,10 @@ def wrapper(self, continuation, client_call_details, request):
4243 )
4344 operation : "ActiveOperationMetric" = self .operation_map .get (key )
4445 if operation :
45- if operation .state != OperationState .ACTIVE_ATTEMPT :
46+ if (
47+ operation .state == OperationState .CREATED
48+ or operation .state == OperationState .BETWEEN_ATTEMPTS
49+ ):
4650 operation .start_attempt ()
4751 return func (self , operation , continuation , client_call_details , request )
4852 else :
@@ -51,6 +55,22 @@ def wrapper(self, continuation, client_call_details, request):
5155 return wrapper
5256
5357
58+ def _end_attempt (operation , exc , metadata ):
59+ """Helper to add metadata and exception to an operation"""
60+ if metadata is not None :
61+ operation .add_response_metadata (metadata )
62+ if exc is not None :
63+ operation .end_attempt_with_status (exc )
64+
65+
66+ def _get_metadata (source ):
67+ """Helper to extract metadata from a call or RpcError"""
68+ try :
69+ return (source .trailing_metadata () or []) + (source .initial_metadata () or [])
70+ except Exception :
71+ return None
72+
73+
5474class BigtableMetricsInterceptor (
5575 UnaryUnaryClientInterceptor , UnaryStreamClientInterceptor , MetricsHandler
5676):
@@ -76,7 +96,8 @@ def register_operation(self, operation):
7696 operation .handlers .append (self )
7797
7898 def on_operation_complete (self , op ):
79- del self .operation_map [op .uuid ]
99+ if op .uuid in self .operation_map :
100+ del self .operation_map [op .uuid ]
80101
81102 def on_operation_cancelled (self , op ):
82103 self .on_operation_complete (op )
@@ -86,36 +107,42 @@ def intercept_unary_unary(
86107 self , operation , continuation , client_call_details , request
87108 ):
88109 encountered_exc : Exception | None = None
89- call = None
110+ metadata = None
90111 try :
91112 call = continuation (client_call_details , request )
113+ metadata = _get_metadata (call )
92114 return call
93- except Exception as e :
94- encountered_exc = e
95- raise
115+ except Exception as rpc_error :
116+ metadata = _get_metadata (rpc_error )
117+ encountered_exc = rpc_error
118+ raise rpc_error
96119 finally :
97- if call is not None :
98- metadata = call .trailing_metadata () + call .initial_metadata ()
99- operation .add_response_metadata (metadata )
100- if encountered_exc is not None :
101- operation .end_attempt_with_status (encountered_exc )
120+ _end_attempt (operation , encountered_exc , metadata )
102121
103122 @_with_operation_from_metadata
104123 def intercept_unary_stream (
105124 self , operation , continuation , client_call_details , request
106125 ):
107126 def response_wrapper (call ):
127+ has_first_response = operation .first_response_latency is not None
108128 encountered_exc = None
109129 try :
110130 for response in call :
131+ if not has_first_response :
132+ operation .first_response_latency_ns = (
133+ time .monotonic_ns () - operation .start_time_ns
134+ )
135+ has_first_response = True
111136 yield response
112137 except Exception as e :
113138 encountered_exc = e
114139 raise
115140 finally :
116- metadata = call .trailing_metadata () + call .initial_metadata ()
117- operation .add_response_metadata (metadata )
118- if encountered_exc is not None :
119- operation .end_attempt_with_status (encountered_exc )
141+ if call is not None :
142+ _end_attempt (operation , encountered_exc , _get_metadata (call ))
120143
121- return response_wrapper (continuation (client_call_details , request ))
144+ try :
145+ return response_wrapper (continuation (client_call_details , request ))
146+ except Exception as rpc_error :
147+ _end_attempt (operation , rpc_error , _get_metadata (rpc_error ))
148+ raise rpc_error
0 commit comments