|
13 | 13 | """ |
14 | 14 |
|
15 | 15 | import atexit |
| 16 | +import os |
16 | 17 | import platform |
17 | 18 | import random |
18 | 19 | import signal |
|
27 | 28 | from sentry_sdk._compat import PY33 |
28 | 29 | from sentry_sdk._queue import Queue |
29 | 30 | from sentry_sdk._types import MYPY |
30 | | -from sentry_sdk.utils import nanosecond_time |
| 31 | +from sentry_sdk.utils import ( |
| 32 | + filename_for_module, |
| 33 | + handle_in_app_impl, |
| 34 | + nanosecond_time, |
| 35 | +) |
31 | 36 |
|
32 | | -RawFrameData = namedtuple("RawFrameData", ["function", "abs_path", "lineno"]) |
| 37 | +RawFrameData = namedtuple( |
| 38 | + "RawFrameData", ["abs_path", "filename", "function", "lineno", "module"] |
| 39 | +) |
33 | 40 |
|
34 | 41 | if MYPY: |
35 | 42 | from types import FrameType |
|
61 | 68 | ProcessedFrame = TypedDict( |
62 | 69 | "ProcessedFrame", |
63 | 70 | { |
| 71 | + "abs_path": str, |
| 72 | + "filename": Optional[str], |
64 | 73 | "function": str, |
65 | | - "filename": str, |
66 | 74 | "lineno": int, |
| 75 | + "module": Optional[str], |
67 | 76 | }, |
68 | 77 | ) |
69 | 78 |
|
@@ -162,13 +171,24 @@ def extract_stack(frame, max_stack_depth=MAX_STACK_DEPTH): |
162 | 171 | stack.append(frame) |
163 | 172 | frame = frame.f_back |
164 | 173 |
|
165 | | - return tuple( |
166 | | - RawFrameData( |
167 | | - function=get_frame_name(frame), |
168 | | - abs_path=frame.f_code.co_filename, |
169 | | - lineno=frame.f_lineno, |
170 | | - ) |
171 | | - for frame in stack |
| 174 | + return tuple(extract_frame(frame) for frame in stack) |
| 175 | + |
| 176 | + |
| 177 | +def extract_frame(frame): |
| 178 | + # type: (FrameType) -> RawFrameData |
| 179 | + abs_path = frame.f_code.co_filename |
| 180 | + |
| 181 | + try: |
| 182 | + module = frame.f_globals["__name__"] |
| 183 | + except Exception: |
| 184 | + module = None |
| 185 | + |
| 186 | + return RawFrameData( |
| 187 | + abs_path=os.path.abspath(abs_path), |
| 188 | + filename=filename_for_module(module, abs_path) or None, |
| 189 | + function=get_frame_name(frame), |
| 190 | + lineno=frame.f_lineno, |
| 191 | + module=module, |
172 | 192 | ) |
173 | 193 |
|
174 | 194 |
|
@@ -243,18 +263,24 @@ def __exit__(self, ty, value, tb): |
243 | 263 | self.scheduler.stop_profiling() |
244 | 264 | self._stop_ns = nanosecond_time() |
245 | 265 |
|
246 | | - def to_json(self, event_opt): |
247 | | - # type: (Any) -> Dict[str, Any] |
| 266 | + def to_json(self, event_opt, options): |
| 267 | + # type: (Any, Dict[str, Any]) -> Dict[str, Any] |
248 | 268 | assert self._start_ns is not None |
249 | 269 | assert self._stop_ns is not None |
250 | 270 |
|
| 271 | + profile = self.scheduler.sample_buffer.slice_profile( |
| 272 | + self._start_ns, self._stop_ns |
| 273 | + ) |
| 274 | + |
| 275 | + handle_in_app_impl( |
| 276 | + profile["frames"], options["in_app_exclude"], options["in_app_include"] |
| 277 | + ) |
| 278 | + |
251 | 279 | return { |
252 | 280 | "environment": event_opt.get("environment"), |
253 | 281 | "event_id": uuid.uuid4().hex, |
254 | 282 | "platform": "python", |
255 | | - "profile": self.scheduler.sample_buffer.slice_profile( |
256 | | - self._start_ns, self._stop_ns |
257 | | - ), |
| 283 | + "profile": profile, |
258 | 284 | "release": event_opt.get("release", ""), |
259 | 285 | "timestamp": event_opt["timestamp"], |
260 | 286 | "version": "1", |
@@ -358,9 +384,11 @@ def slice_profile(self, start_ns, stop_ns): |
358 | 384 | frames[frame] = len(frames) |
359 | 385 | frames_list.append( |
360 | 386 | { |
361 | | - "function": frame.function, |
362 | | - "filename": frame.abs_path, |
| 387 | + "abs_path": frame.abs_path, |
| 388 | + "function": frame.function or "<unknown>", |
| 389 | + "filename": frame.filename, |
363 | 390 | "lineno": frame.lineno, |
| 391 | + "module": frame.module, |
364 | 392 | } |
365 | 393 | ) |
366 | 394 |
|
|
0 commit comments