6
6
import sys
7
7
import time
8
8
import types
9
- import typing
9
+ from typing import Any
10
+ from typing import Callable
11
+ from typing import Dict
12
+ from typing import Optional
13
+ from typing import Tuple
14
+ from typing import Type
10
15
11
16
import wrapt
12
17
19
24
from ddtrace .trace import Tracer
20
25
21
26
22
- def _current_thread ():
23
- # type: (...) -> typing.Tuple[int, str]
27
+ def _current_thread () -> Tuple [int , str ]:
24
28
thread_id = _thread .get_ident ()
25
29
return thread_id , _threading .get_thread_name (thread_id )
26
30
@@ -42,8 +46,8 @@ def _current_thread():
42
46
class _ProfiledLock (wrapt .ObjectProxy ):
43
47
def __init__ (
44
48
self ,
45
- wrapped : typing . Any ,
46
- tracer : typing . Optional [Tracer ],
49
+ wrapped : Any ,
50
+ tracer : Optional [Tracer ],
47
51
max_nframes : int ,
48
52
capture_sampler : collector .CaptureSampler ,
49
53
endpoint_collection_enabled : bool ,
@@ -56,15 +60,15 @@ def __init__(
56
60
frame = sys ._getframe (2 if WRAPT_C_EXT else 3 )
57
61
code = frame .f_code
58
62
self ._self_init_loc = "%s:%d" % (os .path .basename (code .co_filename ), frame .f_lineno )
59
- self ._self_name : typing . Optional [str ] = None
63
+ self ._self_name : Optional [str ] = None
60
64
61
- def __aenter__ (self , * args , ** kwargs ) :
65
+ def __aenter__ (self , * args : Any , ** kwargs : Any ) -> Any :
62
66
return self ._acquire (self .__wrapped__ .__aenter__ , * args , ** kwargs )
63
67
64
- def __aexit__ (self , * args , ** kwargs ) :
68
+ def __aexit__ (self , * args : Any , ** kwargs : Any ) -> Any :
65
69
return self ._release (self .__wrapped__ .__aexit__ , * args , ** kwargs )
66
70
67
- def _acquire (self , inner_func , * args , ** kwargs ) :
71
+ def _acquire (self , inner_func : Callable [..., Any ], * args : Any , ** kwargs : Any ) -> Any :
68
72
if not self ._self_capture_sampler .capture ():
69
73
return inner_func (* args , ** kwargs )
70
74
@@ -106,12 +110,10 @@ def _acquire(self, inner_func, *args, **kwargs):
106
110
except Exception :
107
111
pass # nosec
108
112
109
- def acquire (self , * args , ** kwargs ) :
113
+ def acquire (self , * args : Any , ** kwargs : Any ) -> Any :
110
114
return self ._acquire (self .__wrapped__ .acquire , * args , ** kwargs )
111
115
112
- def _release (self , inner_func , * args , ** kwargs ):
113
- # type (typing.Any, typing.Any) -> None
114
-
116
+ def _release (self , inner_func : Any , * args : Any , ** kwargs : Any ) -> None :
115
117
# The underlying threading.Lock class is implemented using C code, and
116
118
# it doesn't have the __dict__ attribute. So we can't do
117
119
# self.__dict__.pop("_self_acquired_at", None) to remove the attribute.
@@ -162,18 +164,18 @@ def _release(self, inner_func, *args, **kwargs):
162
164
handle .push_frame (frame .function_name , frame .file_name , 0 , frame .lineno )
163
165
handle .flush_sample ()
164
166
165
- def release (self , * args , ** kwargs ) :
167
+ def release (self , * args : Any , ** kwargs : Any ) -> Any :
166
168
return self ._release (self .__wrapped__ .release , * args , ** kwargs )
167
169
168
170
acquire_lock = acquire
169
171
170
- def __enter__ (self , * args , ** kwargs ) :
172
+ def __enter__ (self , * args : Any , ** kwargs : Any ) -> Any :
171
173
return self ._acquire (self .__wrapped__ .__enter__ , * args , ** kwargs )
172
174
173
- def __exit__ (self , * args , ** kwargs ) :
175
+ def __exit__ (self , * args : Any , ** kwargs : Any ) -> None :
174
176
self ._release (self .__wrapped__ .__exit__ , * args , ** kwargs )
175
177
176
- def _find_self_name (self , var_dict : typing . Dict ) :
178
+ def _find_self_name (self , var_dict : Dict [ str , Any ]) -> Optional [ str ] :
177
179
for name , value in var_dict .items ():
178
180
if name .startswith ("__" ) or isinstance (value , types .ModuleType ):
179
181
continue
@@ -188,7 +190,7 @@ def _find_self_name(self, var_dict: typing.Dict):
188
190
189
191
# Get lock acquire/release call location and variable name the lock is assigned to
190
192
# This function propagates ValueError if the frame depth is <= 3.
191
- def _maybe_update_self_name (self ):
193
+ def _maybe_update_self_name (self ) -> None :
192
194
if self ._self_name is not None :
193
195
return
194
196
# We expect the call stack to be like this:
@@ -223,7 +225,7 @@ class FunctionWrapper(wrapt.FunctionWrapper):
223
225
# Override the __get__ method: whatever happens, _allocate_lock is always considered by Python like a "static"
224
226
# method, even when used as a class attribute. Python never tried to "bind" it to a method, because it sees it is a
225
227
# builtin function. Override default wrapt behavior here that tries to detect bound method.
226
- def __get__ (self , instance , owner = None ):
228
+ def __get__ (self , instance : Any , owner : Optional [ Type ] = None ) -> "FunctionWrapper" :
227
229
return self
228
230
229
231
@@ -232,51 +234,43 @@ class LockCollector(collector.CaptureSamplerCollector):
232
234
233
235
def __init__ (
234
236
self ,
235
- nframes = config .max_frames ,
236
- endpoint_collection_enabled = config .endpoint_collection ,
237
- tracer = None ,
238
- * args ,
239
- ** kwargs ,
240
- ):
237
+ nframes : int = config .max_frames ,
238
+ endpoint_collection_enabled : bool = config .endpoint_collection ,
239
+ tracer : Optional [ Tracer ] = None ,
240
+ * args : Any ,
241
+ ** kwargs : Any ,
242
+ ) -> None :
241
243
super ().__init__ (* args , ** kwargs )
242
- self .nframes = nframes
243
- self .endpoint_collection_enabled = endpoint_collection_enabled
244
- self .tracer = tracer
245
- self ._original = None
244
+ self .nframes : int = nframes
245
+ self .endpoint_collection_enabled : bool = endpoint_collection_enabled
246
+ self .tracer : Optional [ Tracer ] = tracer
247
+ self ._original : Optional [ Any ] = None
246
248
247
249
@abc .abstractmethod
248
- def _get_patch_target (self ):
249
- # type: (...) -> typing.Any
250
- pass
250
+ def _get_patch_target (self ) -> Callable [..., Any ]:
251
+ ...
251
252
252
253
@abc .abstractmethod
253
- def _set_patch_target (
254
- self ,
255
- value , # type: typing.Any
256
- ):
257
- # type: (...) -> None
258
- pass
254
+ def _set_patch_target (self , value : Any ) -> None :
255
+ ...
259
256
260
- def _start_service (self ):
261
- # type: (...) -> None
257
+ def _start_service (self ) -> None :
262
258
"""Start collecting lock usage."""
263
259
self .patch ()
264
260
super (LockCollector , self )._start_service () # type: ignore[safe-super]
265
261
266
- def _stop_service (self ):
267
- # type: (...) -> None
262
+ def _stop_service (self ) -> None :
268
263
"""Stop collecting lock usage."""
269
264
super (LockCollector , self )._stop_service () # type: ignore[safe-super]
270
265
self .unpatch ()
271
266
272
- def patch (self ):
273
- # type: (...) -> None
267
+ def patch (self ) -> None :
274
268
"""Patch the module for tracking lock allocation."""
275
269
# We only patch the lock from the `threading` module.
276
270
# Nobody should use locks from `_thread`; if they do so, then it's deliberate and we don't profile.
277
271
self ._original = self ._get_patch_target ()
278
272
279
- def _allocate_lock (wrapped , instance , args , kwargs ) :
273
+ def _allocate_lock (wrapped : Any , instance : Any , args : Any , kwargs : Any ) -> _ProfiledLock :
280
274
lock = wrapped (* args , ** kwargs )
281
275
return self .PROFILED_LOCK_CLASS (
282
276
lock ,
@@ -288,7 +282,6 @@ def _allocate_lock(wrapped, instance, args, kwargs):
288
282
289
283
self ._set_patch_target (FunctionWrapper (self ._original , _allocate_lock ))
290
284
291
- def unpatch (self ):
292
- # type: (...) -> None
285
+ def unpatch (self ) -> None :
293
286
"""Unpatch the threading module for tracking lock allocation."""
294
287
self ._set_patch_target (self ._original )
0 commit comments