Annotation of embedaddon/ntp/scripts/summary.in, revision 1.1
1.1 ! misho 1: #! @PATH_PERL@ -w
! 2: # $Id$
! 3: # Perl version of (summary.sh, loop.awk, peer.awk):
! 4: # Create summaries from xntpd's loop and peer statistics.
! 5: #
! 6: # Copyright (c) 1997, 1999 by Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de>
! 7: #
! 8: # This program is free software; you can redistribute it and/or modify
! 9: # it under the terms of the GNU General Public License as published by
! 10: # the Free Software Foundation; either version 2 of the License, or
! 11: # (at your option) any later version.
! 12: #
! 13: # This program is distributed in the hope that it will be useful, but
! 14: # WITHOUT ANY WARRANTY; without even the implied warranty of
! 15: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! 16: # General Public License for more details.
! 17: #
! 18: # You should have received a copy of the GNU General Public License
! 19: # along with this program; if not, write to the Free Software
! 20: # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
! 21:
! 22: require 5.003; # "never tested with any other version of Perl"
! 23: use strict;
! 24:
! 25: use Getopt::Long;
! 26:
! 27: my $log_date_pattern = '[12]\d{3}[01]\d[0-3]\d';
! 28: my $statsdir = "/var/log/ntp"; # directory with input files
! 29: my $outputdir = "/tmp"; # directory for output files
! 30: my $skip_time_steps = 3600.0; # ignore time offsets larger that this
! 31: my $startdate = "19700101"; # first data file to use (YYYYMMDD)
! 32: my $enddate=`date -u +%Y%m%d`; chomp $enddate; --$enddate;
! 33: my $peer_dist_limit = 400.0;
! 34:
! 35: my %options = ("directory|input-directory=s" => \$statsdir,
! 36: "output-directory=s" => \$outputdir,
! 37: "skip-time-steps:f" => \$skip_time_steps,
! 38: "start-date=s" => \$startdate,
! 39: "end-date=s" => \$enddate,
! 40: "peer-dist-limit=f" => \$peer_dist_limit);
! 41:
! 42: if ( !GetOptions(%options) )
! 43: {
! 44: print STDERR "valid options for $0 are:\n";
! 45: my $opt;
! 46: foreach $opt (sort(keys %options)) {
! 47: print STDERR "\t--$opt\t(default is ";
! 48: if ( ref($options{$opt}) eq "ARRAY" ) {
! 49: print STDERR join(", ", map { "'$_'" } @{$options{$opt}});
! 50: } else {
! 51: print STDERR "'${$options{$opt}}'";
! 52: }
! 53: print STDERR ")\n";
! 54: }
! 55: print STDERR "\n";
! 56: die;
! 57: }
! 58:
! 59: # check possibly current values of options
! 60: die "$statsdir: no such directory" unless (-d $statsdir);
! 61: die "$outputdir: no such directory" unless (-d $outputdir);
! 62: die "$skip_time_steps: skip-time-steps must be positive"
! 63: unless ($skip_time_steps >= 0.0);
! 64: die "$startdate: invalid start date|$`|$&|$'"
! 65: unless ($startdate =~ m/.*$log_date_pattern$/);
! 66: die "$enddate: invalid end date"
! 67: unless ($enddate =~ m/.*$log_date_pattern$/);
! 68:
! 69: $skip_time_steps = 0.128 if ($skip_time_steps == 0);
! 70:
! 71: sub min
! 72: {
! 73: my ($result, @rest) = @_;
! 74: map { $result = $_ if ($_ < $result) } @rest;
! 75: return($result);
! 76: }
! 77:
! 78: sub max
! 79: {
! 80: my ($result, @rest) = @_;
! 81: map { $result = $_ if ($_ > $result) } @rest;
! 82: return($result);
! 83: }
! 84:
! 85: # calculate mean, range, and standard deviation for offset and frequency
! 86: sub do_loop
! 87: {
! 88: my ($directory, $fname, $out_file) = @_;
! 89: print "$directory/$fname\n";
! 90: open INPUT, "$directory/$fname" or warn "can't open $directory/$fname: $!";
! 91: open OUTPUT, ">>$out_file" or die "can't open $out_file: $!";
! 92: print OUTPUT "$fname\n";
! 93: my ($loop_tmax, $loop_fmax) = (-1e9, -1e9);
! 94: my ($loop_tmin, $loop_fmin) = (1e9, 1e9);
! 95: my ($loop_time_rms, $loop_freq_rms) = (0, 0);
! 96: my $loop_count = 0;
! 97: my $loop_time = 0;
! 98: my $loop_freq = 0;
! 99: my ($freq, $offs);
! 100: my @Fld;
! 101: while (<INPUT>) {
! 102: chop; # strip record separator
! 103: @Fld = split;
! 104: next if ($#Fld < 4);
! 105: #NTPv3: 50529 74356.259 -0.000112 16.1230 8
! 106: #NTPv3: day, sec.msec, offset, drift_comp, sys_poll
! 107: #NTPv4: 51333 54734.582 0.000001648 16.981964 0.000001094 0.020938 6
! 108: #NTPv4: day, sec.msec, offset, drift_comp, sys_error, clock_stabil, sys_poll
! 109: if ($Fld[2] > $skip_time_steps || $Fld[2] < -$skip_time_steps) {
! 110: warn "ignoring loop offset $Fld[2] (file $fname, line $.)\n";
! 111: next
! 112: }
! 113: $loop_count++;
! 114: ($offs, $freq) = ($Fld[2], $Fld[3]);
! 115: $loop_tmax = max($loop_tmax, $offs);
! 116: $loop_tmin = min($loop_tmin, $offs);
! 117: $loop_fmax = max($loop_fmax, $freq);
! 118: $loop_fmin = min($loop_fmin, $freq);
! 119: $loop_time += $offs;
! 120: $loop_time_rms += $offs * $offs;
! 121: $loop_freq += $freq;
! 122: $loop_freq_rms += $freq * $freq;
! 123: }
! 124: close INPUT;
! 125: if ($loop_count > 1) {
! 126: $loop_time /= $loop_count;
! 127: $loop_time_rms = $loop_time_rms / $loop_count - $loop_time * $loop_time;
! 128: if ($loop_time_rms < 0) {
! 129: warn "loop_time_rms: $loop_time_rms < 0";
! 130: $loop_time_rms = 0;
! 131: }
! 132: $loop_time_rms = sqrt($loop_time_rms);
! 133: $loop_freq /= $loop_count;
! 134: $loop_freq_rms = $loop_freq_rms / $loop_count - $loop_freq * $loop_freq;
! 135: if ($loop_freq_rms < 0) {
! 136: warn "loop_freq_rms: $loop_freq_rms < 0";
! 137: $loop_freq_rms = 0;
! 138: }
! 139: $loop_freq_rms = sqrt($loop_freq_rms);
! 140: printf OUTPUT
! 141: ("loop %d, %.0f+/-%.1f, rms %.1f, freq %.2f+/-%0.3f, var %.3f\n",
! 142: $loop_count, ($loop_tmax + $loop_tmin) / 2 * 1e6,
! 143: ($loop_tmax - $loop_tmin) / 2 * 1e6, $loop_time_rms * 1e6,
! 144: ($loop_fmax + $loop_fmin) / 2, ($loop_fmax - $loop_fmin) / 2,
! 145: $loop_freq_rms);
! 146: }
! 147: else {
! 148: warn "no valid lines in $directory/$fname";
! 149: }
! 150: close OUTPUT
! 151: }
! 152:
! 153: # calculate mean, standard deviation, maximum offset, mean dispersion,
! 154: # and maximum distance for each peer
! 155: sub do_peer
! 156: {
! 157: my ($directory, $fname, $out_file) = @_;
! 158: print "$directory/$fname\n";
! 159: open INPUT, "$directory/$fname" or warn "can't open $directory/$fname: $!";
! 160: open OUTPUT, ">>$out_file" or die "can't open $out_file: $!";
! 161: print OUTPUT "$fname\n";
! 162: # we toss out all distances greater than one second on the assumption the
! 163: # peer is in initial acquisition
! 164: my ($n, $MAXDISTANCE) = (0, 1.0);
! 165: my %peer_time;
! 166: my %peer_time_rms;
! 167: my %peer_count;
! 168: my %peer_delay;
! 169: my %peer_disp;
! 170: my %peer_dist;
! 171: my %peer_ident;
! 172: my %peer_tmin;
! 173: my %peer_tmax;
! 174: my @Fld;
! 175: my ($i, $j);
! 176: my ($dist, $offs);
! 177: while (<INPUT>) {
! 178: chop; # strip record separator
! 179: @Fld = split;
! 180: next if ($#Fld < 6);
! 181: #NTPv3: 50529 83316.249 127.127.8.1 9674 0.008628 0.00000 0.00700
! 182: #NTPv3: day, sec.msec, addr, status, offset, delay, dispersion
! 183: #NTPv4: 51333 56042.037 127.127.8.1 94f5 -0.000014657 0.000000000 0.000000000 0.000013214
! 184: #NTPv4: day, sec.msec, addr, status, offset, delay, dispersion, skew
! 185:
! 186: $dist = $Fld[6] + $Fld[5] / 2;
! 187: next if ($dist > $MAXDISTANCE);
! 188: $offs = $Fld[4];
! 189: if ($offs > $skip_time_steps || $offs < -$skip_time_steps) {
! 190: warn "ignoring peer offset $offs (file $fname, line $.)\n";
! 191: next
! 192: }
! 193: $i = $n;
! 194: for ($j = 0; $j < $n; $j++) {
! 195: if ($Fld[2] eq $peer_ident{$j}) {
! 196: $i = $j; # peer found
! 197: last;
! 198: }
! 199: }
! 200: if ($i == $n) { # add new peer
! 201: $peer_ident{$i} = $Fld[2];
! 202: $peer_tmax{$i} = $peer_dist{$i} = -1e9;
! 203: $peer_tmin{$i} = 1e9;
! 204: $peer_time{$i} = $peer_time_rms{$i} = 0;
! 205: $peer_delay{$i} = $peer_disp{$i} = 0;
! 206: $peer_count{$i} = 0;
! 207: $n++;
! 208: }
! 209: $peer_count{$i}++;
! 210: $peer_tmax{$i} = max($peer_tmax{$i}, $offs);
! 211: $peer_tmin{$i} = min($peer_tmin{$i}, $offs);
! 212: $peer_dist{$i} = max($peer_dist{$i}, $dist);
! 213: $peer_time{$i} += $offs;
! 214: $peer_time_rms{$i} += $offs * $offs;
! 215: $peer_delay{$i} += $Fld[5];
! 216: $peer_disp{$i} += $Fld[6];
! 217: }
! 218: close INPUT;
! 219: print OUTPUT
! 220: " ident cnt mean rms max delay dist disp\n";
! 221: print OUTPUT
! 222: "==========================================================================\n";
! 223: my @lines = ();
! 224: for ($i = 0; $i < $n; $i++) {
! 225: next if $peer_count{$i} < 2;
! 226: $peer_time{$i} /= $peer_count{$i};
! 227: eval { $peer_time_rms{$i} = sqrt($peer_time_rms{$i} / $peer_count{$i} -
! 228: $peer_time{$i} * $peer_time{$i}); };
! 229: $peer_time_rms{$i} = 0, warn $@ if $@;
! 230: $peer_delay{$i} /= $peer_count{$i};
! 231: $peer_disp{$i} /= $peer_count{$i};
! 232: $peer_tmax{$i} = $peer_tmax{$i} - $peer_time{$i};
! 233: $peer_tmin{$i} = $peer_time{$i} - $peer_tmin{$i};
! 234: if ($peer_tmin{$i} > $peer_tmax{$i}) { # can this happen at all?
! 235: $peer_tmax{$i} = $peer_tmin{$i};
! 236: }
! 237: push @lines, sprintf
! 238: "%-15s %4d %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f\n",
! 239: $peer_ident{$i}, $peer_count{$i}, $peer_time{$i} * 1e3,
! 240: $peer_time_rms{$i} * 1e3, $peer_tmax{$i} * 1e3,
! 241: $peer_delay{$i} * 1e3, $peer_dist{$i} * 1e3, $peer_disp{$i} * 1e3;
! 242: }
! 243: print OUTPUT sort @lines;
! 244: close OUTPUT;
! 245: }
! 246:
! 247: sub do_clock
! 248: {
! 249: my ($directory, $fname, $out_file) = @_;
! 250: print "$directory/$fname\n";
! 251: open INPUT, "$directory/$fname";
! 252: open OUTPUT, ">>$out_file" or die "can't open $out_file: $!";
! 253: print OUTPUT "$fname\n";
! 254: close INPUT;
! 255: close OUTPUT;
! 256: }
! 257:
! 258: sub peer_summary
! 259: {
! 260: my $in_file = shift;
! 261: my ($i, $j, $n);
! 262: my (%peer_ident, %peer_count, %peer_mean, %peer_var, %peer_max);
! 263: my (%peer_1, %peer_2, %peer_3, %peer_4);
! 264: my $dist;
! 265: my $max;
! 266: open INPUT, "<$in_file" or die "can't open $in_file: $!";
! 267: my @Fld;
! 268: $n = 0;
! 269: while (<INPUT>) {
! 270: chop; # strip record separator
! 271: @Fld = split;
! 272: next if ($#Fld < 7 || $Fld[0] eq 'ident');
! 273: $i = $n;
! 274: for ($j = 0; $j < $n; $j++) {
! 275: if ($Fld[0] eq $peer_ident{$j}) {
! 276: $i = $j;
! 277: last; # peer found
! 278: }
! 279: }
! 280: if ($i == $n) { # add new peer
! 281: $peer_count{$i} = $peer_mean{$i} = $peer_var{$i} = 0;
! 282: $peer_max{$i} = 0;
! 283: $peer_1{$i} = $peer_2{$i} = $peer_3{$i} = $peer_4{$i} = 0;
! 284: $peer_ident{$i} = $Fld[0];
! 285: ++$n;
! 286: }
! 287: $dist = $Fld[6] - $Fld[5] / 2;
! 288: if ($dist < $peer_dist_limit) {
! 289: $peer_count{$i}++;
! 290: $peer_mean{$i} += $Fld[2];
! 291: $peer_var{$i} += $Fld[3] * $Fld[3];
! 292: $max = $Fld[4];
! 293: $peer_max{$i} = max($peer_max{$i}, $max);
! 294: if ($max > 1) {
! 295: $peer_1{$i}++;
! 296: if ($max > 5) {
! 297: $peer_2{$i}++;
! 298: if ($max > 10) {
! 299: $peer_3{$i}++;
! 300: if ($max > 50) {
! 301: $peer_4{$i}++;
! 302: }
! 303: }
! 304: }
! 305: }
! 306: }
! 307: else {
! 308: warn "dist exceeds limit: $dist (file $in_file, line $.)\n";
! 309: }
! 310: }
! 311: close INPUT;
! 312: my @lines = ();
! 313: print
! 314: " host days mean rms max >1 >5 >10 >50\n";
! 315: print
! 316: "==================================================================\n";
! 317: for ($i = 0; $i < $n; $i++) {
! 318: next if ($peer_count{$i} < 2);
! 319: $peer_mean{$i} /= $peer_count{$i};
! 320: eval { $peer_var{$i} = sqrt($peer_var{$i} / $peer_count{$i} -
! 321: $peer_mean{$i} * $peer_mean{$i}); };
! 322: $peer_var{$i} = 0, warn $@ if $@;
! 323: push @lines, sprintf
! 324: "%-15s %3d %9.3f% 9.3f %9.3f %3d %3d %3d %3d\n",
! 325: $peer_ident{$i}, $peer_count{$i}, $peer_mean{$i}, $peer_var{$i},
! 326: $peer_max{$i}, $peer_1{$i}, $peer_2{$i}, $peer_3{$i}, $peer_4{$i};
! 327: }
! 328: print sort @lines;
! 329: }
! 330:
! 331: my $loop_summary="$outputdir/loop_summary";
! 332: my $peer_summary="$outputdir/peer_summary";
! 333: my $clock_summary="$outputdir/clock_summary";
! 334: my (@loopfiles, @peerfiles, @clockfiles);
! 335:
! 336: print STDERR "Creating summaries from $statsdir ($startdate to $enddate)\n";
! 337:
! 338: opendir SDIR, $statsdir or die "directory ${statsdir}: $!";
! 339: rewinddir SDIR;
! 340: @loopfiles=sort grep /loop.*$log_date_pattern/, readdir SDIR;
! 341: rewinddir SDIR;
! 342: @peerfiles=sort grep /peer.*$log_date_pattern/, readdir SDIR;
! 343: rewinddir SDIR;
! 344: @clockfiles=sort grep /clock.*$log_date_pattern/, readdir SDIR;
! 345: closedir SDIR;
! 346:
! 347: # remove old summary files
! 348: map { unlink $_ if -f $_ } ($loop_summary, $peer_summary, $clock_summary);
! 349:
! 350: my $date;
! 351: map {
! 352: $date = $_; $date =~ s/.*($log_date_pattern)$/$1/;
! 353: if ($date ge $startdate && $date le $enddate) {
! 354: do_loop $statsdir, $_, $loop_summary;
! 355: }
! 356: } @loopfiles;
! 357:
! 358: map {
! 359: $date = $_; $date =~ s/.*($log_date_pattern)$/$1/;
! 360: if ($date ge $startdate && $date le $enddate) {
! 361: do_peer $statsdir, $_, $peer_summary;
! 362: }
! 363: } @peerfiles;
! 364:
! 365: map {
! 366: $date = $_; $date =~ s/.*($log_date_pattern)$/$1/;
! 367: if ($date ge $startdate && $date le $enddate) {
! 368: do_clock $statsdir, $_, $clock_summary;
! 369: }
! 370: } @clockfiles;
! 371:
! 372: print STDERR "Creating peer summary with limit $peer_dist_limit\n";
! 373: peer_summary $peer_summary if (-f $peer_summary);
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>