diff --git a/man/man8/argdist.8 b/man/man8/argdist.8 index b0a539f03032..4116cd4d2e5f 100644 --- a/man/man8/argdist.8 +++ b/man/man8/argdist.8 @@ -2,7 +2,7 @@ .SH NAME argdist \- Trace a function and display a histogram or frequency count of its parameter values. Uses Linux eBPF/bcc. .SH SYNOPSIS -.B argdist [-h] [-p PID] [-z STRING_SIZE] [-i INTERVAL] [-n COUNT] [-v] [-T TOP] [-H specifier] [-C specifier] [-I header] +.B argdist [-h] [-p PID] [-z STRING_SIZE] [-i INTERVAL] [-d DURATION] [-n COUNT] [-v] [-T TOP] [-H specifier] [-C specifier] [-I header] .SH DESCRIPTION argdist attaches to function entry and exit points, collects specified parameter values, and stores them in a histogram or a frequency collection that counts @@ -27,6 +27,9 @@ characters. Longer strings will be truncated. \-i INTERVAL Print the collected data every INTERVAL seconds. The default is 1 second. .TP +\-d DURATION +Total duration of trace in seconds. +.TP \-n NUMBER Print the collected data COUNT times and then exit. .TP diff --git a/man/man8/funclatency.8 b/man/man8/funclatency.8 index 7b7771b873a9..b82626cf8d8d 100644 --- a/man/man8/funclatency.8 +++ b/man/man8/funclatency.8 @@ -2,7 +2,7 @@ .SH NAME funclatency \- Time functions and print latency as a histogram. .SH SYNOPSIS -.B funclatency [\-h] [\-p PID] [\-i INTERVAL] [\-T] [\-u] [\-m] [\-F] [\-r] [\-v] pattern +.B funclatency [\-h] [\-p PID] [\-i INTERVAL] [\-d DURATION] [\-T] [\-u] [\-m] [\-F] [\-r] [\-v] pattern .SH DESCRIPTION This tool traces function calls and times their duration (latency), and shows the latency distribution as a histogram. The time is measured from when @@ -37,6 +37,9 @@ Trace this process ID only. \-i INTERVAL Print output every interval seconds. .TP +\-d DURATION +Total duration of trace, in seconds. +.TP \-T Include timestamps on output. .TP @@ -72,6 +75,10 @@ Time do_nanosleep(), and print the histogram in units of milliseconds: # .B funclatency \-m do_nanosleep .TP +Time libc open(), and print output every 2 seconds, for duration 10 seconds: +# +.B funclatency \-i 2 -d 10 c:read +.TP Time vfs_read(), and print output every 5 seconds, with timestamps: # .B funclatency \-mTi 5 vfs_read diff --git a/man/man8/syscount.8 b/man/man8/syscount.8 index 2a472404e910..d13793be56a3 100644 --- a/man/man8/syscount.8 +++ b/man/man8/syscount.8 @@ -2,7 +2,7 @@ .SH NAME syscount \- Summarize syscall counts and latencies. .SH SYNOPSIS -.B syscount [-h] [-p PID] [-i INTERVAL] [-T TOP] [-x] [-e ERRNO] [-L] [-m] [-P] [-l] +.B syscount [-h] [-p PID] [-i INTERVAL] [-d DURATION] [-T TOP] [-x] [-e ERRNO] [-L] [-m] [-P] [-l] .SH DESCRIPTION This tool traces syscall entry and exit tracepoints and summarizes either the number of syscalls of each type, or the number of syscalls per process. It can @@ -23,6 +23,9 @@ Trace only this process. \-i INTERVAL Print the summary at the specified interval (in seconds). .TP +\-d DURATION +Total duration of trace (in seconds). +.TP \-T TOP Print only this many entries. Default: 10. .TP diff --git a/tools/argdist.py b/tools/argdist.py index 9724073b0bc7..dfb06b46c046 100755 --- a/tools/argdist.py +++ b/tools/argdist.py @@ -610,7 +610,9 @@ def __init__(self): type=int, help="maximum string size to read from char* arguments") parser.add_argument("-i", "--interval", default=1, type=int, - help="output interval, in seconds") + help="output interval, in seconds (default 1 second)") + parser.add_argument("-d", "--duration", type=int, + help="total duration of trace, in seconds") parser.add_argument("-n", "--number", type=int, dest="count", help="number of outputs") parser.add_argument("-v", "--verbose", action="store_true", @@ -684,9 +686,11 @@ def _attach(self): def _main_loop(self): count_so_far = 0 + seconds = 0 while True: try: sleep(self.args.interval) + seconds += self.args.interval except KeyboardInterrupt: exit() print("[%s]" % strftime("%H:%M:%S")) @@ -696,6 +700,9 @@ def _main_loop(self): if self.args.count is not None and \ count_so_far >= self.args.count: exit() + if self.args.duration and \ + seconds >= self.args.duration: + exit() def run(self): try: diff --git a/tools/argdist_example.txt b/tools/argdist_example.txt index dec9e6fafc98..7098e56c57ea 100644 --- a/tools/argdist_example.txt +++ b/tools/argdist_example.txt @@ -348,7 +348,9 @@ optional arguments: -z STRING_SIZE, --string-size STRING_SIZE maximum string size to read from char* arguments -i INTERVAL, --interval INTERVAL - output interval, in seconds + output interval, in seconds (default 1 second) + -d DURATION, --duration DURATION + total duration of trace, in seconds -n COUNT, --number COUNT number of outputs -v, --verbose print resulting BPF program code before executing diff --git a/tools/funclatency.py b/tools/funclatency.py index fe06d1b08f94..3f08a7e0d74f 100755 --- a/tools/funclatency.py +++ b/tools/funclatency.py @@ -35,6 +35,7 @@ ./funclatency c:read # time the read() C library function ./funclatency -u vfs_read # time vfs_read(), in microseconds ./funclatency -m do_nanosleep # time do_nanosleep(), in milliseconds + ./funclatency -i 2 -d 10 c:open # output every 2 seconds, for duration 10s ./funclatency -mTi 5 vfs_read # output every 5 seconds, with timestamps ./funclatency -p 181 vfs_read # time process 181 only ./funclatency 'vfs_fstat*' # time both vfs_fstat() and vfs_fstatat() @@ -47,8 +48,10 @@ epilog=examples) parser.add_argument("-p", "--pid", type=int, help="trace this PID only") -parser.add_argument("-i", "--interval", default=99999999, - help="summary interval, seconds") +parser.add_argument("-i", "--interval", type=int, + help="summary interval, in seconds") +parser.add_argument("-d", "--duration", type=int, + help="total duration of trace, in seconds") parser.add_argument("-T", "--timestamp", action="store_true", help="include timestamp on output") parser.add_argument("-u", "--microseconds", action="store_true", @@ -66,6 +69,10 @@ parser.add_argument("--ebpf", action="store_true", help=argparse.SUPPRESS) args = parser.parse_args() +if args.duration and not args.interval: + args.interval = args.duration +if not args.interval: + args.interval = 99999999 def bail(error): print("Error: " + error) @@ -226,14 +233,18 @@ def print_section(key): return "%s [%d]" % (BPF.sym(key[0], key[1]), key[1]) exiting = 0 if args.interval else 1 +seconds = 0 dist = b.get_table("dist") while (1): try: - sleep(int(args.interval)) + sleep(args.interval) + seconds += args.interval except KeyboardInterrupt: exiting = 1 # as cleanup can take many seconds, trap Ctrl-C: signal.signal(signal.SIGINT, signal_ignore) + if args.duration and seconds >= args.duration: + exiting = 1 print() if args.timestamp: diff --git a/tools/funclatency_example.txt b/tools/funclatency_example.txt index ee63a5bbb41c..d8217a236ce8 100644 --- a/tools/funclatency_example.txt +++ b/tools/funclatency_example.txt @@ -343,7 +343,9 @@ optional arguments: -h, --help show this help message and exit -p PID, --pid PID trace this PID only -i INTERVAL, --interval INTERVAL - summary interval, seconds + summary interval, in seconds + -d DURATION, --duration DURATION + total duration of trace, in seconds -T, --timestamp include timestamp on output -u, --microseconds microsecond histogram -m, --milliseconds millisecond histogram @@ -357,6 +359,7 @@ examples: ./funclatency c:read # time the read() C library function ./funclatency -u vfs_read # time vfs_read(), in microseconds ./funclatency -m do_nanosleep # time do_nanosleep(), in milliseconds + ./funclatency -i 2 -d 10 c:open # output every 2 seconds, for duration 10s ./funclatency -mTi 5 vfs_read # output every 5 seconds, with timestamps ./funclatency -p 181 vfs_read # time process 181 only ./funclatency 'vfs_fstat*' # time both vfs_fstat() and vfs_fstatat() diff --git a/tools/syscount.py b/tools/syscount.py index e219e91d6ad7..a23abde5a310 100755 --- a/tools/syscount.py +++ b/tools/syscount.py @@ -17,6 +17,7 @@ import itertools import subprocess import sys +import signal import platform if sys.version_info.major < 3: @@ -370,6 +371,9 @@ def parse_syscall(line): else: raise Exception("ausyscall: command not found") +# signal handler +def signal_ignore(signal, frame): + print() def handle_errno(errstr): try: @@ -388,6 +392,8 @@ def handle_errno(errstr): parser.add_argument("-p", "--pid", type=int, help="trace only this pid") parser.add_argument("-i", "--interval", type=int, help="print summary at this interval (seconds)") +parser.add_argument("-d", "--duration", type=int, + help="total duration of trace, in seconds") parser.add_argument("-T", "--top", type=int, default=10, help="print only the top syscalls by count or latency") parser.add_argument("-x", "--failures", action="store_true", @@ -405,6 +411,10 @@ def handle_errno(errstr): parser.add_argument("--ebpf", action="store_true", help=argparse.SUPPRESS) args = parser.parse_args() +if args.duration and not args.interval: + args.interval = args.duration +if not args.interval: + args.interval = 99999999 if args.list: for grp in izip_longest(*(iter(sorted(syscalls.values())),) * 4): @@ -545,11 +555,20 @@ def print_latency_stats(): print("Tracing %ssyscalls, printing top %d... Ctrl+C to quit." % ("failed " if args.failures else "", args.top)) +exiting = 0 if args.interval else 1 +seconds = 0 while True: try: - sleep(args.interval or 999999999) - print_stats() + sleep(args.interval) + seconds += args.interval except KeyboardInterrupt: - if not args.interval: - print_stats() - break + exiting = 1 + signal.signal(signal.SIGINT, signal_ignore) + if args.duration and seconds >= args.duration: + exiting = 1 + + print_stats() + + if exiting: + print("Detaching...") + exit() diff --git a/tools/syscount_example.txt b/tools/syscount_example.txt index be6d3e616e8b..aad51c409f16 100644 --- a/tools/syscount_example.txt +++ b/tools/syscount_example.txt @@ -151,6 +151,8 @@ optional arguments: -p PID, --pid PID trace only this pid -i INTERVAL, --interval INTERVAL print summary at this interval (seconds) + -d DURATION, --duration DURATION + total duration of trace, in seconds -T TOP, --top TOP print only the top syscalls by count or latency -x, --failures trace only failed syscalls (return < 0) -e ERRNO, --errno ERRNO