Whamcloud - gitweb
LU-8551 test: Use mds1 rather than mds to operate on MDT0000
[fs/lustre-release.git] / lustre / utils / llstat
1 #!/usr/bin/perl
2 # llstat is a utility that takes stats files as input with optional 
3 # clear-flag. The clear-flag is used to clear the stats file before 
4 # printing stats information. The lustre stats files generally located
5 # inside proc/fs/lustre/. This program first reads the required statistics
6 # information from specified stat file, process the information and prints
7 # the output after every interval specified by user.
8
9 # Subroutine for printing usages information
10 sub usage()
11 {
12         print STDERR "Usage: $pname [-c] [-g] [-i <interval>] [-h <help>] <stats_file>\n";
13         print STDERR "       stats_file : lustre/.../stat\n";
14         print STDERR "       -i interval: polling period\n";
15         print STDERR "       -c         : clear stats file first\n";
16         print STDERR "       -g         : graphable output format\n";
17         print STDERR "       -h         : help, display this information\n";
18         print STDERR "example: $pname -i 1 ost (monitors lustre/ost/OSS/ost/stats)\n";
19         print STDERR "Use CTRL + C to stop statistics printing\n";
20         exit 1;
21 }
22
23 sub print_headings()
24 {       my $cc = $_[0];
25         if ($graphable) {
26                 if ( $print_once && $interval ) {
27                         printf "Timestamp [Name Count Rate Total Unit]...";
28                         printf "\n--------------------------------------------------------------------";
29                         $print_once = 0;
30                 }
31                 if ($cc && !$starttime) {
32                         $starttime = $cc
33                 }
34                 printf "\n%-5.0f", ($cc - $starttime);
35         } else {
36                 printf "$statspath @ $cc\n";
37                 printf "%-25s %-10s %-10s %-10s", "Name", "Cur.Count", "Cur.Rate", "#Events";
38                 if ( $anysum ) {
39                         printf "%-8s %10s %10s %12s %10s", "Unit", "last", "min", "avg", "max";
40                 }
41                 if ( $anysumsquare ) {
42                         printf "%10s", "stddev";
43                 }
44                 printf "\n";
45         }
46 }
47
48 # known units are: reqs, bytes, usec, bufs, regs, pages
49 # readstat subroutine reads and processes statistics from stats file.
50 # This subroutine gets called after every interval specified by user.
51 sub readstat()
52 {
53         seek STATS, 0, 0;
54         while (<STATS>) {
55         chop;
56         ($name, $cumulcount, $samples, $unit, $min, $max, $sum, $sumsquare) 
57                 = split(/\s+/, $_);
58         $prevcount = %cumulhash->{$name};
59         if (defined($prevcount)) {
60                 $diff = $cumulcount - $prevcount;
61                 if ($name eq "snapshot_time") {
62                         $tdiff = int($diff);
63                         &print_headings($cumulcount);
64                         $| = 1;
65                         if ($tdiff == 0) {
66                             $tdiff = 1; # avoid division by zero
67                         }
68                 }
69                 elsif ($cumulcount!=0) {
70                         if ($graphable) {
71                             my $myunit = $unit;
72                             my $myname = $name;
73                             if (defined($sum)) {
74                                 $myunit = "[reqs]";
75                                 $myname = $myname . "_rq";
76                             }
77                             printf "   %s %lu %lu %lu %s", 
78                             $myname, $diff, ($diff/$tdiff), $cumulcount, $myunit;
79                         } else {
80                             printf "%-25s %-10lu %-10lu %-10lu",
81                             $name, $diff, ($diff/$tdiff), $cumulcount;
82                         }
83                         if (defined($sum)) {
84                                 my $sum_orig = $sum;
85                                 my $sum_diff = $sum - %sumhash->{$name};
86                                 if ($graphable) {
87                                     printf "   %s %lu %.2f %lu %s",
88                                     $name, $sum_diff, ($sum_diff/$tdiff), $sum, $unit;
89                                 } else {
90                                     printf "%-8s %10lu %10lu %12.2f %10lu", $unit, 
91                                     $sum_diff, $min, ($sum/$cumulcount), $max;
92                                 }
93                                 if (defined($sumsquare)) {
94                                         my $s = $sumsquare - (($sum_orig*$sum_orig)/$cumulcount);
95                                         if ($s >= 0) {
96                                                 my $cnt = ($cumulcount >= 2) ? $cumulcount : 2 ;
97                                                 my $stddev = sqrt($s/($cnt - 1));
98                                                 if (!$graphable) {
99                                                         printf " %9.2f ", $stddev;
100                                                 }
101                                         }
102                                 }
103                         }
104                         if (!$graphable) {
105                                 printf "\n";
106                         }
107                         $| = 1;
108                 }
109         } else {
110                 if ($cumulcount!=0) {
111                         # print info when interval is not specified.
112                         printf "%-25s $cumulcount\n", $name
113                 }
114                 if (defined($sum)) {
115                         $anysum = 1;
116                 }
117                 if (defined($sumsquare)) {
118                         $anysumsquare = 1;
119                 }
120         }
121         %cumulhash->{$name} = $cumulcount;
122         %sumhash->{$name} = $sum;
123         } #end of while
124 }
125
126 #Globals
127 $pname = $0;
128 $obdstats = "stats";
129 $clear = 0;
130 $graphable = 0;
131 $interval = 0;
132 $statspath = "None";
133 $anysumsquare = 0;
134 $mhz = 0;
135 $print_once = 1;
136 %cumulhash;
137 %sumhash;
138 $anysum = 0;
139 $obddev = "";
140 $starttime = 0;
141 $ONE_MB = 1048576;
142
143 # Command line parameter parsing
144 use Getopt::Std;
145 getopts('hcgi:') or usage();
146 usage() if $opt_h;
147 $clear = 1 if $opt_c;
148 $graphable = 1 if $opt_g;
149 $interval = $opt_i if $opt_i;
150
151 my $i = 0;
152 foreach (@ARGV) {
153         $obddev = $_;
154         $i++;
155         if ($i > 1) {
156                 print "ERROR: extra argument $_\n";
157                 usage();
158         }
159 }
160 if ( !$obddev ) {
161         print "ERROR: Need to specify stats_file\n";
162         usage();
163 }
164 # Process arguments
165 if ( -f $obddev ) {
166         $statspath = $obddev;
167 } elsif ( -f "$obddev/$obdstats" ) {
168         $statspath = "$obddev/$obdstats";
169 } else {
170         my $st = glob("/{proc,sys}/fs/lustre/*/$obddev/$obdstats");
171         if ( -f "$st" ) {
172                 $statspath = $st;
173         } else {
174                 $st = glob("/{proc,sys}/fs/lustre/*/*/$obddev/$obdstats");
175                 if ( -f "$st" ) {
176                         $statspath = $st;
177                 }
178         }
179 }
180 if ( $statspath =~ /^None$/ ) {
181         die "Cannot locate stat file for: $obddev\n";
182 }
183 # Clears stats file before printing information in intervals
184 if ( $clear ) {
185         open ( STATS, "> $statspath") || die "Cannot clear $statspath: $!\n";
186         print STATS " ";
187         close STATS;
188         sleep($interval);           
189 }
190 use POSIX qw(strftime);
191 $time_v = time();
192 $hostname = `lctl list_nids | head -1`;
193 chop($hostname);
194 print "$pname: STATS on ", strftime("%D", localtime($time_v));
195 print " $statspath on $hostname\n";
196 open(STATS, $statspath) || die "Cannot open $statspath: $!\n";
197 do {
198         readstat();
199         if ($interval) { 
200                 sleep($interval);
201         }
202 } while ($interval);
203 close STATS;