| 204 | usdt_contexts=[self.usdt] if self.usdt else []) |
| 205 | |
| 206 | class Tool(object): |
| 207 | def __init__(self): |
| 208 | examples = """examples: |
| 209 | ./stackcount submit_bio # count kernel stack traces for submit_bio |
| 210 | ./stackcount -d ip_output # include a user/kernel stack delimiter |
| 211 | ./stackcount -s ip_output # show symbol offsets |
| 212 | ./stackcount -sv ip_output # show offsets and raw addresses (verbose) |
| 213 | ./stackcount 'tcp_send*' # count stacks for funcs matching tcp_send* |
| 214 | ./stackcount -r '^tcp_send.*' # same as above, using regular expressions |
| 215 | ./stackcount -Ti 5 ip_output # output every 5 seconds, with timestamps |
| 216 | ./stackcount -p 185 ip_output # count ip_output stacks for PID 185 only |
| 217 | ./stackcount -c 1 put_prev_entity # count put_prev_entity stacks for CPU 1 only |
| 218 | ./stackcount -p 185 c:malloc # count stacks for malloc in PID 185 |
| 219 | ./stackcount t:sched:sched_fork # count stacks for sched_fork tracepoint |
| 220 | ./stackcount -p 185 u:node:* # count stacks for all USDT probes in node |
| 221 | ./stackcount -K t:sched:sched_switch # kernel stacks only |
| 222 | ./stackcount -U t:sched:sched_switch # user stacks only |
| 223 | """ |
| 224 | parser = argparse.ArgumentParser( |
| 225 | description="Count events and their stack traces", |
| 226 | formatter_class=argparse.RawDescriptionHelpFormatter, |
| 227 | epilog=examples) |
| 228 | parser.add_argument("-p", "--pid", type=int, |
| 229 | help="trace this PID only") |
| 230 | parser.add_argument("-c", "--cpu", type=int, |
| 231 | help="trace this CPU only") |
| 232 | parser.add_argument("-i", "--interval", |
| 233 | help="summary interval, seconds") |
| 234 | parser.add_argument("-D", "--duration", |
| 235 | help="total duration of trace, seconds") |
| 236 | parser.add_argument("-T", "--timestamp", action="store_true", |
| 237 | help="include timestamp on output") |
| 238 | parser.add_argument("-r", "--regexp", action="store_true", |
| 239 | help="use regular expressions. Default is \"*\" wildcards only.") |
| 240 | parser.add_argument("-s", "--offset", action="store_true", |
| 241 | help="show address offsets") |
| 242 | parser.add_argument("-P", "--perpid", action="store_true", |
| 243 | help="display stacks separately for each process") |
| 244 | parser.add_argument("-K", "--kernel-stacks-only", |
| 245 | action="store_true", help="kernel stack only", default=False) |
| 246 | parser.add_argument("-U", "--user-stacks-only", |
| 247 | action="store_true", help="user stack only", default=False) |
| 248 | parser.add_argument("-v", "--verbose", action="store_true", |
| 249 | help="show raw addresses") |
| 250 | parser.add_argument("-d", "--delimited", action="store_true", |
| 251 | help="insert delimiter between kernel/user stacks") |
| 252 | parser.add_argument("-f", "--folded", action="store_true", |
| 253 | help="output folded format") |
| 254 | parser.add_argument("--debug", action="store_true", |
| 255 | help="print BPF program before starting (for debugging purposes)") |
| 256 | parser.add_argument("pattern", |
| 257 | help="search expression for events") |
| 258 | self.args = parser.parse_args() |
| 259 | global debug |
| 260 | debug = self.args.debug |
| 261 | |
| 262 | if self.args.duration and not self.args.interval: |
| 263 | self.args.interval = self.args.duration |