Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 52b75d9

Browse filesBrowse files
committed
signal handling improvements, more debug logging
1 parent 666eb62 commit 52b75d9
Copy full SHA for 52b75d9

9 files changed

+50
-19
lines changed

‎setup.py

Copy file name to clipboardExpand all lines: setup.py
+1-1
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

Copy file name to clipboardExpand all lines: stackimpact/agent.py
+16-5
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

Copy file name to clipboardExpand all lines: stackimpact/frame_selector.py
+1-5
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

Copy file name to clipboardExpand all lines: stackimpact/message_queue.py
-2
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

Copy file name to clipboardExpand all lines: stackimpact/reporters/allocation_reporter.py
+7
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

Copy file name to clipboardExpand all lines: stackimpact/reporters/block_reporter.py
+6-4
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

Copy file name to clipboardExpand all lines: stackimpact/reporters/cpu_reporter.py
+4
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

Copy file name to clipboardExpand all lines: stackimpact/reporters/error_reporter.py
-2
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

Copy file name to clipboardExpand all lines: stackimpact/runtime.py
+15
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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.