14
14
15
15
from apify_client ._errors import ApifyApiError , InvalidResponseBodyError , is_retryable_error
16
16
from apify_client ._logging import log_context , logger_name
17
+ from apify_client ._statistics import Statistics
17
18
from apify_client ._utils import retry_with_exp_backoff , retry_with_exp_backoff_async
18
19
19
20
if TYPE_CHECKING :
@@ -35,6 +36,7 @@ def __init__(
35
36
max_retries : int = 8 ,
36
37
min_delay_between_retries_millis : int = 500 ,
37
38
timeout_secs : int = 360 ,
39
+ stats : Statistics | None = None ,
38
40
) -> None :
39
41
self .max_retries = max_retries
40
42
self .min_delay_between_retries_millis = min_delay_between_retries_millis
@@ -59,6 +61,8 @@ def __init__(
59
61
self .httpx_client = httpx .Client (headers = headers , follow_redirects = True , timeout = timeout_secs )
60
62
self .httpx_async_client = httpx .AsyncClient (headers = headers , follow_redirects = True , timeout = timeout_secs )
61
63
64
+ self .stats = stats or Statistics ()
65
+
62
66
@staticmethod
63
67
def _maybe_parse_response (response : httpx .Response ) -> Any :
64
68
if response .status_code == HTTPStatus .NO_CONTENT :
@@ -143,6 +147,8 @@ def call(
143
147
log_context .method .set (method )
144
148
log_context .url .set (url )
145
149
150
+ self .stats .calls += 1
151
+
146
152
if stream and parse_response :
147
153
raise ValueError ('Cannot stream response and parse it at the same time!' )
148
154
@@ -153,6 +159,9 @@ def call(
153
159
def _make_request (stop_retrying : Callable , attempt : int ) -> httpx .Response :
154
160
log_context .attempt .set (attempt )
155
161
logger .debug ('Sending request' )
162
+
163
+ self .stats .requests += 1
164
+
156
165
try :
157
166
request = httpx_client .build_request (
158
167
method = method ,
@@ -177,6 +186,9 @@ def _make_request(stop_retrying: Callable, attempt: int) -> httpx.Response:
177
186
178
187
return response
179
188
189
+ if response .status_code == HTTPStatus .TOO_MANY_REQUESTS :
190
+ self .stats .add_rate_limit_error (attempt )
191
+
180
192
except Exception as e :
181
193
logger .debug ('Request threw exception' , exc_info = e )
182
194
if not is_retryable_error (e ):
@@ -217,6 +229,8 @@ async def call(
217
229
log_context .method .set (method )
218
230
log_context .url .set (url )
219
231
232
+ self .stats .calls += 1
233
+
220
234
if stream and parse_response :
221
235
raise ValueError ('Cannot stream response and parse it at the same time!' )
222
236
@@ -251,6 +265,9 @@ async def _make_request(stop_retrying: Callable, attempt: int) -> httpx.Response
251
265
252
266
return response
253
267
268
+ if response .status_code == HTTPStatus .TOO_MANY_REQUESTS :
269
+ self .stats .add_rate_limit_error (attempt )
270
+
254
271
except Exception as e :
255
272
logger .debug ('Request threw exception' , exc_info = e )
256
273
if not is_retryable_error (e ):
0 commit comments