Dan Price
2007-Dec-04 23:46 UTC
[dtrace-discuss] printa, IP addresses, and columnar output?
I have been using Eric Kustarz''s "nfstop" dtrace script to
keep an eye on
a server; the output looks like this:
host: 129.146.226.97 num nfs calls: 6
host: 129.145.154.106 num nfs calls: 7
host: 129.146.11.146 num nfs calls: 8
host: 129.146.108.85 num nfs calls: 8
host: 10.4.180.27 num nfs calls: 11
host: 129.146.228.172 num nfs calls: 16
host: 129.146.11.145 num nfs calls: 17
host: 129.146.228.151 num nfs calls: 19
host: 129.146.228.144 num nfs calls: 22
...
While this is helpful, I''d much rather format the output as follows:
HOST OPS
129.146.226.97 6
129.145.154.106 7
129.146.11.146 8
129.146.108.85 8
10.4.180.27 11
129.146.228.172 16
129.146.11.145 17
129.146.228.151 19
129.146.228.144 22
Which to my eyes is a lot easier to process rapidly.
The problem here is that the IP address is stored byte by byte in the
aggregation, as follows:
@hosts[self->sin_addr[0], self->sin_addr[1], self->sin_addr[2],
self->sin_addr[3]] = count();
(There is a similar clause for ipv6 addresses which I have omitted here).
And so the printa() looks like this:
printa("\nhost: %d.%d.%d.%d num nfs calls: %@d", @hosts)
This would seem to make it fairly difficult to align the columns of output,
unless I zero-fill each IP address (ugly). My initial thought was to trying
something like this:
s = sprintf("%d.%d.%d.%d", self->sin_addr[0],
self->sin_addr[1],
self->sin_addr[2], self->sin_addr[3]])
@hosts[s] = count();
...
printa("%20s\t\t%d")
Unfortunately, there is no sprintf, I presume because printf processing happens
up in userland. So I was wondering if there''s a best practice here, or
some
other obvious way to cope with this problem?
-dp
--
Daniel Price - Solaris Kernel Engineering - dp at eng.sun.com - blogs.sun.com/dp
Dan McDonald
2007-Dec-05 00:10 UTC
[dtrace-discuss] printa, IP addresses, and columnar output?
On Tue, Dec 04, 2007 at 03:46:50PM -0800, Dan Price wrote: <SNIP!>> Unfortunately, there is no sprintf, I presume because printf processing happens > up in userland. So I was wondering if there''s a best practice here, or some > other obvious way to cope with this problem?Pity most of the format characters are taken. A format character for %A4 for IPv4 or %A6 for IPv6 would work very well here. (''A'' would obviously need to be replaced.) Dan
Brendan Gregg - Sun Microsystems
2007-Dec-05 00:12 UTC
[dtrace-discuss] printa, IP addresses, and columnar output?
G''Day Dan, On Tue, Dec 04, 2007 at 03:46:50PM -0800, Dan Price wrote:> > I have been using Eric Kustarz''s "nfstop" dtrace script to keep an eye on > a server; the output looks like this:Eric''s script is going to become much easier with the stable NFS providers. :)> host: 129.146.226.97 num nfs calls: 6 > host: 129.145.154.106 num nfs calls: 7 > host: 129.146.11.146 num nfs calls: 8 > host: 129.146.108.85 num nfs calls: 8 > host: 10.4.180.27 num nfs calls: 11 > host: 129.146.228.172 num nfs calls: 16 > host: 129.146.11.145 num nfs calls: 17 > host: 129.146.228.151 num nfs calls: 19 > host: 129.146.228.144 num nfs calls: 22 > ... > > > While this is helpful, I''d much rather format the output as follows: > > HOST OPS > 129.146.226.97 6 > 129.145.154.106 7 > 129.146.11.146 8 > 129.146.108.85 8 > 10.4.180.27 11 > 129.146.228.172 16 > 129.146.11.145 17 > 129.146.228.151 19 > 129.146.228.144 22 > > Which to my eyes is a lot easier to process rapidly. > > The problem here is that the IP address is stored byte by byte in the > aggregation, as follows: > > @hosts[self->sin_addr[0], self->sin_addr[1], self->sin_addr[2], > self->sin_addr[3]] = count(); > > (There is a similar clause for ipv6 addresses which I have omitted here). > > And so the printa() looks like this: > > printa("\nhost: %d.%d.%d.%d num nfs calls: %@d", @hosts) > > This would seem to make it fairly difficult to align the columns of output, > unless I zero-fill each IP address (ugly). My initial thought was to trying > something like this: > > s = sprintf("%d.%d.%d.%d", self->sin_addr[0], self->sin_addr[1], > self->sin_addr[2], self->sin_addr[3]]) > @hosts[s] = count(); > > ... > > printa("%20s\t\t%d") > > Unfortunately, there is no sprintf, I presume because printf processing happens > up in userland. So I was wondering if there''s a best practice here, or some > other obvious way to cope with this problem?I solved this once using a series of strjoin()s (see tcpsnoop.d in the DTraceToolkit); but you really want to use inet_ntoa(), inet_ntoa6() or inet_ntop(), which I added to DTrace several months ago (and to the DTrace wiki about a week ago), for usage such as this. The changes to nfstop would include something like this: this->str4 = inet_ntoa(&((struct sockaddr_in *)self->ca)->sin_addr.S_un.S_addr); [...] this->str6 = inet_ntoa6(&((struct sockaddr_in6 *)self->ca)->sin6_addr); Brendan -- Brendan [CA, USA]
Dan Price
2007-Dec-05 00:40 UTC
[dtrace-discuss] printa, IP addresses, and columnar output?
On Tue 04 Dec 2007 at 04:12PM, Brendan Gregg - Sun Microsystems wrote:> G''Day Dan, > > On Tue, Dec 04, 2007 at 03:46:50PM -0800, Dan Price wrote: > > > > I have been using Eric Kustarz''s "nfstop" dtrace script to keep an eye on > > a server; the output looks like this: > > Eric''s script is going to become much easier with the stable NFS providers. :)I''m eagerly awaiting them :)> > > > Unfortunately, there is no sprintf, I presume because printf processing happens > > up in userland. So I was wondering if there''s a best practice here, or some > > other obvious way to cope with this problem? > > I solved this once using a series of strjoin()s (see tcpsnoop.d in the > DTraceToolkit); but you really want to use inet_ntoa(), inet_ntoa6() or > inet_ntop(), which I added to DTrace several months ago (and to the DTrace > wiki about a week ago), for usage such as this. > > The changes to nfstop would include something like this: > > this->str4 = inet_ntoa(&((struct sockaddr_in *)self->ca)->sin_addr.S_un.S_addr); > [...] > this->str6 = inet_ntoa6(&((struct sockaddr_in6 *)self->ca)->sin6_addr);Absolutely perfect. Thanks. I''ve attached the updated script, in case anyone else finds it useful. -dp -- Daniel Price - Solaris Kernel Engineering - dp at eng.sun.com - blogs.sun.com/dp -------------- next part -------------- #!/usr/sbin/dtrace -FCs #define AF_INET 2 #define AF_INET6 26 fbt::common_dispatch:entry { self->ca = (struct sockaddr *)(args[0]->rq_xprt->xp_xpc.xpc_rtaddr.buf); self->in = 1; } fbt::common_dispatch:return /self->in && self->ca->sa_family == AF_INET/ { self->sin_addr = &((struct sockaddr_in *)self->ca)->sin_addr.S_un.S_addr; @hosts[inet_ntoa(self->sin_addr)] = count(); total++; self->in = 0; self->ca = 0; } fbt::common_dispatch:return /self->in && self->ca->sa_family == AF_INET6/ { self->sin6 = &((struct sockaddr_in6 *)self->ca)->sin6_addr; total++; @hosts6[inet_ntoa6(self->sin6)] = count(); self->in = 0; self->ca = 0; } END { trunc (@hosts, 20); trunc (@hosts6, 20); printf("Interrupt.\n\n"); printf("HOST%56sOPS", ""); printa("\n%-40s %@d", @hosts); printa("\n%-40s %@d", @hosts6); printf("\nTOTAL%55s%d", "", total); } tick-3s { trunc (@hosts, 20); trunc (@hosts6, 20); printf("\033[H\033[2J"); printf("HOST%56sOPS", ""); printa("\n%-40s %@d", @hosts); printa("\n%-40s %@d", @hosts6); printf("\nTOTAL%55s%d", "", total); total = 0; trunc (@hosts); trunc (@hosts6); }
Johan Hartzenberg
2007-Dec-05 06:39 UTC
[dtrace-discuss] printa, IP addresses, and columnar output?
Dan Price wrote:> I have been using Eric Kustarz''s "nfstop" dtrace script to keep an eye on > a server; the output looks like this: > > host: 129.146.226.97 num nfs calls: 6 > host: 129.145.154.106 num nfs calls: 7 > host: 129.146.11.146 num nfs calls: 8 > host: 129.146.108.85 num nfs calls: 8 > host: 10.4.180.27 num nfs calls: 11 > host: 129.146.228.172 num nfs calls: 16 > host: 129.146.11.145 num nfs calls: 17 > host: 129.146.228.151 num nfs calls: 19 > host: 129.146.228.144 num nfs calls: 22 > ... > > > While this is helpful, I''d much rather format the output as follows: > > HOST OPS > 129.146.226.97 6 > 129.145.154.106 7 > 129.146.11.146 8 > 129.146.108.85 8 > 10.4.180.27 11 > 129.146.228.172 16 > 129.146.11.145 17 > 129.146.228.151 19 > 129.146.228.144 22 > > Which to my eyes is a lot easier to process rapidly. > [snip] > >May I suggest simply parsing the output by a shell command, eg usin the initial output shown above, extracting fields 2 and 6 from each line: nfstop | awk ''{printf ("%-20s %3s\n", $2, $6)}'' -- <http://www.sun.com/solaris> * Johan Hartzenberg * *Sun Microsystems, Inc.* Cape Town South Africa Phone +27 219107160 Mobile +27 730612464 Fax +27 219199214 Email Johan.Hartzenberg.Bytes at Sun.COM <http://www.sun.com/solaris> -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.opensolaris.org/pipermail/dtrace-discuss/attachments/20071205/7fb96639/attachment.html>