Skip to content

Commit 52b75d9

Browse files
committed
signal handling improvements, more debug logging
1 parent 666eb62 commit 52b75d9

File tree

9 files changed

+50
-19
lines changed

9 files changed

+50
-19
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name = 'stackimpact',
5-
version = '1.0.0',
5+
version = '1.0.1',
66
description = 'StackImpact Python Agent',
77
author = 'StackImpact',
88
author_email = 'devops@stackimpact.com',

stackimpact/agent.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
import os
1010
import signal
1111
import atexit
12+
import platform
1213

13-
from .runtime import min_version, runtime_info
14+
from .runtime import min_version, runtime_info, register_signal
1415
from .utils import timestamp, generate_uuid
1516
from .config import Config
1617
from .config_loader import ConfigLoader
@@ -25,7 +26,7 @@
2526

2627
class Agent:
2728

28-
AGENT_VERSION = "1.0.0"
29+
AGENT_VERSION = "1.0.1"
2930
SAAS_DASHBOARD_ADDRESS = "https://agent-api.stackimpact.com"
3031

3132
def __init__(self, **kwargs):
@@ -62,6 +63,9 @@ def start(self, **kwargs):
6263
if not min_version(2, 7) and not min_version(3, 4):
6364
raise Exception('Supported Python versions 2.6 or highter and 3.4 or higher')
6465

66+
if platform.python_implementation() != 'CPython':
67+
raise Exception('Supported Python interpreter is CPython')
68+
6569
if self.agent_destroyed:
6670
self.log('Destroyed agent cannot be started')
6771
return
@@ -106,10 +110,12 @@ def _signal_handler(signum, frame):
106110
except Exception:
107111
self.exception()
108112

109-
signal.signal(signal.SIGUSR2, _signal_handler)
113+
return True
114+
115+
register_signal(signal.SIGUSR2, _signal_handler)
110116

111117
# destroy agent on exit
112-
def _exit():
118+
def _exit_handler(*arg):
113119
if not self.agent_started or self.agent_destroyed:
114120
return
115121

@@ -120,7 +126,12 @@ def _exit():
120126
self.exception()
121127

122128

123-
atexit.register(_exit)
129+
atexit.register(_exit_handler)
130+
131+
register_signal(signal.SIGQUIT, _exit_handler)
132+
register_signal(signal.SIGINT, _exit_handler)
133+
register_signal(signal.SIGTERM, _exit_handler)
134+
register_signal(signal.SIGHUP, _exit_handler)
124135

125136
self.agent_started = True
126137
self.log('Agent started')

stackimpact/frame_selector.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,7 @@ def start(self):
6464

6565

6666
def destroy(self):
67-
self.agent_frame_cache = None
68-
self.system_frame_cache = None
69-
self.http_frame_cache = None
70-
71-
self.http_frame_regexp = None
67+
pass
7268

7369

7470
def is_agent_frame(self, filename):

stackimpact/message_queue.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ def start(self):
2525

2626

2727
def destroy(self):
28-
self.queue = []
29-
3028
if self.flush_timer:
3129
self.flush_timer.cancel()
3230
self.flush_timer = None

stackimpact/reporters/allocation_reporter.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ def reset(self):
6363

6464

6565
def record(self, max_duration):
66+
if self.agent.config.is_profiling_disabled():
67+
return
68+
69+
self.agent.log('Activating memory allocation profiler.')
70+
6671
def start():
6772
tracemalloc.start(self.MAX_TRACEBACK_SIZE)
6873
self.agent.run_in_main_thread(start)
@@ -76,6 +81,8 @@ def start():
7681
if tracemalloc.get_tracemalloc_memory() > self.MAX_MEMORY_OVERHEAD:
7782
break
7883

84+
self.agent.log('Deactivating memory allocation profiler.')
85+
7986
if tracemalloc.is_tracing():
8087
snapshot = tracemalloc.take_snapshot()
8188
self.agent.log('Allocation profiler memory overhead {0} bytes'.format(tracemalloc.get_tracemalloc_memory()))

stackimpact/reporters/block_reporter.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,14 @@ def record(self, duration):
103103
if self.agent.config.is_profiling_disabled():
104104
return
105105

106+
self.agent.log('Activating blocking call profiler.')
107+
106108
signal.setitimer(signal.ITIMER_REAL, self.SAMPLING_RATE, self.SAMPLING_RATE)
107109
time.sleep(duration)
108110
signal.setitimer(signal.ITIMER_REAL, 0)
109111

112+
self.agent.log('Deactivating blocking call profiler.')
113+
110114
self.profile_duration += duration
111115

112116
self.agent.log('Time profiler CPU overhead per activity second: {0} seconds'.format(self.block_profile._overhead / self.profile_duration))
@@ -152,17 +156,15 @@ def update_http_profile(self, stack, sample_time):
152156
include = False
153157
for frame in stack:
154158
if self.agent.frame_selector.is_http_frame(frame.filename):
155-
frame._skip = True
156159
include = True
157160

158161
if include:
159162
current_node = self.http_profile
160163
current_node.increment(sample_time, 1)
161164

162165
for frame in reversed(stack):
163-
if not frame._skip:
164-
current_node = current_node.find_or_add_child(str(frame))
165-
current_node.increment(sample_time, 1)
166+
current_node = current_node.find_or_add_child(str(frame))
167+
current_node.increment(sample_time, 1)
166168

167169

168170
def report(self):

stackimpact/reporters/cpu_reporter.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,14 @@ def record(self, duration):
8686
if self.agent.config.is_profiling_disabled():
8787
return
8888

89+
self.agent.log('Activating CPU profiler.')
90+
8991
signal.setitimer(signal.ITIMER_PROF, self.SAMPLING_RATE, self.SAMPLING_RATE)
9092
time.sleep(duration)
9193
signal.setitimer(signal.ITIMER_PROF, 0)
9294

95+
self.agent.log('Deactivating CPU profiler.')
96+
9397
self.profile_duration += duration
9498

9599
self.agent.log('CPU profiler CPU overhead per activity second: {0} seconds'.format(self.profile._overhead / self.profile_duration))

stackimpact/reporters/error_reporter.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ def destroy(self):
5353

5454
unpatch(sys, 'exc_info')
5555

56-
self.reset_profile()
57-
5856
if self.process_timer:
5957
self.process_timer.cancel()
6058
self.process_timer = None

stackimpact/runtime.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import resource
55
import re
66
import os
7+
import signal
78
from functools import wraps
89

910

@@ -117,3 +118,17 @@ def unpatch(obj, func_name):
117118
return
118119

119120
setattr(obj, func_name, getattr(wrapper, '__stackimpact_orig__'))
121+
122+
123+
def register_signal(signal_number, handler_func):
124+
prev_handler = signal.SIG_IGN
125+
def _handler(signum, frame):
126+
skip_prev = handler_func(signum, frame)
127+
128+
if not skip_prev and prev_handler not in [signal.SIG_IGN, signal.SIG_DFL] and callable(prev_handler):
129+
prev_handler(signum, frame)
130+
131+
prev_handler = signal.signal(signal_number, signal.SIG_IGN)
132+
if prev_handler != signal.SIG_IGN:
133+
signal.signal(signal_number, _handler)
134+

0 commit comments

Comments
 (0)