From 85963720e962f37f48d1e1b86739a1bdd6396df6 Mon Sep 17 00:00:00 2001 From: Tony Xiao Date: Fri, 25 Nov 2022 11:16:06 -0500 Subject: [PATCH] fix(profiling): Resolve inherited method class names Methods may be inherited from a parent class. If multiple classes inherit from the same class and uses the inherited method, we'd want it to report the parent class's name instead of the individual child classes since they'd have the same filename and lineno of the parent class and not the children. --- sentry_sdk/profiler.py | 8 ++++-- tests/test_profiler.py | 56 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/sentry_sdk/profiler.py b/sentry_sdk/profiler.py index 28e96016ca..3d3b7cf5a0 100644 --- a/sentry_sdk/profiler.py +++ b/sentry_sdk/profiler.py @@ -211,7 +211,9 @@ def get_frame_name(frame): and f_code.co_varnames[0] == "self" and "self" in frame.f_locals ): - return "{}.{}".format(frame.f_locals["self"].__class__.__name__, name) + for cls in frame.f_locals["self"].__class__.__mro__: + if name in cls.__dict__: + return "{}.{}".format(cls.__name__, name) except AttributeError: pass @@ -225,7 +227,9 @@ def get_frame_name(frame): and f_code.co_varnames[0] == "cls" and "cls" in frame.f_locals ): - return "{}.{}".format(frame.f_locals["cls"].__name__, name) + for cls in frame.f_locals["cls"].__mro__: + if name in cls.__dict__: + return "{}.{}".format(cls.__name__, name) except AttributeError: pass diff --git a/tests/test_profiler.py b/tests/test_profiler.py index 11e92630cf..42721044ce 100644 --- a/tests/test_profiler.py +++ b/tests/test_profiler.py @@ -82,7 +82,35 @@ def get_frame(depth=1): return inspect.currentframe() -class GetFrame: +class GetFrameBase: + def inherited_instance_method(self): + return inspect.currentframe() + + def inherited_instance_method_wrapped(self): + def wrapped(): + self + return inspect.currentframe() + + return wrapped + + @classmethod + def inherited_class_method(cls): + return inspect.currentframe() + + @classmethod + def inherited_class_method_wrapped(cls): + def wrapped(): + cls + return inspect.currentframe() + + return wrapped + + @staticmethod + def inherited_static_method(): + return inspect.currentframe() + + +class GetFrame(GetFrameBase): def instance_method(self): return inspect.currentframe() @@ -149,6 +177,32 @@ def static_method(): id="static_method", marks=pytest.mark.skip(reason="unsupported"), ), + pytest.param( + GetFrame().inherited_instance_method(), + "GetFrameBase.inherited_instance_method", + id="inherited_instance_method", + ), + pytest.param( + GetFrame().inherited_instance_method_wrapped()(), + "wrapped", + id="instance_method_wrapped", + ), + pytest.param( + GetFrame().inherited_class_method(), + "GetFrameBase.inherited_class_method", + id="inherited_class_method", + ), + pytest.param( + GetFrame().inherited_class_method_wrapped()(), + "wrapped", + id="inherited_class_method_wrapped", + ), + pytest.param( + GetFrame().inherited_static_method(), + "GetFrameBase.static_method", + id="inherited_static_method", + marks=pytest.mark.skip(reason="unsupported"), + ), ], ) def test_get_frame_name(frame, frame_name):