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>