├── README.md └── oneliners ├── freebsd.md └── README.md /README.md: -------------------------------------------------------------------------------- 1 | # DTrace Scripts 2 | 3 | DTrace includes a scripting language, D, in which more complex scripts 4 | can be written. The `scripts` repository contains scripts in native 5 | D, as well as `sh`, `ksh`, `Python`, and `Perl`. 6 | 7 | ## Organization 8 | 9 | * `oneliners` Markdown files containing well known one-liners 10 | arranged by operating system. 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /oneliners/freebsd.md: -------------------------------------------------------------------------------- 1 | # DTrace One Liners for FreeBSD 2 | 3 | [FreeBSD](http://www.freebsd.org) has supported DTrace since FreeBSD 8 4 | and support was turned on by default for FreeBSD 10. The following 5 | library of DTrace one-liners were last tested on FreeBSD 10.0 and were 6 | originally imported from the [FreeBSD Wiki](http://wiki.freebsd.org). 7 | 8 | ## Kernel Locks ## 9 | 10 | ### Sum kernel adaptive lock block time by process name (ns): 11 | ``` 12 | dtrace -n 'lockstat:::adaptive-block { @[execname] = sum(arg1); }' 13 | ``` 14 | 15 | ### Summarize adaptive lock block time distribution by process name (ns): 16 | ``` 17 | dtrace -n 'lockstat:::adaptive-block { @[execname] = quantize(arg1); }' 18 | ``` 19 | 20 | ### Sum kernel adaptive lock block time by kernel stack trace (ns): 21 | ``` 22 | dtrace -n 'lockstat:::adaptive-block { @[stack()] = sum(arg1); }' 23 | ``` 24 | 25 | ### Sum kernel adaptive lock block time by lock name (ns): 26 | ``` 27 | dtrace -n 'lockstat:::adaptive-block { @[arg0] = sum(arg1); } END { printa("%40a %@16d ns\n", @); }' 28 | ``` 29 | 30 | ### Sum kernel adaptive lock block time by calling function (ns): 31 | ``` 32 | dtrace -n 'lockstat:::adaptive-block { @[caller] = sum(arg1); } END { printa("%40a %@16d ns\n", @); }' 33 | ``` 34 | 35 | ## Namecache ## 36 | 37 | ### Count namecache lookups by program 38 | ``` 39 | dtrace -n 'vfs:namecache:lookup: { @missing[execname] = count(); }' 40 | ``` 41 | 42 | ### Count namecache misses by program 43 | ``` 44 | dtrace -n 'vfs:namecache:lookup:miss { @missing[execname] = count(); }' 45 | ``` 46 | 47 | ## Raw Kernel Tracing ## 48 | 49 | ## Count kernel slab memory allocation by function: 50 | ``` 51 | dtrace -n 'fbt::kmem*:entry { @[probefunc] = count(); }' 52 | ``` 53 | 54 | ### Count kernel slab memory allocation by calling function: 55 | ``` 56 | dtrace -n 'fbt::kmem*:entry { @[caller] = count(); } END { printa("%40a %@16d\n", @); }' 57 | ``` 58 | 59 | ### Count kernel malloc() by calling function: 60 | ``` 61 | dtrace -n 'fbt::malloc:entry { @[caller] = count(); } END { printa("%40a %@16d\n", @); }' 62 | ``` 63 | 64 | ### Count kernel malloc() by kernel stack trace: 65 | ``` 66 | dtrace -n 'fbt::malloc:entry { @[stack()] = count(); }' 67 | ``` 68 | 69 | ### Summarize vmem_alloc()s by arena name and size distribution: 70 | ``` 71 | dtrace -n 'fbt::vmem_alloc:entry { @[args[0]->vm_name] = quantize(arg1); }' 72 | ``` 73 | 74 | ### Summarize TCP life span in seconds: 75 | ``` 76 | dtrace -n 'fbt::tcp_close:entry { @["TCP life span (seconds):"] = 77 | quantize((uint32_t)(`ticks - args[0]->t_starttime) / `hz); }' 78 | ``` 79 | -------------------------------------------------------------------------------- /oneliners/README.md: -------------------------------------------------------------------------------- 1 | # DTrace One Liners 2 | 3 | A `DTrace` one liner is a simple invocation of the `dtrace(1)` command 4 | that can be used to find out something about the system being traced. 5 | One liners can be general or specific to the underlying operating 6 | system, depending on the provider being used or the data to be 7 | extracted. One liners that are expected to work across all operating 8 | systems are included in this `README` file while those specific to 9 | various operating systems and software are kept in their own files. 10 | 11 | ## Finding Probes 12 | 13 | ### List probes and search for string "foo": 14 | ``` 15 | dtrace -l | grep foo 16 | ``` 17 | 18 | ### Summarize probes by providers: 19 | ``` 20 | dtrace -l | awk '{ print $2 }' | sort | uniq -c | sort -n 21 | ``` 22 | 23 | ### List probes for a particular provider 24 | ``` 25 | dtrace -l -P syscall 26 | ``` 27 | 28 | ### List the arguments for a probe 29 | ``` 30 | dtrace -lv syscall::write:entry 31 | ``` 32 | 33 | ## Syscalls ## 34 | 35 | ### Trace file opens with process and filename: 36 | ``` 37 | dtrace -n 'syscall::open*:entry { printf("%s %s", execname, copyinstr(arg0)); }' 38 | ``` 39 | 40 | ### Count system calls by program name: 41 | ``` 42 | dtrace -n 'syscall:::entry { @[execname] = count(); }' 43 | ``` 44 | 45 | ### Count system calls by syscall: 46 | ``` 47 | dtrace -n 'syscall:::entry { @[probefunc] = count(); }' 48 | ``` 49 | 50 | ### Count system calls by syscall, for PID 123 only: 51 | ``` 52 | dtrace -n 'syscall:::entry /pid ## 123/ { @[probefunc] = count(); }' 53 | ``` 54 | 55 | ### Count system calls by syscall, for all processes with a specific program name ("nginx"): 56 | ``` 57 | dtrace -n 'syscall:::entry /execname ## "nginx"/ { @[probefunc] = count(); }' 58 | ``` 59 | 60 | ### Count system calls by PID and program name: 61 | ``` 62 | dtrace -n 'syscall:::entry { @[pid, execname] = count(); }' 63 | ``` 64 | 65 | ### Summarize requested read() sizes by program name, as power-of-2 distributions (bytes): 66 | ``` 67 | dtrace -n 'syscall::read:entry { @[execname] = quantize(arg2); }' 68 | ``` 69 | 70 | ### Summarize returned read() sizes by program name, as power-of-2 distributions (bytes or error): 71 | ``` 72 | dtrace -n 'syscall::read:return { @[execname] = quantize(arg1); }' 73 | ``` 74 | 75 | ### Summarize read() latency as a power-of-2 distribution by program name (ns): 76 | ``` 77 | dtrace -n 'syscall::read:entry { self->ts = timestamp; } syscall::read:return /self->ts/ { 78 | @[execname, "ns"] = quantize(timestamp - self->ts); self->ts = 0; }' 79 | ``` 80 | 81 | ### Summarize read() latency as a linear distribution (0 to 1000, step 5) by program name (ms): 82 | ``` 83 | dtrace -n 'syscall::read:entry { self->ts = timestamp; } syscall::read:return /self->ts/ { 84 | @[execname, "ms"] = lquantize((timestamp - self->ts) / 1000000, 0, 1000, 5); self->ts = 0; }' 85 | ``` 86 | 87 | ### Summarize read() on-CPU duration as a power-of-2 distribution by program name (ns): 88 | ``` 89 | dtrace -n 'syscall::read:entry { self->ts = vtimestamp; } syscall::read:return /self->ts/ { 90 | @[execname, "ns"] = quantize(vtimestamp - self->ts); self->ts = 0; }' 91 | ``` 92 | 93 | ### Count read() variants that "nginx" is using (if previous one-liners didn't work): 94 | ``` 95 | dtrace -n 'syscall::*read*:entry /execname ## "nginx"/ { @[probefunc] = count(); }' 96 | ``` 97 | 98 | ### Summarize returned pread() sizes for "nginx" as distributions (bytes or error): 99 | ``` 100 | dtrace -n 'syscall::pread:return /execname ## "nginx"/ { @ = quantize(arg1); }' 101 | ``` 102 | 103 | ### Count socket accept() variants by process name: 104 | ``` 105 | dtrace -n 'syscall::*accept*:return { @[execname] = count(); }' 106 | ``` 107 | 108 | ### Count socket connect() variants by process name: 109 | ``` 110 | dtrace -n 'syscall::*connect*:return { @[execname] = count(); }' 111 | ``` 112 | 113 | ### Summarize returned pread() sizes for "nginx"... and label the output: 114 | ``` 115 | dtrace -n 'syscall::pread:return /execname ## "nginx"/ { @["rval (bytes)"] = quantize(arg1); }' 116 | ``` 117 | 118 | ## Process Tracing ## 119 | 120 | ### Trace new processes showing program name (and args if available): 121 | ``` 122 | dtrace -n 'proc:::exec-success { trace(curpsinfo->pr_psargs); }' 123 | ``` 124 | 125 | ### Count process-level events: 126 | ``` 127 | dtrace -n 'proc::: { @[probename] = count(); }' 128 | ``` 129 | 130 | 131 | ## Profiling ## 132 | 133 | ### Count sampled thread names on-CPU at 997 Hertz: 134 | ``` 135 | dtrace -n 'profile-997 { @[stringof(curthread->td_name)] = count(); }' 136 | ``` 137 | 138 | ### Count sampled non-idle thread names on-CPU at 997 Hertz: 139 | ``` 140 | dtrace -n 'profile-997 /!(curthread->td_flags & 0x20)/ { @[stringof(curthread->td_name)] = count(); }' 141 | ``` 142 | 143 | ### Count sampled on-CPU kernel stacks at 99 Hertz: 144 | ``` 145 | dtrace -n 'profile-99 /arg0/ { @[stack()] = count(); }' 146 | ``` 147 | 148 | ### Count sampled process names and on-CP user stacks at 99 Hertz: 149 | ``` 150 | dtrace -n 'profile-99 /arg1/ { @[execname, ustack()] = count(); }' 151 | ``` 152 | 153 | ## IP ## 154 | 155 | ### Count IP-level events: 156 | ``` 157 | dtrace -n 'ip::: { @[probename] = count(); }' 158 | ``` 159 | 160 | ## UDP ## 161 | 162 | ### Count UDP-level events: 163 | ``` 164 | dtrace -n 'udp::: { @[probename] = count(); }' 165 | ``` 166 | 167 | ## TCP ## 168 | 169 | ### Count TCP-level events: 170 | ``` 171 | dtrace -n 'tcp::: { @[probename] = count(); }' 172 | ``` 173 | 174 | ### Trace TCP accepted connections by remote IP address: 175 | ``` 176 | dtrace -n 'tcp:::accept-established { trace(args[3]->tcps_raddr); }' 177 | ``` 178 | 179 | ### Count TCP passive opens by remote IP address: 180 | ``` 181 | dtrace -n 'tcp:::accept-established { @[args[3]->tcps_raddr] = count(); }' 182 | ``` 183 | 184 | ### Count TCP active opens by remote IP address: 185 | ``` 186 | dtrace -n 'tcp:::connect-established { @[args[3]->tcps_raddr] = count(); }' 187 | ``` 188 | 189 | ### Count TCP sent messages by remote IP address: 190 | ``` 191 | dtrace -n 'tcp:::send { @[args[2]->ip_daddr] = count(); }' 192 | ``` 193 | 194 | ### Count TCP received messages by remote IP address: 195 | ``` 196 | dtrace -n 'tcp:::receive { @[args[2]->ip_saddr] = count(); }' 197 | ``` 198 | 199 | ### Summarize TCP sent messages by IP payload size, as a power-of-2 distribution: 200 | ``` 201 | dtrace -n 'tcp:::send { @[args[2]->ip_daddr] = quantize(args[2]->ip_plength); }' 202 | ``` 203 | 204 | 205 | 206 | --------------------------------------------------------------------------------