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 9b15b18

Browse filesBrowse files
committed
auto_destroy option
1 parent b32bf14 commit 9b15b18
Copy full SHA for 9b15b18

14 files changed

+54
-59
lines changed

‎README.md

Copy file name to clipboardExpand all lines: README.md
+2-1
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,14 @@ Add the agent initialization to the worker code, e.g. wsgi.py, if applicable.
7171
All initialization options:
7272

7373
* `agent_key` (Required) The access key for communication with the StackImpact servers.
74-
* `app_name` (Required) A name to identify and group application data. Typically, a single codebase corresponds to one application.
74+
* `app_name` (Required) A name to identify and group application data. Typically, a single codebase, deployable unit or executable module corresponds to one application.
7575
* `app_version` (Optional) Sets application version, which can be used to associate profiling information with the source code release.
7676
* `app_environment` (Optional) Used to differentiate applications in different environments.
7777
* `host_name` (Optional) By default, host name will be the OS hostname.
7878
* `debug` (Optional) Enables debug logging.
7979
* `cpu_profiler_disabled`, `allocation_profiler_disabled`, `block_profiler_disabled`, `error_profiler_disabled` (Optional) Disables respective profiler when `True`.
8080
* `include_agent_frames`, `include_system_frames` (Optional) Set to `True` to not exclude agent and/or system stack frames from profiles.
81+
* `auto_destroy` (Optional) Set to `False` to disable agent's exit handlers. If necessary, call `destroy()` to gracefully shutdown the agent.
8182

8283

8384

‎README.rst

Copy file name to clipboardExpand all lines: README.rst
+6-2
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,11 @@ applicable.
9191

9292
All initialization options:
9393

94-
- ``agent_key`` (Required) The access key for communication with
94+
- ``agent_key`` (Required) The access key for communication with the
9595
StackImpact servers.
9696
- ``app_name`` (Required) A name to identify and group application
97-
data. Typically, single codebase corresponds to one application.
97+
data. Typically, a single codebase, deployable unit or executable
98+
module corresponds to one application.
9899
- ``app_version`` (Optional) Sets application version, which can be
99100
used to associate profiling information with the source code release.
100101
- ``app_environment`` (Optional) Used to differentiate applications in
@@ -108,6 +109,9 @@ All initialization options:
108109
- ``include_agent_frames``, ``include_system_frames`` (Optional) Set to
109110
``True`` to not exclude agent and/or system stack frames from
110111
profiles.
112+
- ``auto_destroy`` (Optional) Set to ``False`` to disable agent's exit
113+
handlers. If necessary, call ``destroy()`` to gracefully shutdown the
114+
agent.
111115

112116
Analyzing performance data in the Dashboard
113117
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

‎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.4',
5+
version = '1.0.5',
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
+18-17
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
class Agent:
2828

29-
AGENT_VERSION = "1.0.4"
29+
AGENT_VERSION = "1.0.5"
3030
SAAS_DASHBOARD_ADDRESS = "https://agent-api.stackimpact.com"
3131

3232
def __init__(self, **kwargs):
@@ -61,7 +61,7 @@ def get_option(self, name, default_val = None):
6161

6262
def start(self, **kwargs):
6363
if not min_version(2, 7) and not min_version(3, 4):
64-
raise Exception('Supported Python versions 2.6 or highter and 3.4 or higher')
64+
raise Exception('Supported Python versions 2.6 or higher and 3.4 or higher')
6565

6666
if platform.python_implementation() != 'CPython':
6767
raise Exception('Supported Python interpreter is CPython')
@@ -114,24 +114,26 @@ def _signal_handler(signum, frame):
114114

115115
register_signal(signal.SIGUSR2, _signal_handler)
116116

117-
# destroy agent on exit
118-
def _exit_handler(*arg):
119-
if not self.agent_started or self.agent_destroyed:
120-
return
117+
if self.get_option('auto_destroy') == False:
118+
# destroy agent on exit
119+
def _exit_handler(*arg):
120+
if not self.agent_started or self.agent_destroyed:
121+
return
122+
123+
try:
124+
self.message_queue.flush()
125+
self.destroy()
126+
except Exception:
127+
self.exception()
121128

122-
try:
123-
self.message_queue.flush()
124-
self.destroy()
125-
except Exception:
126-
self.exception()
127129

130+
atexit.register(_exit_handler)
128131

129-
atexit.register(_exit_handler)
132+
register_signal(signal.SIGQUIT, _exit_handler, once = True)
133+
register_signal(signal.SIGINT, _exit_handler, once = True)
134+
register_signal(signal.SIGTERM, _exit_handler, once = True)
135+
register_signal(signal.SIGHUP, _exit_handler, once = True)
130136

131-
register_signal(signal.SIGQUIT, _exit_handler, ignore_default = False)
132-
register_signal(signal.SIGINT, _exit_handler, ignore_default = False)
133-
register_signal(signal.SIGTERM, _exit_handler, ignore_default = False)
134-
register_signal(signal.SIGHUP, _exit_handler, ignore_default = False)
135137

136138
self.agent_started = True
137139
self.log('Agent started')
@@ -178,7 +180,6 @@ def error(self, message):
178180

179181
def exception(self):
180182
if self.get_option('debug'):
181-
self.print_err(sys.exc_info()[0])
182183
traceback.print_exc()
183184

184185

‎stackimpact/api_request.py

Copy file name to clipboardExpand all lines: stackimpact/api_request.py
+3-2
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ def post(self, endpoint, payload):
3333
'Content-Encoding': 'gzip'
3434
}
3535

36-
host_name = 'host'
36+
host_name = 'undefined'
3737
try:
3838
host_name = socket.gethostname()
3939
except Exception:
40-
pass
40+
self.agent.exception()
4141

4242
req_body = {
4343
'runtime_type': 'python',
@@ -71,6 +71,7 @@ def post(self, endpoint, payload):
7171
headers = headers)
7272

7373
response = urlopen(request, timeout = 20)
74+
7475
result_data = response.read()
7576

7677
if response.info():

‎stackimpact/metric.py

Copy file name to clipboardExpand all lines: stackimpact/metric.py
+7
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,13 @@ def normalize(self, factor):
285285
child.normalize(factor)
286286

287287

288+
def floor(self):
289+
self.measurement = int(self.measurement)
290+
291+
for name, child in self.children.items():
292+
child.floor()
293+
294+
288295
def to_dict(self):
289296
children_map = []
290297
for name, child in self.children.items():

‎stackimpact/reporters/allocation_reporter.py

Copy file name to clipboardExpand all lines: stackimpact/reporters/allocation_reporter.py
+1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ def report(self):
130130
return
131131

132132
self.profile.normalize(self.profile_duration)
133+
self.profile.floor()
133134
self.profile.filter(2, 1000, float("inf"))
134135

135136
metric = Metric(self.agent, Metric.TYPE_PROFILE, Metric.CATEGORY_MEMORY_PROFILE, Metric.NAME_UNCOLLECTED_ALLOCATIONS, Metric.UNIT_BYTE)

‎stackimpact/reporters/block_reporter.py

Copy file name to clipboardExpand all lines: stackimpact/reporters/block_reporter.py
+1
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ def report(self):
189189

190190
with self.profile_lock:
191191
self.block_profile.normalize(self.profile_duration)
192+
self.block_profile.floor()
192193
self.block_profile.filter(2, 1, float("inf"))
193194

194195
metric = Metric(self.agent, Metric.TYPE_PROFILE, Metric.CATEGORY_BLOCK_PROFILE, Metric.NAME_BLOCKING_CALL_TIMES, Metric.UNIT_MILLISECOND)

‎stackimpact/reporters/process_reporter.py

Copy file name to clipboardExpand all lines: stackimpact/reporters/process_reporter.py
+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def __init__(self, agent):
1919

2020

2121
def start(self):
22-
self.report_timer = self.agent.schedule(5, 60, self.report)
22+
self.report_timer = self.agent.schedule(60, 60, self.report)
2323

2424

2525
def destroy(self):

‎stackimpact/runtime.py

Copy file name to clipboardExpand all lines: stackimpact/runtime.py
+4-2
Original file line numberDiff line numberDiff line change
@@ -122,16 +122,18 @@ def unpatch(obj, func_name):
122122
setattr(obj, func_name, getattr(wrapper, '__stackimpact_orig__'))
123123

124124

125-
def register_signal(signal_number, handler_func, ignore_default = True):
125+
def register_signal(signal_number, handler_func, once = False):
126126
prev_handler = None
127127

128128
def _handler(signum, frame):
129129
skip_prev = handler_func(signum, frame)
130130

131131
if not skip_prev:
132132
if callable(prev_handler):
133+
if once:
134+
signal.signal(signum, prev_handler)
133135
prev_handler(signum, frame)
134-
elif prev_handler == signal.SIG_DFL and not ignore_default:
136+
elif prev_handler == signal.SIG_DFL and once:
135137
signal.signal(signum, signal.SIG_DFL)
136138
os.kill(os.getpid(), signum)
137139

‎tests/agent_test.py

Copy file name to clipboardExpand all lines: tests/agent_test.py
+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import stackimpact
66

77

8-
# python -m unittest discover -s tests -p *_test.py
8+
# python3 -m unittest discover -s tests -p *_test.py
99

1010
class AgentTestCase(unittest.TestCase):
1111

‎tests/runtime_test.py

Copy file name to clipboardExpand all lines: tests/runtime_test.py
+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def _handler(signum, frame):
3030
def _handler(signum, frame):
3131
result['handler'] += 1
3232
33-
register_signal(signal.SIGUSR1, _handler, ignore_default = False)
33+
register_signal(signal.SIGUSR1, _handler, once = True)
3434
3535
os.kill(os.getpid(), signal.SIGUSR1)
3636
os.kill(os.getpid(), signal.SIGUSR1)

‎tests/test.py

Copy file name to clipboardExpand all lines: tests/test.py
-29
This file was deleted.

‎tests/test_server.py

Copy file name to clipboardExpand all lines: tests/test_server.py
+8-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ def __init__(self, port, delay = None, handler_func = None):
2121
self.port = port
2222
RequestHandler.delay = delay
2323
RequestHandler.handler_func = [handler_func]
24+
RequestHandler.response_data = '{}'
25+
RequestHandler.response_code = 200
2426
threading.Thread.__init__(self)
2527
self.server = HTTPServer(('localhost', self.port), RequestHandler)
2628

@@ -30,6 +32,9 @@ def get_request_data(self):
3032
def set_response_data(self, response_data):
3133
RequestHandler.response_data = response_data
3234

35+
def set_response_code(self, response_code):
36+
RequestHandler.response_code = response_code
37+
3338
def run(self):
3439
self.server.handle_request()
3540

@@ -39,6 +44,7 @@ class RequestHandler(BaseHTTPRequestHandler):
3944
handler_func = None
4045
request_data = None
4146
response_data = '{}'
47+
response_code = 200
4248

4349

4450
def do_GET(self):
@@ -48,7 +54,7 @@ def do_GET(self):
4854
if RequestHandler.handler_func:
4955
RequestHandler.handler_func[0]()
5056

51-
self.send_response(200)
57+
self.send_response(RequestHandler.response_code)
5258
self.send_header('Content-Type', 'application/json')
5359
self.end_headers()
5460
self.wfile.write(RequestHandler.response_data.encode('utf-8'))
@@ -64,7 +70,7 @@ def do_POST(self):
6470
decompressed_data = gzip.GzipFile(fileobj=BytesIO(self.rfile.read(content_len))).read()
6571
RequestHandler.request_data = decompressed_data.decode('utf-8')
6672

67-
self.send_response(200)
73+
self.send_response(RequestHandler.response_code)
6874
self.send_header('Content-Type', 'application/json')
6975
self.end_headers()
7076
self.wfile.write(RequestHandler.response_data.encode('utf-8'))

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.