Skip to content

Commit 7baab35

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 a4ba6a8 commit 7baab35

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
@@ -308,16 +308,24 @@ def __init__(
308308

309309
transaction._profile = self
310310

311-
def __enter__(self):
311+
def start(self):
312312
# type: () -> None
313313
self.start_ns = nanosecond_time()
314314
self.scheduler.start_profiling(self)
315315

316-
def __exit__(self, ty, value, tb):
317-
# type: (Optional[Any], Optional[Any], Optional[Any]) -> None
316+
def stop(self):
317+
# type: () -> None
318318
self.scheduler.stop_profiling(self)
319319
self.stop_ns = nanosecond_time()
320320

321+
def __enter__(self):
322+
# type: () -> None
323+
self.start()
324+
325+
def __exit__(self, ty, value, tb):
326+
# type: (Optional[Any], Optional[Any], Optional[Any]) -> None
327+
self.stop()
328+
321329
def write(self, ts, sample):
322330
# type: (int, RawSample) -> None
323331
if ts < self.start_ns:
@@ -429,6 +437,15 @@ def to_json(self, event_opt, options, scope):
429437
],
430438
}
431439

440+
@staticmethod
441+
def from_transaction(transaction, hub):
442+
# type: (sentry_sdk.tracing.Transaction, Optional[sentry_sdk.Hub]) -> Optional[Profile]
443+
if not _should_profile(transaction, hub):
444+
return None
445+
446+
assert _scheduler is not None
447+
return Profile(_scheduler, transaction)
448+
432449

433450
class Scheduler(object):
434451
mode = "unknown"
@@ -644,7 +661,7 @@ def run(self):
644661

645662

646663
def _should_profile(transaction, hub):
647-
# type: (sentry_sdk.tracing.Transaction, sentry_sdk.Hub) -> bool
664+
# type: (sentry_sdk.tracing.Transaction, Optional[sentry_sdk.Hub]) -> bool
648665

649666
# The corresponding transaction was not sampled,
650667
# so don't generate a profile for it.
@@ -655,6 +672,7 @@ def _should_profile(transaction, hub):
655672
if _scheduler is None:
656673
return False
657674

675+
hub = hub or sentry_sdk.Hub.current
658676
client = hub.client
659677

660678
# The client is None, so we can't get the sample rate.
@@ -675,12 +693,12 @@ def _should_profile(transaction, hub):
675693
@contextmanager
676694
def start_profiling(transaction, hub=None):
677695
# type: (sentry_sdk.tracing.Transaction, Optional[sentry_sdk.Hub]) -> Generator[None, None, None]
678-
hub = hub or sentry_sdk.Hub.current
696+
697+
transaction._profile = Profile.from_transaction(transaction, hub)
679698

680699
# if profiling was not enabled, this should be a noop
681-
if _should_profile(transaction, hub):
682-
assert _scheduler is not None
683-
with Profile(_scheduler, transaction):
700+
if transaction._profile is not None:
701+
with transaction._profile:
684702
yield
685703
else:
686704
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)