@@ -137,7 +137,7 @@ def is_gevent():
137137
138138
139139def setup_profiler (options ):
140- # type: (Dict[str, Any]) -> None
140+ # type: (Dict[str, Any]) -> bool
141141 """
142142 `buffer_secs` determines the max time a sample will be buffered for
143143 `frequency` determines the number of samples to take per second (Hz)
@@ -147,11 +147,11 @@ def setup_profiler(options):
147147
148148 if _scheduler is not None :
149149 logger .debug ("profiling is already setup" )
150- return
150+ return False
151151
152152 if not PY33 :
153153 logger .warn ("profiling is only supported on Python >= 3.3" )
154- return
154+ return False
155155
156156 frequency = 101
157157
@@ -184,6 +184,8 @@ def setup_profiler(options):
184184
185185 atexit .register (teardown_profiler )
186186
187+ return True
188+
187189
188190def teardown_profiler ():
189191 # type: () -> None
@@ -410,8 +412,7 @@ def __init__(
410412 #
411413 # We cannot keep a reference to the transaction around here because it'll create
412414 # a reference cycle. So we opt to pull out just the necessary attributes.
413- self ._transaction_sampled = transaction .sampled # type: Optional[bool]
414- self .sampled = None # type: Optional[bool]
415+ self .sampled = transaction .sampled # type: Optional[bool]
415416
416417 # Various framework integrations are capable of overwriting the active thread id.
417418 # If it is set to `None` at the end of the profile, we fall back to the default.
@@ -448,7 +449,7 @@ def _set_initial_sampling_decision(self, sampling_context):
448449
449450 # The corresponding transaction was not sampled,
450451 # so don't generate a profile for it.
451- if not self ._transaction_sampled :
452+ if not self .sampled :
452453 self .sampled = False
453454 return
454455
@@ -485,19 +486,21 @@ def get_profile_context(self):
485486
486487 def start (self ):
487488 # type: () -> None
488- if not self .sampled :
489+ if not self .sampled or self . active :
489490 return
490491
491492 assert self .scheduler , "No scheduler specified"
493+ self .active = True
492494 self .start_ns = nanosecond_time ()
493495 self .scheduler .start_profiling (self )
494496
495497 def stop (self ):
496498 # type: () -> None
497- if not self .sampled :
499+ if not self .sampled or not self . active :
498500 return
499501
500502 assert self .scheduler , "No scheduler specified"
503+ self .active = False
501504 self .scheduler .stop_profiling (self )
502505 self .stop_ns = nanosecond_time ()
503506
@@ -526,11 +529,15 @@ def __exit__(self, ty, value, tb):
526529
527530 def write (self , ts , sample ):
528531 # type: (int, RawSample) -> None
532+ if not self .active :
533+ return
534+
529535 if ts < self .start_ns :
530536 return
531537
532538 offset = ts - self .start_ns
533539 if offset > MAX_PROFILE_DURATION_NS :
540+ self .stop ()
534541 return
535542
536543 elapsed_since_start_ns = str (offset )
@@ -666,12 +673,11 @@ def teardown(self):
666673
667674 def start_profiling (self , profile ):
668675 # type: (Profile) -> None
669- profile .active = True
670676 self .new_profiles .append (profile )
671677
672678 def stop_profiling (self , profile ):
673679 # type: (Profile) -> None
674- profile . active = False
680+ pass
675681
676682 def make_sampler (self ):
677683 # type: () -> Callable[..., None]
0 commit comments