aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/sentry_sdk/profiler/utils.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/sentry_sdk/profiler/utils.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are hereHEADmaster
Diffstat (limited to '.venv/lib/python3.12/site-packages/sentry_sdk/profiler/utils.py')
-rw-r--r--.venv/lib/python3.12/site-packages/sentry_sdk/profiler/utils.py199
1 files changed, 199 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/sentry_sdk/profiler/utils.py b/.venv/lib/python3.12/site-packages/sentry_sdk/profiler/utils.py
new file mode 100644
index 00000000..3554cddb
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/sentry_sdk/profiler/utils.py
@@ -0,0 +1,199 @@
+import os
+from collections import deque
+
+from sentry_sdk._compat import PY311
+from sentry_sdk.utils import filename_for_module
+
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+ from sentry_sdk._lru_cache import LRUCache
+ from types import FrameType
+ from typing import Deque
+ from typing import List
+ from typing import Optional
+ from typing import Sequence
+ from typing import Tuple
+ from typing_extensions import TypedDict
+
+ ThreadId = str
+
+ ProcessedStack = List[int]
+
+ ProcessedFrame = TypedDict(
+ "ProcessedFrame",
+ {
+ "abs_path": str,
+ "filename": Optional[str],
+ "function": str,
+ "lineno": int,
+ "module": Optional[str],
+ },
+ )
+
+ ProcessedThreadMetadata = TypedDict(
+ "ProcessedThreadMetadata",
+ {"name": str},
+ )
+
+ FrameId = Tuple[
+ str, # abs_path
+ int, # lineno
+ str, # function
+ ]
+ FrameIds = Tuple[FrameId, ...]
+
+ # The exact value of this id is not very meaningful. The purpose
+ # of this id is to give us a compact and unique identifier for a
+ # raw stack that can be used as a key to a dictionary so that it
+ # can be used during the sampled format generation.
+ StackId = Tuple[int, int]
+
+ ExtractedStack = Tuple[StackId, FrameIds, List[ProcessedFrame]]
+ ExtractedSample = Sequence[Tuple[ThreadId, ExtractedStack]]
+
+# The default sampling frequency to use. This is set at 101 in order to
+# mitigate the effects of lockstep sampling.
+DEFAULT_SAMPLING_FREQUENCY = 101
+
+
+# We want to impose a stack depth limit so that samples aren't too large.
+MAX_STACK_DEPTH = 128
+
+
+if PY311:
+
+ def get_frame_name(frame):
+ # type: (FrameType) -> str
+ return frame.f_code.co_qualname
+
+else:
+
+ def get_frame_name(frame):
+ # type: (FrameType) -> str
+
+ f_code = frame.f_code
+ co_varnames = f_code.co_varnames
+
+ # co_name only contains the frame name. If the frame was a method,
+ # the class name will NOT be included.
+ name = f_code.co_name
+
+ # if it was a method, we can get the class name by inspecting
+ # the f_locals for the `self` argument
+ try:
+ if (
+ # the co_varnames start with the frame's positional arguments
+ # and we expect the first to be `self` if its an instance method
+ co_varnames
+ and co_varnames[0] == "self"
+ and "self" in frame.f_locals
+ ):
+ for cls in type(frame.f_locals["self"]).__mro__:
+ if name in cls.__dict__:
+ return "{}.{}".format(cls.__name__, name)
+ except (AttributeError, ValueError):
+ pass
+
+ # if it was a class method, (decorated with `@classmethod`)
+ # we can get the class name by inspecting the f_locals for the `cls` argument
+ try:
+ if (
+ # the co_varnames start with the frame's positional arguments
+ # and we expect the first to be `cls` if its a class method
+ co_varnames
+ and co_varnames[0] == "cls"
+ and "cls" in frame.f_locals
+ ):
+ for cls in frame.f_locals["cls"].__mro__:
+ if name in cls.__dict__:
+ return "{}.{}".format(cls.__name__, name)
+ except (AttributeError, ValueError):
+ pass
+
+ # nothing we can do if it is a staticmethod (decorated with @staticmethod)
+
+ # we've done all we can, time to give up and return what we have
+ return name
+
+
+def frame_id(raw_frame):
+ # type: (FrameType) -> FrameId
+ return (raw_frame.f_code.co_filename, raw_frame.f_lineno, get_frame_name(raw_frame))
+
+
+def extract_frame(fid, raw_frame, cwd):
+ # type: (FrameId, FrameType, str) -> ProcessedFrame
+ abs_path = raw_frame.f_code.co_filename
+
+ try:
+ module = raw_frame.f_globals["__name__"]
+ except Exception:
+ module = None
+
+ # namedtuples can be many times slower when initialing
+ # and accessing attribute so we opt to use a tuple here instead
+ return {
+ # This originally was `os.path.abspath(abs_path)` but that had
+ # a large performance overhead.
+ #
+ # According to docs, this is equivalent to
+ # `os.path.normpath(os.path.join(os.getcwd(), path))`.
+ # The `os.getcwd()` call is slow here, so we precompute it.
+ #
+ # Additionally, since we are using normalized path already,
+ # we skip calling `os.path.normpath` entirely.
+ "abs_path": os.path.join(cwd, abs_path),
+ "module": module,
+ "filename": filename_for_module(module, abs_path) or None,
+ "function": fid[2],
+ "lineno": raw_frame.f_lineno,
+ }
+
+
+def extract_stack(
+ raw_frame, # type: Optional[FrameType]
+ cache, # type: LRUCache
+ cwd, # type: str
+ max_stack_depth=MAX_STACK_DEPTH, # type: int
+):
+ # type: (...) -> ExtractedStack
+ """
+ Extracts the stack starting the specified frame. The extracted stack
+ assumes the specified frame is the top of the stack, and works back
+ to the bottom of the stack.
+
+ In the event that the stack is more than `MAX_STACK_DEPTH` frames deep,
+ only the first `MAX_STACK_DEPTH` frames will be returned.
+ """
+
+ raw_frames = deque(maxlen=max_stack_depth) # type: Deque[FrameType]
+
+ while raw_frame is not None:
+ f_back = raw_frame.f_back
+ raw_frames.append(raw_frame)
+ raw_frame = f_back
+
+ frame_ids = tuple(frame_id(raw_frame) for raw_frame in raw_frames)
+ frames = []
+ for i, fid in enumerate(frame_ids):
+ frame = cache.get(fid)
+ if frame is None:
+ frame = extract_frame(fid, raw_frames[i], cwd)
+ cache.set(fid, frame)
+ frames.append(frame)
+
+ # Instead of mapping the stack into frame ids and hashing
+ # that as a tuple, we can directly hash the stack.
+ # This saves us from having to generate yet another list.
+ # Additionally, using the stack as the key directly is
+ # costly because the stack can be large, so we pre-hash
+ # the stack, and use the hash as the key as this will be
+ # needed a few times to improve performance.
+ #
+ # To Reduce the likelihood of hash collisions, we include
+ # the stack depth. This means that only stacks of the same
+ # depth can suffer from hash collisions.
+ stack_id = len(raw_frames), hash(frame_ids)
+
+ return stack_id, frame_ids, frames