Skip to content

Commit 17e92b3

Browse files
authored
ref(profiling): Rename profiling frame keys (getsentry#1680)
Standardizing the names of the keys in the frames across SDKs so we're going to rename them.
1 parent bb879ab commit 17e92b3

2 files changed

Lines changed: 338 additions & 29 deletions

File tree

sentry_sdk/profiler.py

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
from sentry_sdk._types import MYPY
3030
from sentry_sdk.utils import nanosecond_time
3131

32+
RawFrameData = namedtuple("RawFrameData", ["function", "abs_path", "lineno"])
33+
3234
if MYPY:
3335
from types import FrameType
3436
from typing import Any
@@ -39,10 +41,46 @@
3941
from typing import List
4042
from typing import Optional
4143
from typing import Sequence
44+
from typing import Tuple
45+
from typing_extensions import TypedDict
4246
import sentry_sdk.tracing
4347

44-
45-
FrameData = namedtuple("FrameData", ["name", "file", "line"])
48+
RawSampleData = Tuple[int, Sequence[Tuple[int, Sequence[RawFrameData]]]]
49+
50+
ProcessedStack = Tuple[int, ...]
51+
52+
ProcessedSample = TypedDict(
53+
"ProcessedSample",
54+
{
55+
"elapsed_since_start_ns": str,
56+
"thread_id": str,
57+
"stack_id": int,
58+
},
59+
)
60+
61+
ProcessedFrame = TypedDict(
62+
"ProcessedFrame",
63+
{
64+
"function": str,
65+
"filename": str,
66+
"lineno": int,
67+
},
68+
)
69+
70+
ProcessedThreadMetadata = TypedDict(
71+
"ProcessedThreadMetadata",
72+
{"name": str},
73+
)
74+
75+
ProcessedProfile = TypedDict(
76+
"ProcessedProfile",
77+
{
78+
"frames": List[ProcessedFrame],
79+
"stacks": List[ProcessedStack],
80+
"samples": List[ProcessedSample],
81+
"thread_metadata": Dict[str, ProcessedThreadMetadata],
82+
},
83+
)
4684

4785

4886
_sample_buffer = None # type: Optional[SampleBuffer]
@@ -132,7 +170,7 @@ def _sample_stack(*args, **kwargs):
132170

133171

134172
def extract_stack(frame, max_stack_depth=MAX_STACK_DEPTH):
135-
# type: (Optional[FrameType], int) -> Sequence[FrameData]
173+
# type: (Optional[FrameType], int) -> Sequence[RawFrameData]
136174
"""
137175
Extracts the stack starting the specified frame. The extracted stack
138176
assumes the specified frame is the top of the stack, and works back
@@ -149,10 +187,10 @@ def extract_stack(frame, max_stack_depth=MAX_STACK_DEPTH):
149187
frame = frame.f_back
150188

151189
return [
152-
FrameData(
153-
name=get_frame_name(frame),
154-
file=frame.f_code.co_filename,
155-
line=frame.f_lineno,
190+
RawFrameData(
191+
function=get_frame_name(frame),
192+
abs_path=frame.f_code.co_filename,
193+
lineno=frame.f_lineno,
156194
)
157195
for frame in stack
158196
]
@@ -268,12 +306,12 @@ class SampleBuffer(object):
268306
def __init__(self, capacity):
269307
# type: (int) -> None
270308

271-
self.buffer = [None] * capacity
272-
self.capacity = capacity
273-
self.idx = 0
309+
self.buffer = [None] * capacity # type: List[Optional[RawSampleData]]
310+
self.capacity = capacity # type: int
311+
self.idx = 0 # type: int
274312

275313
def write(self, sample):
276-
# type: (Any) -> None
314+
# type: (RawSampleData) -> None
277315
"""
278316
Writing to the buffer is not thread safe. There is the possibility
279317
that parallel writes will overwrite one another.
@@ -290,12 +328,12 @@ def write(self, sample):
290328
self.idx = (idx + 1) % self.capacity
291329

292330
def slice_profile(self, start_ns, stop_ns):
293-
# type: (int, int) -> Dict[str, Any]
294-
samples = [] # type: List[Any]
295-
stacks = dict() # type: Dict[Any, int]
296-
stacks_list = list() # type: List[Any]
297-
frames = dict() # type: Dict[FrameData, int]
298-
frames_list = list() # type: List[Any]
331+
# type: (int, int) -> ProcessedProfile
332+
samples = [] # type: List[ProcessedSample]
333+
stacks = dict() # type: Dict[ProcessedStack, int]
334+
stacks_list = list() # type: List[ProcessedStack]
335+
frames = dict() # type: Dict[RawFrameData, int]
336+
frames_list = list() # type: List[ProcessedFrame]
299337

300338
# TODO: This is doing an naive iteration over the
301339
# buffer and extracting the appropriate samples.
@@ -311,20 +349,16 @@ def slice_profile(self, start_ns, stop_ns):
311349
continue
312350

313351
for tid, stack in raw_sample[1]:
314-
sample = {
315-
"elapsed_since_start_ns": str(ts - start_ns),
316-
"thread_id": str(tid),
317-
}
318352
current_stack = []
319353

320354
for frame in stack:
321355
if frame not in frames:
322356
frames[frame] = len(frames)
323357
frames_list.append(
324358
{
325-
"name": frame.name,
326-
"file": frame.file,
327-
"line": frame.line,
359+
"function": frame.function,
360+
"filename": frame.abs_path,
361+
"lineno": frame.lineno,
328362
}
329363
)
330364
current_stack.append(frames[frame])
@@ -334,8 +368,13 @@ def slice_profile(self, start_ns, stop_ns):
334368
stacks[current_stack] = len(stacks)
335369
stacks_list.append(current_stack)
336370

337-
sample["stack_id"] = stacks[current_stack]
338-
samples.append(sample)
371+
samples.append(
372+
{
373+
"elapsed_since_start_ns": str(ts - start_ns),
374+
"thread_id": str(tid),
375+
"stack_id": stacks[current_stack],
376+
}
377+
)
339378

340379
# This collects the thread metadata at the end of a profile. Doing it
341380
# this way means that any threads that terminate before the profile ends
@@ -345,7 +384,7 @@ def slice_profile(self, start_ns, stop_ns):
345384
"name": thread.name,
346385
}
347386
for thread in threading.enumerate()
348-
}
387+
} # type: Dict[str, ProcessedThreadMetadata]
349388

350389
return {
351390
"stacks": stacks_list,

0 commit comments

Comments
 (0)