diff --git a/ddtrace/profiling/collector/_lock.py b/ddtrace/profiling/collector/_lock.py index ab01e66c2a5..33cf8bc226f 100644 --- a/ddtrace/profiling/collector/_lock.py +++ b/ddtrace/profiling/collector/_lock.py @@ -123,6 +123,7 @@ def _acquire(self, inner_func, *args, **kwargs): finally: try: end = self._self_acquired_at = time.monotonic_ns() + print("lock acquired at ", end) thread_id, thread_name = _current_thread() task_id, task_name, task_frame = _task.get_task(thread_id) self._maybe_update_self_name() @@ -179,57 +180,62 @@ def acquire(self, *args, **kwargs): def _release(self, inner_func, *args, **kwargs): # type (typing.Any, typing.Any) -> None - # Since we're holding this lock, we can be sure that _self_acquired_at is set - start = self._self_acquired_at + + start = None + if hasattr(self, "_self_acquired_at"): + # _self_acquired_at is only set when the acquire was captured + # if it's not set, we're not capturing the release + start = self.self_acquired_at try: return inner_func(*args, **kwargs) finally: - end = time.monotonic_ns() - thread_id, thread_name = _current_thread() - task_id, task_name, task_frame = _task.get_task(thread_id) - lock_name = "%s:%s" % (self._self_init_loc, self._self_name) if self._self_name else self._self_init_loc + if start is not None: + end = time.monotonic_ns() + thread_id, thread_name = _current_thread() + task_id, task_name, task_frame = _task.get_task(thread_id) + lock_name = "%s:%s" % (self._self_init_loc, self._self_name) if self._self_name else self._self_init_loc - if task_frame is None: - # See the comments in _acquire - frame = sys._getframe(2) - else: - frame = task_frame - - frames, nframes = _traceback.pyframe_to_frames(frame, self._self_max_nframes) - - if self._self_export_libdd_enabled: - thread_native_id = _threading.get_thread_native_id(thread_id) - - handle = ddup.SampleHandle() - handle.push_monotonic_ns(end) - handle.push_lock_name(lock_name) - handle.push_release(end - start, 1) # AFAICT, capture_pct does not adjust anything here - handle.push_threadinfo(thread_id, thread_native_id, thread_name) - handle.push_task_id(task_id) - handle.push_task_name(task_name) - - if self._self_tracer is not None: - handle.push_span(self._self_tracer.current_span()) - for frame in frames: - handle.push_frame(frame.function_name, frame.file_name, 0, frame.lineno) - handle.flush_sample() - else: - event = self.RELEASE_EVENT_CLASS( - lock_name=lock_name, - frames=frames, - nframes=nframes, - thread_id=thread_id, - thread_name=thread_name, - task_id=task_id, - task_name=task_name, - locked_for_ns=end - start, - sampling_pct=self._self_capture_sampler.capture_pct, - ) + if task_frame is None: + # See the comments in _acquire + frame = sys._getframe(2) + else: + frame = task_frame - if self._self_tracer is not None: - event.set_trace_info(self._self_tracer.current_span(), self._self_endpoint_collection_enabled) + frames, nframes = _traceback.pyframe_to_frames(frame, self._self_max_nframes) + + if self._self_export_libdd_enabled: + thread_native_id = _threading.get_thread_native_id(thread_id) + + handle = ddup.SampleHandle() + handle.push_monotonic_ns(end) + handle.push_lock_name(lock_name) + handle.push_release(end - start, 1) # AFAICT, capture_pct does not adjust anything here + handle.push_threadinfo(thread_id, thread_native_id, thread_name) + handle.push_task_id(task_id) + handle.push_task_name(task_name) - self._self_recorder.push_event(event) + if self._self_tracer is not None: + handle.push_span(self._self_tracer.current_span()) + for frame in frames: + handle.push_frame(frame.function_name, frame.file_name, 0, frame.lineno) + handle.flush_sample() + else: + event = self.RELEASE_EVENT_CLASS( + lock_name=lock_name, + frames=frames, + nframes=nframes, + thread_id=thread_id, + thread_name=thread_name, + task_id=task_id, + task_name=task_name, + locked_for_ns=end - start, + sampling_pct=self._self_capture_sampler.capture_pct, + ) + + if self._self_tracer is not None: + event.set_trace_info(self._self_tracer.current_span(), self._self_endpoint_collection_enabled) + + self._self_recorder.push_event(event) def release(self, *args, **kwargs): return self._release(self.__wrapped__.release, *args, **kwargs)