9 from signal
import signal
, SIGTERM
, SIGINT
11 SESSIOND_BIN_NAME
= "lttng-sessiond"
12 SESSIOND_BIN_PATH
= "src/bin/lttng-sessiond/.libs/"
15 PRINT_BRACKET
= "\033[1;34m[\033[1;33m+\033[1;34m]\033[00m"
16 PRINT_RED_BRACKET
= "\033[1;31m[+]\033[00m"
17 PRINT_GREEN_BRACKET
= "\033[1;32m[+]\033[00m"
18 PRINT_ARROW
= "\033[1;32m-->\033[00m"
24 top_cpu_legend
= { 'us': "User CPU time", 'sy': "System CPU time",
25 'id': "Idle CPU time", 'ni': "Nice CPU time", 'wa': "iowait",
26 'hi': "Hardware IRQ", 'si': "Software Interrupts", 'st': "Steal Time", }
28 cpu_ret_q
= Queue
.Queue()
29 mem_ret_q
= Queue
.Queue()
30 test_ret_q
= Queue
.Queue()
35 def cpu_create_usage_dict(top_line
):
37 Return a dictionnary from a 'top' cpu line.
38 Ex: Cpu(s): 2.1%us, 1.2%sy, 0.0%ni, 96.2%id, 0.4%wa, 0.0%hi, 0.0%si, 0.0%st
40 top_dict
= {'us': 0, 'sy': 0, 'ni': 0, 'id': 0, 'wa': 0, 'hi': 0, 'si': 0, 'st': 0}
42 # Split expression and remove first value which is "Cpu(s)"
43 top_line
= top_line
.replace(",","")
44 words
= top_line
.split()[1:]
47 index
= word
.find('%')
48 # Add the value to the dictionnary
49 top_dict
[word
[index
+ 1:]] = float(word
[:index
])
53 def cpu_average_usage(top_lines
):
55 Return a dictionnary of 'top' CPU stats but averaging all values.
57 avg_dict
= {'us': 0, 'sy': 0, 'ni': 0, 'id': 0, 'wa': 0, 'hi': 0, 'si': 0, 'st': 0}
61 for line
in top_lines
:
62 tmp_dict
= cpu_create_usage_dict(line
)
63 # Add value to avg dictionnary
65 avg_dict
[key
] += tmp_dict
[key
]
70 avg_dict
[key
] = avg_dict
[key
] / count
72 return (count
, avg_dict
)
74 def cpu_sample_usage(pid
=None):
76 Sample CPU usage for num iterations.
77 If num is greater than 1, the average will be computed.
79 args
= ["top", "-b", "-n", "1"]
85 top
= subprocess
.Popen(args
, stdout
= subprocess
.PIPE
)
87 grep
= subprocess
.Popen(["grep", "^Cpu"], stdin
= top
.stdout
,
88 stdout
= subprocess
.PIPE
)
91 return grep
.communicate()[0].strip("\n")
93 def mem_sample_usage(pid
):
95 Sample memory usage using /proc and a pid
97 args
= ["cat", "/proc/" + str(pid
) + "/status"]
99 if not os
.path
.isfile(args
[1]):
102 mem_proc
= subprocess
.Popen(args
, stdout
= subprocess
.PIPE
)
104 grep
= subprocess
.Popen(["grep", "^VmRSS"], stdin
= mem_proc
.stdout
,
105 stdout
= subprocess
.PIPE
)
106 mem_proc
.stdout
.close()
108 # Return virtual memory size in kilobytes (kB)
109 #ret = grep.communicate()[0].split()
110 ret
= grep
.communicate()[0].split()
119 class SamplingWorker(threading
.Thread
):
120 def __init__(self
, s_type
, worker
= None, delay
= 0.2, pid
= 0):
121 threading
.Thread
.__init
__ (self
)
131 if self
.s_type
== "cpu":
133 if self
.worker
== None:
134 cpu_line
= cpu_sample_usage(self
.pid
)
135 lines
.append(cpu_line
)
137 elif self
.worker
.is_alive():
138 cpu_line
= cpu_sample_usage(self
.pid
)
139 lines
.append(cpu_line
)
143 # Delay sec per memory sampling
144 time
.sleep(self
.delay
)
146 count
, stats
= cpu_average_usage(lines
)
147 cpu_ret_q
.put((count
, stats
))
148 # grep process has ended here
150 elif self
.s_type
== "mem":
155 if self
.worker
== None:
156 cpu_line
= cpu_sample_usage(self
.pid
)
157 lines
.append(cpu_line
)
159 elif self
.worker
.is_alive():
160 mem_stat
+= get_mem_usage(self
.pid
)
165 # Delay sec per memory sampling
166 time
.sleep(self
.delay
)
168 mem_ret_q
.put((count
, mem_stat
))
170 class TestWorker(threading
.Thread
):
171 def __init__(self
, path
, name
):
172 threading
.Thread
.__init
__(self
)
177 bin_path_name
= os
.path
.join(self
.path
, self
.name
)
180 env
['TEST_NO_SESSIOND'] = '1'
182 test
= subprocess
.Popen([bin_path_name
], env
=env
)
185 # Send ret value to main thread
186 test_ret_q
.put(test
.returncode
)
188 def get_pid(procname
):
190 Return pid of process name using 'pidof' command
192 pidof
= subprocess
.Popen(["pidof", procname
], stdout
= subprocess
.PIPE
)
193 pid
= pidof
.communicate()[0].split()
200 def spawn_session_daemon():
202 Exec the session daemon and return PID
206 pid
= get_pid(SESSIOND_BIN_NAME
)
208 os
.kill(pid
, SIGTERM
)
210 bin_path
= os
.path
.join(TESTDIR_PATH
, "..", SESSIOND_BIN_PATH
, SESSIOND_BIN_NAME
)
212 if not os
.path
.isfile(bin_path
):
213 print "Error: No session daemon binary found. Compiled?"
217 sdaemon_proc
= subprocess
.Popen([bin_path
, "-d"], shell
=False,
218 stderr
= subprocess
.PIPE
)
223 return get_pid(SESSIOND_BIN_NAME
)
225 def start_test(name
):
227 Spawn test and return exit code
229 tw
= TestWorker(".", name
)
232 return test_ret_q
.get(True)
234 def print_cpu_stats(stats
, count
):
236 Pretty print on one line the CPU stats
238 sys
.stdout
.write(PRINT_ARROW
+ " Cpu [sampled %d time(s)]:\n " % (count
))
240 sys
.stdout
.write(" %s: %.2f, " % (stat
, stats
[stat
]))
243 def get_cpu_usage(delay
=1, pid
=0):
245 Spawn a worker thread to sample cpu usage.
247 sw
= SamplingWorker("cpu", delay
= delay
, pid
= pid
)
250 return cpu_ret_q
.get(True)
252 def get_mem_usage(pid
):
254 Get memory usage for PID
256 return mem_sample_usage(pid
)
258 def print_test_success(ret
, expect
):
260 Print if test has failed or pass according to the expected value.
263 print "\n" + PRINT_RED_BRACKET
+ \
264 " Failed: ret = %d (expected %d)" % (ret
, expect
)
267 print "\n" + PRINT_BRACKET
+ \
268 " Passed: ret = %d (expected %d)" % (ret
, expect
)
273 Run test 'name' and output report of the test with stats.
277 dem_pid
= 0 # Session daemon pid
279 print PRINT_BRACKET
+ " %s" % (test
['name'])
280 print PRINT_ARROW
+ " %s" % (test
['desc'])
282 print PRINT_ARROW
+ " Statistics will NOT be collected"
284 print PRINT_ARROW
+ " Statistics of the session daemon will be collected"
286 if test
['kern'] and not is_root
:
287 print "Needs root for kernel tracing. Skipping"
290 if not os
.path
.isfile(test
['bin']):
291 print "Unable to find test file '%s'. Skipping" % (test
['bin'])
294 # No session daemon needed
295 if not test
['daemon']:
296 print PRINT_ARROW
+ " No session daemon needed"
297 ret
= start_test(test
['bin'])
298 print_test_success(ret
, test
['success'])
301 print PRINT_ARROW
+ " Session daemon needed"
303 dem_pid
= spawn_session_daemon()
305 print "Unable to start %s. Stopping" % (SESSIOND_BIN_NAME
)
306 print sdaemon_proc
.communicate()[1]
309 print PRINT_BRACKET
+ " Session daemon spawned (pid: %d)\n" % (dem_pid
)
312 mem_before
= get_mem_usage(dem_pid
)
313 print PRINT_BRACKET
+ " Stats *before* test:"
314 print PRINT_ARROW
+ " Mem (kB): %d" % (mem_before
)
315 cpu_count
, cpu_stats
= get_cpu_usage(pid
= dem_pid
)
316 print_cpu_stats(cpu_stats
, cpu_count
)
318 tw
= TestWorker(".", test
['bin'])
322 # Start CPU sampling for test
323 sw_cpu
= SamplingWorker("cpu", worker
= tw
, pid
= dem_pid
)
325 sw_mem
= SamplingWorker("mem", worker
= tw
, pid
= dem_pid
)
328 ret
= test_ret_q
.get(True)
332 # Compute memory average
333 mem_count
, mem_during
= mem_ret_q
.get(True)
334 mem_during
= float(mem_during
) / float(mem_count
)
335 cpu_count
, cpu_stats
= cpu_ret_q
.get(True)
337 print "\n" + PRINT_BRACKET
+ " Stats *during* test:"
338 print PRINT_ARROW
+ " Mem (kB): %.0f [sampled %d time(s)]" % (mem_during
, mem_count
)
339 print_cpu_stats(cpu_stats
, cpu_count
)
341 mem_after
= get_mem_usage(dem_pid
)
342 print "\n" + PRINT_BRACKET
+ " Stats *after* test:"
343 print PRINT_ARROW
+ " Mem (kB): %d" % (mem_after
)
344 cpu_count
, cpu_stats
= get_cpu_usage(pid
= dem_pid
)
345 print_cpu_stats(cpu_stats
, cpu_count
)
347 print "\n" + PRINT_BRACKET
+ " Memory usage differences:"
348 print PRINT_ARROW
+ " Diff during and before (kB): %d" % (mem_during
- mem_before
)
349 print PRINT_ARROW
+ " Diff during and after (kB): %d" % (mem_during
- mem_after
)
350 print PRINT_ARROW
+ " Diff before and after (kB): %d" % (mem_after
- mem_before
)
352 # Return value of 0 means that is passed else it failed
353 ret
= print_test_success(ret
, test
['success'])
355 # Stop session daemon
357 print PRINT_BRACKET
+ " Stopping session daemon (pid: %d)..." % (dem_pid
)
359 os
.kill(dem_pid
, SIGTERM
)
360 # This call simply does not work... It seems python does not relay the signal
361 # to the child processes of sdaemon_proc.
362 # sdaemon_proc.terminate()
364 print sdaemon_proc
.communicate()[1]
365 elif sdaemon_proc
.returncode
== None:
366 sdaemon_proc
.communicate()
370 # Make sure all thread are released
380 if not test
['enabled']:
385 # Stop all tests, the last one failed
389 def cleanup(signo
, stack
):
390 """ Cleanup function """
393 if __name__
== "__main__":
394 if not os
.getuid() == 0:
396 print "NOTICE: Not root. No kernel tracing will be tested\n"
398 if os
.path
.isfile("test_list.py"):
399 from test_list
import Tests
401 print "No test_list.py found. Stopping"
404 TESTDIR_PATH
= os
.getcwd()
406 if len(sys
.argv
) > 1:
407 if sys
.argv
[1] == "--no-stats":
411 signal(SIGTERM
, cleanup
)
412 signal(SIGINT
, cleanup
)
415 except KeyboardInterrupt:
This page took 0.037279 seconds and 4 git commands to generate.