Skip to content

Commit f2d3814

Browse files
committed
feat(profiling): Enable profiling on all transactions
Up to now, we've only been profiling WSGI transactions. This change will enable profiling for all transactions.
1 parent b300b10 commit f2d3814

File tree

4 files changed

+37
-12
lines changed

4 files changed

+37
-12
lines changed

sentry_sdk/hub.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ def start_transaction(
547547
}
548548
sampling_context.update(custom_sampling_context)
549549
transaction._set_initial_sampling_decision(sampling_context=sampling_context)
550+
transaction._set_profiling_decision()
550551

551552
# we don't bother to keep spans if we already know we're not going to
552553
# send the transaction

sentry_sdk/integrations/wsgi.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from sentry_sdk.tracing import Transaction, TRANSACTION_SOURCE_ROUTE
1313
from sentry_sdk.sessions import auto_session_tracking
1414
from sentry_sdk.integrations._wsgi_common import _filter_headers
15-
from sentry_sdk.profiler import start_profiling
1615

1716
from sentry_sdk._types import MYPY
1817

@@ -132,7 +131,7 @@ def __call__(self, environ, start_response):
132131

133132
with hub.start_transaction(
134133
transaction, custom_sampling_context={"wsgi_environ": environ}
135-
), start_profiling(transaction, hub):
134+
):
136135
try:
137136
rv = self.app(
138137
environ,

sentry_sdk/profiler.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -316,16 +316,24 @@ def __init__(
316316

317317
transaction._profile = self
318318

319-
def __enter__(self):
319+
def start(self):
320320
# type: () -> None
321321
self.start_ns = nanosecond_time()
322322
self.scheduler.start_profiling(self)
323323

324-
def __exit__(self, ty, value, tb):
325-
# type: (Optional[Any], Optional[Any], Optional[Any]) -> None
324+
def stop(self):
325+
# type: () -> None
326326
self.scheduler.stop_profiling(self)
327327
self.stop_ns = nanosecond_time()
328328

329+
def __enter__(self):
330+
# type: () -> None
331+
self.start()
332+
333+
def __exit__(self, ty, value, tb):
334+
# type: (Optional[Any], Optional[Any], Optional[Any]) -> None
335+
self.stop()
336+
329337
def write(self, ts, sample):
330338
# type: (int, RawSample) -> None
331339
if ts < self.start_ns:
@@ -437,6 +445,15 @@ def to_json(self, event_opt, options, scope):
437445
],
438446
}
439447

448+
@staticmethod
449+
def from_transaction(transaction, hub):
450+
# type: (sentry_sdk.tracing.Transaction, Optional[sentry_sdk.Hub]) -> Optional[Profile]
451+
if not _should_profile(transaction, hub):
452+
return None
453+
454+
assert _scheduler is not None
455+
return Profile(_scheduler, transaction)
456+
440457

441458
class Scheduler(object):
442459
mode = "unknown"
@@ -632,7 +649,7 @@ def run(self):
632649

633650

634651
def _should_profile(transaction, hub):
635-
# type: (sentry_sdk.tracing.Transaction, sentry_sdk.Hub) -> bool
652+
# type: (sentry_sdk.tracing.Transaction, Optional[sentry_sdk.Hub]) -> bool
636653

637654
# The corresponding transaction was not sampled,
638655
# so don't generate a profile for it.
@@ -643,6 +660,7 @@ def _should_profile(transaction, hub):
643660
if _scheduler is None:
644661
return False
645662

663+
hub = hub or sentry_sdk.Hub.current
646664
client = hub.client
647665

648666
# The client is None, so we can't get the sample rate.
@@ -663,12 +681,12 @@ def _should_profile(transaction, hub):
663681
@contextmanager
664682
def start_profiling(transaction, hub=None):
665683
# type: (sentry_sdk.tracing.Transaction, Optional[sentry_sdk.Hub]) -> Generator[None, None, None]
666-
hub = hub or sentry_sdk.Hub.current
684+
685+
transaction._profile = Profile.from_transaction(transaction, hub)
667686

668687
# if profiling was not enabled, this should be a noop
669-
if _should_profile(transaction, hub):
670-
assert _scheduler is not None
671-
with Profile(_scheduler, transaction):
688+
if transaction._profile is not None:
689+
with transaction._profile:
672690
yield
673691
else:
674692
yield

sentry_sdk/tracing.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import sentry_sdk
99
from sentry_sdk.consts import INSTRUMENTER
10+
from sentry_sdk.profiler import Profile
1011
from sentry_sdk.utils import logger
1112
from sentry_sdk._types import MYPY
1213

@@ -21,7 +22,6 @@
2122
from typing import Tuple
2223
from typing import Iterator
2324

24-
import sentry_sdk.profiler
2525
from sentry_sdk._types import Event, SamplingContext, MeasurementUnit
2626

2727
BAGGAGE_HEADER_NAME = "baggage"
@@ -604,7 +604,7 @@ def __init__(
604604
self._third_party_tracestate = third_party_tracestate
605605
self._measurements = {} # type: Dict[str, Any]
606606
self._contexts = {} # type: Dict[str, Any]
607-
self._profile = None # type: Optional[sentry_sdk.profiler.Profile]
607+
self._profile = None # type: Optional[Profile]
608608
self._baggage = baggage
609609
# for profiling, we want to know on which thread a transaction is started
610610
# to accurately show the active thread in the UI
@@ -708,6 +708,7 @@ def finish(self, hub=None, end_timestamp=None):
708708
} # type: Event
709709

710710
if hub.client is not None and self._profile is not None:
711+
self._profile.stop()
711712
event["profile"] = self._profile
712713

713714
if has_custom_measurements_enabled():
@@ -853,6 +854,12 @@ def _set_initial_sampling_decision(self, sampling_context):
853854
)
854855
)
855856

857+
def _set_profiling_decision(self):
858+
# type: () -> None
859+
self._profile = Profile.from_transaction(self, self.hub)
860+
if self._profile is not None:
861+
self._profile.start()
862+
856863

857864
class NoOpSpan(Span):
858865
def __repr__(self):

0 commit comments

Comments
 (0)