Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(profiling): Introduce active thread id on scope #1764

Merged
merged 4 commits into from Dec 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion sentry_sdk/client.py
Expand Up @@ -433,7 +433,9 @@ def capture_event(

if is_transaction:
if profile is not None:
envelope.add_profile(profile.to_json(event_opt, self.options))
envelope.add_profile(
profile.to_json(event_opt, self.options, scope)
)
envelope.add_transaction(event_opt)
else:
envelope.add_event(event_opt)
Expand Down
14 changes: 11 additions & 3 deletions sentry_sdk/profiler.py
Expand Up @@ -51,6 +51,7 @@
from typing import Sequence
from typing import Tuple
from typing_extensions import TypedDict
import sentry_sdk.scope
import sentry_sdk.tracing

RawStack = Tuple[RawFrameData, ...]
Expand Down Expand Up @@ -267,8 +268,8 @@ def __exit__(self, ty, value, tb):
self.scheduler.stop_profiling()
self._stop_ns = nanosecond_time()

def to_json(self, event_opt, options):
# type: (Any, Dict[str, Any]) -> Dict[str, Any]
def to_json(self, event_opt, options, scope):
# type: (Any, Dict[str, Any], Optional[sentry_sdk.scope.Scope]) -> Dict[str, Any]
assert self._start_ns is not None
assert self._stop_ns is not None

Expand All @@ -280,6 +281,9 @@ def to_json(self, event_opt, options):
profile["frames"], options["in_app_exclude"], options["in_app_include"]
)

# the active thread id from the scope always take priorty if it exists
active_thread_id = None if scope is None else scope.active_thread_id

return {
"environment": event_opt.get("environment"),
"event_id": uuid.uuid4().hex,
Expand Down Expand Up @@ -311,7 +315,11 @@ def to_json(self, event_opt, options):
# because we end the transaction after the profile
"relative_end_ns": str(self._stop_ns - self._start_ns),
"trace_id": self.transaction.trace_id,
"active_thread_id": str(self.transaction._active_thread_id),
"active_thread_id": str(
self.transaction._active_thread_id
if active_thread_id is None
else active_thread_id
),
}
],
}
Expand Down
21 changes: 21 additions & 0 deletions sentry_sdk/scope.py
Expand Up @@ -94,6 +94,10 @@ class Scope(object):
"_session",
"_attachments",
"_force_auto_session_tracking",
# The thread that is handling the bulk of the work. This can just
# be the main thread, but that's not always true. For web frameworks,
# this would be the thread handling the request.
"_active_thread_id",
)

def __init__(self):
Expand Down Expand Up @@ -125,6 +129,8 @@ def clear(self):
self._session = None # type: Optional[Session]
self._force_auto_session_tracking = None # type: Optional[bool]

self._active_thread_id = None # type: Optional[int]

@_attr_setter
def level(self, value):
# type: (Optional[str]) -> None
Expand Down Expand Up @@ -228,6 +234,17 @@ def span(self, span):
if transaction.name:
self._transaction = transaction.name

@property
def active_thread_id(self):
# type: () -> Optional[int]
"""Get/set the current active thread id."""
return self._active_thread_id

def set_active_thread_id(self, active_thread_id):
# type: (Optional[int]) -> None
"""Set the current active thread id."""
self._active_thread_id = active_thread_id

def set_tag(
self,
key, # type: str
Expand Down Expand Up @@ -447,6 +464,8 @@ def update_from_scope(self, scope):
self._span = scope._span
if scope._attachments:
self._attachments.extend(scope._attachments)
if scope._active_thread_id is not None:
self._active_thread_id = scope._active_thread_id

def update_from_kwargs(
self,
Expand Down Expand Up @@ -496,6 +515,8 @@ def __copy__(self):
rv._force_auto_session_tracking = self._force_auto_session_tracking
rv._attachments = list(self._attachments)

rv._active_thread_id = self._active_thread_id

return rv

def __repr__(self):
Expand Down