#! /usr/bin/env stap # # Copyright (C) 2018 Red Hat, Inc. # By William cohen, Red Hat Inc. # wcohen@redhat.com # global latency = 0 // non-zero to include latency info global syscalls = 0 // non-zero to include syscalls global tally global top = 100000 // High enough limit to be "infinite" global entry_time%, acc_time function method_entry(class:string, method:string) { tally[class, method] <<< 1 if (latency) { entry_time[tid(), class, method] = gettimeofday_us() } } function method_exit(class:string, method:string) { t = entry_time[tid(), class, method] = gettimeofday_us() if (t) acc_time[class, method] <<< gettimeofday_us() - t } # probes for java probe hotspot.method_entry? { if (pid() == target()) method_entry(class, name) } probe hotspot.method_return? { if (latency && pid() == target()) method_exit(class, name) } # probes for perl probe perl.sub.call? { if (pid() == target()) method_entry(filename, sub) } probe perl.sub.return? { if (latency && pid() == target()) method_exit(filename, sub) } # probes for php probe process("php").mark("function__entry")? { if (pid() == target()) { class = user_string($arg4) method = user_string($arg1) method_entry(class, method) } } probe process("php").mark("function__return")? { if (latency && pid() == target()) { class = user_string($arg4) method = user_string($arg1) method_exit(class, method) } } # probes for python probe process("/usr/lib*/libpython*.so.1.0").mark("function__entry")? { if (pid() == target()) { class = user_string($arg1) method = user_string($arg2) method_entry(class, method) } } probe process("/usr/lib*/libpython*.so.1.0").mark("function__return")? { if (latency && pid() == target()) { class = user_string($arg1) method = user_string($arg2) method_exit(class, method) } } # probes for ruby probe ruby.method.entry? { if (pid() == target()) method_entry(classname, methodname) } probe ruby.method.return? { if (latency && pid() == target()) method_exit(classname, methodname) } # probes for tcl # TODO cmd__entry ? probe process("/usr/lib*/libtcl*.so").mark("proc__entry")? { if (pid() == target()) { method = user_string($arg1) method_entry("", method) } } probe process("/usr/lib*/libtcl*.so").mark("proc__return")? { if (latency && pid() == target()) { method = user_string($arg1) method_exit("", method) } } probe syscall_any { if (syscalls && pid() == target()) method_entry("syscall", name) } probe syscall_any.return { if (syscalls && latency && pid() == target()) method_exit("syscall", name) } function print_info() { printf("%-50s %8s", "METHOD", "# CALLS") if (latency) printf(" %9s", "TIME (us)") printf("\n") foreach([class, method] in tally- limit top){ class_method = sprintf("%s.%s", class, method) printf("%-50s %8d", class_method, @sum(tally[class, method])) if (latency) printf(" %9d", @sum(acc_time[class, method])) printf("\n") } printf("\n") } probe end { print_info() delete tally delete entry_time delete acc_time } probe begin { process_cmdline() } /* Handle the "top=", "latency", and "syscall" options */ function process_cmdline () { for (i=1; i <= argc; i++) { argument = tokenize(argv[i], "=") if ( argument == "top"){ top=strtol(tokenize("", "="),10) continue; } if ( argument == "latency"){ latency = 1 continue; } if ( argument == "syscalls"){ syscalls = 1 continue; } } }