Skip to content

Commit 15e5ed6

Browse files
add support for profiling threading.BoundedSemaphore objects in Python Lock profiler
1 parent d379a7f commit 15e5ed6

File tree

4 files changed

+231
-69
lines changed

4 files changed

+231
-69
lines changed

ddtrace/profiling/collector/threading.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ class _ProfiledThreadingSemaphore(_lock._ProfiledLock):
2121
pass
2222

2323

24+
class _ProfiledThreadingBoundedSemaphore(_lock._ProfiledLock):
25+
pass
26+
27+
2428
class ThreadingLockCollector(_lock.LockCollector):
2529
"""Record threading.Lock usage."""
2630

@@ -45,6 +49,14 @@ class ThreadingSemaphoreCollector(_lock.LockCollector):
4549
PATCH_ATTR_NAME = "Semaphore"
4650

4751

52+
class ThreadingBoundedSemaphoreCollector(_lock.LockCollector):
53+
"""Record threading.BoundedSemaphore usage."""
54+
55+
PROFILED_LOCK_CLASS = _ProfiledThreadingBoundedSemaphore
56+
PATCH_MODULE = threading
57+
PATCH_ATTR_NAME = "BoundedSemaphore"
58+
59+
4860
# Also patch threading.Thread so echion can track thread lifetimes
4961
def init_stack_v2() -> None:
5062
if config.stack.enabled and stack_v2.is_available:

ddtrace/profiling/profiler.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ def start_collector(collector_class: Type) -> None:
221221
("threading", lambda _: start_collector(threading.ThreadingLockCollector)),
222222
("threading", lambda _: start_collector(threading.ThreadingRLockCollector)),
223223
("threading", lambda _: start_collector(threading.ThreadingSemaphoreCollector)),
224+
("threading", lambda _: start_collector(threading.ThreadingBoundedSemaphoreCollector)),
224225
("asyncio", lambda _: start_collector(asyncio.AsyncioLockCollector)),
225226
]
226227

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
features:
3+
- |
4+
profiling: Add support for ``threading.BoundedSemaphore`` locking type profiling in Python.
5+
The Lock profiler now detects and marks "internal" Lock objects, i.e. those that are part of implementation of higher-level locking types.
6+
One example of such higher-level primitive is ``threading.BoundedSemaphore``, which is implemented with ``threading.Condition``, which itself uses ``threading.Lock`` internally.
7+
Marking a locks as internal will prevent it from being logged, which means the sample will only be counted once.

0 commit comments

Comments
 (0)