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