rsyncstats 8.6 KB

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