908e3d94059f56aa18228fa9dd14e2152b21996f
[rsync/rsync.git] / support / rsyncstats
1 #!/usr/bin/perl
2 #
3 # This script parses the default logfile format produced by rsync when running
4 # as a daemon with transfer logging enabled.  It also parses a slightly tweaked
5 # version of the default format where %o has been replaced with %i.
6 #
7 # This script is derived from the xferstats script that comes with wuftpd.  See
8 # the usage message at the bottom for the options it takes.
9 #
10 # Andrew Tridgell, October 1998
11
12 use Getopt::Long;
13
14 # You may wish to edit the next line to customize for your default log file.
15 $usage_file = "/var/log/rsyncd.log";
16
17 # Edit the following lines for default report settings.
18 # Entries defined here will be over-ridden by the command line.
19
20 $hourly_report = 0; 
21 $domain_report = 0;
22 $total_report = 0;
23 $depth_limit = 9999;
24 $only_section = '';
25
26 &Getopt::Long::Configure('bundling');
27 &usage if !&GetOptions(
28     'hourly-report|h' => \$hourly_report,
29     'domain-report|d' => \$domain_report,
30     'domain|D:s' => \$only_domain,
31     'total-report|t' => \$total_report,
32     'depth-limit|l:i' => \$depth_limit,
33     'real|r' => \$real,
34     'anon|a' => \$anon,
35     'section|s:s' => \$only_section,
36     'file|f:s' => \$usage_file,
37 );
38
39 $anon = 1 if !$real && !$anon;
40
41 open(LOG, $usage_file) || die "Error opening usage log file: $usage_file\n";
42
43 if ($only_domain) {
44     print "Transfer Totals include the '$only_domain' domain only.\n";
45     print "All other domains are filtered out for this report.\n\n";
46 }
47
48 if ($only_section) {
49     print "Transfer Totals include the '$only_section' section only.\n";
50     print "All other sections are filtered out for this report.\n\n";
51 }
52
53 line: while (<LOG>) {
54
55    next unless ($day,$time,$op,$host,$module,$file,$bytes)
56       = m#^ (\d+/\d\d/\d\d)\s+(\d\d:\d\d:\d\d)\s+\[\d+\]\s+(send|recv|[<>]f\S+)\s+
57           (\S+)\s+\[\d+\.\d+\.\d+\.\d+\]\s+(\S+)\s+\(\S*\)\s+(.*)\s+(\d+) $ #x;
58
59    # TODO actually divide the data by into send/recv categories
60    if ($op =~ /^>/) {
61       $op = 'send';
62    } elsif ($op =~ /^</) {
63       $op = 'recv';
64    }
65
66    $daytime = $day;
67    $hour = substr($time,0,2); 
68
69    $file = $module . "/" . $file;
70
71    $file =~ s|//|/|mg;
72
73    @path = split(/\//, $file);
74
75    $pathkey = "";
76    for ($i=0; $i <= $#path && $i <= $depth_limit; $i++) {
77         $pathkey = $pathkey . "/" . $path[$i];
78    }
79
80    if ($only_section ne '') {
81        next unless (substr($pathkey,0,length($only_section)) eq $only_section);
82    }
83
84    $host =~ tr/A-Z/a-z/;
85
86    @address = split(/\./, $host);
87
88    $domain = $address[$#address];
89    if ( int($address[0]) > 0 || $#address < 2 )
90       { $domain = "unresolved"; }
91
92    if ($only_domain ne '') {
93        next unless (substr($domain,0,length($only_domain)) eq $only_domain);
94    }
95
96
97 #   printf("c=%d day=%s bytes=%d file=%s path=%s\n", 
98 #          $#line, $daytime, $bytes, $file, $pathkey);
99
100    $xferfiles++;                                # total files sent
101    $xfertfiles++;                               # total files sent
102    $xferfiles{$daytime}++;                      # files per day
103    $groupfiles{$pathkey}++;                     # per-group accesses
104    $domainfiles{$domain}++;
105
106    $xferbytes{$daytime}   += $bytes;          # bytes per day
107    $domainbytes{$domain}  += $bytes;            # xmit bytes to domain
108    $xferbytes             += $bytes;          # total bytes sent
109    $groupbytes{$pathkey}  += $bytes;          # per-group bytes sent
110
111    $xfertfiles{$hour}++;                        # files per hour
112    $xfertbytes{$hour}     += $bytes;          # bytes per hour
113    $xfertbytes            += $bytes;          # total bytes sent
114 }
115 close LOG;
116
117 #@syslist = keys %systemfiles;
118 @dates = sort datecompare keys %xferbytes;
119
120 if ($xferfiles == 0) {die "There was no data to process.\n";}
121
122
123 print "TOTALS FOR SUMMARY PERIOD ", $dates[0], " TO ", $dates[$#dates], "\n\n";
124 printf("Files Transmitted During Summary Period  %12.0f\n", $xferfiles);
125 printf("Bytes Transmitted During Summary Period  %12.0f\n", $xferbytes); 
126 #printf("Systems Using Archives                   %12.0f\n\n", $#syslist+1);
127
128 printf("Average Files Transmitted Daily          %12.0f\n",
129    $xferfiles / ($#dates + 1));
130 printf("Average Bytes Transmitted Daily          %12.0f\n",
131    $xferbytes / ($#dates + 1));
132
133 format top1 =
134
135 Daily Transmission Statistics
136
137                  Number Of    Number of   Percent Of  Percent Of
138      Date        Files Sent   MB  Sent    Files Sent  Bytes Sent
139 ---------------  ----------  -----------  ----------  ----------
140 .
141
142 format line1 =
143 @<<<<<<<<<<<<<<  @>>>>>>>>>  @>>>>>>>>>>  @>>>>>>>    @>>>>>>>  
144 $date,           $nfiles,    $nbytes/(1024*1024), $pctfiles,  $pctbytes
145 .
146
147 $^ = top1;
148 $~ = line1;
149
150 foreach $date (sort datecompare keys %xferbytes) {
151
152    $nfiles   = $xferfiles{$date};
153    $nbytes   = $xferbytes{$date};
154    $pctfiles = sprintf("%8.2f", 100*$xferfiles{$date} / $xferfiles);
155    $pctbytes = sprintf("%8.2f", 100*$xferbytes{$date} / $xferbytes);
156    write;
157 }
158
159 if ($total_report) {
160 format top2 =
161
162 Total Transfers from each Archive Section (By bytes)
163
164                                                            - Percent -
165      Archive Section                   NFiles     MB      Files   Bytes
166 ------------------------------------- ------- ----------- ----- -------
167 .
168
169 format line2 =
170 @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>>>> @>>>>>>>>>> @>>>>   @>>>>
171 $section,                 $files,    $bytes/(1024*1024),     $pctfiles, $pctbytes
172 .
173
174 $| = 1;
175 $- = 0;
176 $^ = top2;
177 $~ = line2;
178
179 foreach $section (sort bytecompare keys %groupfiles) {
180
181    $files = $groupfiles{$section};
182    $bytes = $groupbytes{$section};
183    $pctbytes = sprintf("%8.2f", 100 * $groupbytes{$section} / $xferbytes);
184    $pctfiles = sprintf("%8.2f", 100 * $groupfiles{$section} / $xferfiles);
185    write;
186
187 }
188
189 if ( $xferfiles < 1 ) { $xferfiles = 1; }
190 if ( $xferbytes < 1 ) { $xferbytes = 1; }
191 }
192
193 if ($domain_report) {
194 format top3 =
195
196 Total Transfer Amount By Domain
197
198              Number Of    Number of    Percent Of  Percent Of
199 Domain Name  Files Sent    MB Sent     Files Sent  Bytes Sent
200 -----------  ----------  ------------  ----------  ----------
201 .
202
203 format line3 =
204 @<<<<<<<<<<  @>>>>>>>>>  @>>>>>>>>>>>  @>>>>>>>    @>>>>>>>  
205 $domain,     $files,     $bytes/(1024*1024), $pctfiles,  $pctbytes
206 .
207
208 $- = 0;
209 $^ = top3;
210 $~ = line3;
211
212 foreach $domain (sort domnamcompare keys %domainfiles) {
213
214    if ( $domainsecs{$domain} < 1 ) { $domainsecs{$domain} = 1; }
215
216    $files = $domainfiles{$domain};
217    $bytes = $domainbytes{$domain};
218    $pctfiles = sprintf("%8.2f", 100 * $domainfiles{$domain} / $xferfiles);
219    $pctbytes = sprintf("%8.2f", 100 * $domainbytes{$domain} / $xferbytes);
220    write;
221
222 }
223
224 }
225
226 if ($hourly_report) {
227
228 format top8 =
229
230 Hourly Transmission Statistics
231
232                  Number Of    Number of   Percent Of  Percent Of
233      Time        Files Sent    MB  Sent   Files Sent  Bytes Sent
234 ---------------  ----------  -----------  ----------  ----------
235 .
236
237 format line8 =
238 @<<<<<<<<<<<<<<  @>>>>>>>>>  @>>>>>>>>>>  @>>>>>>>    @>>>>>>>  
239 $hour,           $nfiles,    $nbytes/(1024*1024), $pctfiles,  $pctbytes
240 .
241
242
243 $| = 1;
244 $- = 0;
245 $^ = top8;
246 $~ = line8;
247
248 foreach $hour (sort keys %xfertbytes) {
249
250    $nfiles   = $xfertfiles{$hour};
251    $nbytes   = $xfertbytes{$hour};
252    $pctfiles = sprintf("%8.2f", 100*$xfertfiles{$hour} / $xferfiles);
253    $pctbytes = sprintf("%8.2f", 100*$xfertbytes{$hour} / $xferbytes);
254    write;
255 }
256 }
257 exit(0);
258
259 sub datecompare {
260     $a gt $b;
261 }
262
263 sub domnamcompare {
264
265    $sdiff = length($a) - length($b);
266    ($sdiff < 0) ? -1 : ($sdiff > 0) ? 1 : ($a lt $b) ? -1 : ($a gt $b) ? 1 : 0;
267
268 }
269
270 sub bytecompare {
271
272    $bdiff = $groupbytes{$b} - $groupbytes{$a};
273    ($bdiff < 0) ? -1 : ($bdiff > 0) ? 1 : ($a lt $b) ? -1 : ($a gt $b) ? 1 : 0;
274
275 }
276
277 sub faccompare {
278
279    $fdiff = $fac{$b} - $fac{$a};
280    ($fdiff < 0) ? -1 : ($fdiff > 0) ? 1 : ($a lt $b) ? -1 : ($a gt $b) ? 1 : 0;
281
282 }
283
284 sub usage
285 {
286     die <<EOT;
287 USAGE: rsyncstats [options]
288
289 OPTIONS:
290   -f FILENAME   Use FILENAME for the log file.
291   -h            Include report on hourly traffic.
292   -d            Include report on domain traffic.
293   -t            Report on total traffic by section.
294   -D DOMAIN     Report only on traffic from DOMAIN.
295   -l DEPTH      Set DEPTH of path detail for sections.
296   -s SECTION    Set SECTION to report on. For example, "-s /pub"
297                 will report only on paths under "/pub".
298 EOT
299 }