fix(profiling): fix Lock dropping all samples when gevent monkey-patches#18261
Conversation
Codeowners resolved as |
|
BenchmarksBenchmark execution time: 2026-05-26 03:58:39 Comparing candidate commit 7c996de in PR branch Found 0 performance improvements and 5 performance regressions! Performance is the same for 617 metrics, 10 unstable metrics. scenario:iastaspects-lstrip_aspect
scenario:iastaspects-translate_aspect
scenario:iastaspectsospath-ospathbasename_aspect
scenario:span-start
scenario:telemetryaddmetric-1-count-metric-1-times
|
7c996de to
9952009
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d0ff52d3c3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Fixes a profiling reliability issue where gevent.monkey.patch_all() / patch_thread() can overwrite the lock-profiler’s patched lock allocators after the profiler is already running, causing lock samples to be dropped.
Changes:
- Add a
LockCollectorclass-level mechanism to detect/wrapgevent.monkey.patch_all/patch_threadand re-apply lock patches if they were overwritten. - Add subprocess tests that simulate gevent’s in-place replacement behavior (plus an optional integration test when gevent is available).
- Add a release note describing the fix.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
ddtrace/profiling/collector/_lock.pyx |
Adds gevent monkey-patch wrapping and repatching logic tied to active lock collectors. |
tests/profiling/collector/test_threading.py |
Adds new subprocess tests simulating gevent lock replacement and verifying repatching behavior. |
releasenotes/notes/fix-lock-profiler-gevent-monkey-patch-12dfaebf75e05535.yaml |
Documents the fix in release notes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
241958d
into
main
Description
Bug
When
gevent.monkey.patch_all(orpatch_thread) runs after the profiler has started, it replaces threading's lock primitives in-place with gevent's cooperative lock types, destroying the profiler's _LockAllocatorWrapper. This causes the lock profiler to silently drop all lock profiling samples for the rest of the process lifetime.This is a follow-up to the module-cloning bug fixed in PR #16775, where cleanup_loaded_modules re-imported threading; this bug is related to gevent's monkey-patching and is a separate code path that overwrites lock attributes after the re-import fix runs.
Fix
Adds a class-level hook on LockCollector that wraps gevent.monkey.patch_all and gevent.monkey.patch_thread with post-callbacks. After gevent finishes replacing lock types, the hook checks if any active collector's _LockAllocatorWrapper was overwritten and re-applies the profiler patch.
Testing
BEFORE
AFTER