#!/usr/local/bin/perl -- ########################################################################## ## ## inndelay.pl: Delay between post and reception of usenet articles. ## ## version: 1.0.3 ## ## Date: 05-31-97 ## ## Copyright (c) 1997, Fabien TASSIN (tassin@eerie.fr). ## ########################################################################## ## ## ABSOLUTELY NO WARRANTY WITH THIS PACKAGE. USE IT AT YOUR OWN RISKS. ## ## Usage: send a part of your history file to inndelay.pl ## ## tail -10000 /var/news/etc/history | inndelay.pl ## or ## inndelay.pl history_extract ## ## This will produce a GIF file (see $out below) ## ## To obtain good results, do not forget to synchronize your clock (with ## xntp for example) before using this tool. ## ## Notes : You need the Perl graphic library GD.pm (1.14 or more) ## GD is available on all good CPAN ftp sites : ## [CPAN_DIR]/authors/id/LDS/GD-1.14.tar.gz ## or directly to : ## http://www-genome.wi.mit.edu/pub/software/WWW/GD.html ## ## Report : please report bugs directly to the author. ## Be sure your are using the latest version of this script. ## (check ftp://ftp.eerie.fr/pub/usenet/inndelay/) ## ########################################################################## # Name of the graph $out = "./inndelay.gif"; # Want articles posted in the future ? $WANT_FUTURE = 1; # Size of the graph ($xmax, $ymax) = (640, 240); ############################################### ## THERE'S NOTHING TO CHANGE AFTER THIS LINE ## ############################################### $version = "1.0.3"; BEGIN { eval "use GD;"; $::HAVE_GD = ($@ eq ""); }; unless ($HAVE_GD) { printf STDERR <) { $max++; unless (/^(<[^>]+>)\s+(\d+)\~.*[^\~]+\~(\d+)\s+\S+/) { $cancel++; next; } # Compute the delay.. $d = $2 - $3; # Articles posted and received at the same second...strange ! if ($d == 0) { $future++; # count them as future $llf{0}++; next; } # Humm.. posted in the future ? if ($d < 0) { $future++; # my ($s) = $1 =~ /<.*\@(.*)>$/; # $bad_date_delay{$s} -= $d; # $bad_date{$s}++; if ($WANT_FUTURE) { if ($d > - 45) { $l = - $d; } else { $l = sprintf "%.2f", log (- $d) / $t; # trunc again $l = sprintf "%d", 10 ** $l; } # and finally store $llf{$l}++; } next; } # Seems to be a cancel... skip it. if (/\scontrol/) { $cancel++; next; } # Finnaly, a "positive" delay.. $done++; if ($d < 45) { $l = $d; } else { $l = sprintf "%.2f", log ($d) / $t; # look at $prec to know the precision # trunc again $l = sprintf "%d", 10 ** $l; } # and finally store $ll{$l}++; } $min_x = 0; $max_x = 0; $max_y = 0; foreach $v (sort (keys (%ll))) { $max_x = $v if ($max_x < $v); $max_y = $ll{"$v"} if ($max_y < $ll{"$v"}); } if ($WANT_FUTURE) { foreach $v (sort (keys (%llf))) { $min_x = - $v if ($min_x > - $v); $max_y = $llf{"$v"} if ($max_y < $llf{"$v"}); } } $max_x = log ($max_x) / log (10); $min_x = - log (- $min_x) / log (10) unless ($min_x == 0); $c = sprintf "%.1f%%", $max_y / $done * 100; ($ml, $mr, $mt, $mb) = (gdSmallFont->width * length ("$c") + 12, 30, gdSmallFont->height * 2 + 35, 45); $image = new GD::Image ($xmax, $ymax); $white = $image->colorAllocate (255, 255, 255); $black = $image->colorAllocate ( 0, 0, 0); $blue = $image->colorAllocate ( 0, 0, 255); $red = $image->colorAllocate (255, 0, 0); $col1 = $image->colorAllocate (255, 200, 0); $image->setStyle ($black, $black, gdTransparent, gdTransparent, gdTransparent, gdTransparent, gdTransparent); # title $s = "Delay between post and reception"; $image->string (gdMediumBoldFont, ($xmax - length ($s) * gdMediumBoldFont->width) / 2, $ymax - gdMediumBoldFont->height - 5, $s, $black); # header $image->string (gdSmallFont, $ml, 5, sprintf ("Number of articles: %10d", $max), $black); $image->string (gdSmallFont, $xmax / 2, 5, sprintf ("Processed: %10d (%.1f%%)", $done, $done / $max * 100), $black); $image->string (gdSmallFont, $xmax / 2, 7 + gdSmallFont->height, sprintf ("Posted in the future: %10d (%.1f%%)", $future, $future / $max * 100), $black); $image->string (gdSmallFont, $ml, 7 + gdSmallFont->height, sprintf ("Cancelled or Expired: %10d (%.1f%%)", $cancel, $cancel / $max * 100), $black); if ($WANT_FUTURE) { $image->filledRectangle ($xmax / 2 - 15, 5, $xmax / 2 - 5, 3 + gdSmallFont->height, $blue); $image->rectangle ($xmax / 2 - 15, 5, $xmax / 2 - 5, 3 + gdSmallFont->height, $black); $image->filledRectangle ($xmax / 2 - 15, 7 + gdSmallFont->height, $xmax / 2 - 5, 5 + 2 * gdSmallFont->height, $red); $image->rectangle ($xmax / 2 - 15, 7 + gdSmallFont->height, $xmax / 2 - 5, 5 + 2 * gdSmallFont->height, $black); } # border $image->rectangle ($ml, $mt, $xmax - $mr, $ymax - $mb, $black); # graduations $image->line ($ml - 3, $ymax - $mb, $ml, $ymax - $mb, $black); $image->string (gdSmallFont, $ml - length ("0%") * gdSmallFont->width - 5, $ymax - $mb - gdSmallFont->height / 2, "0%", $black); $image->line ($ml - 3, $mt, $ml, $mt, $black); for ($i = 1; $i < 4; $i++) { $image->line ($ml - 3, $mt + ($ymax - $mt - $mb) * $i / 4, $xmax - $mr, $mt + ($ymax - $mt - $mb) * $i / 4, gdStyled); } $image->string (gdSmallFont, $ml - length ("$c") * gdSmallFont->width - 5, $mt - gdSmallFont->height / 2, "$c", $black); # ratio if ($WANT_FUTURE) { $rx = ($xmax - $mr - $ml - 2 * $adj) / ($max_x - $min_x + $prec + 2 * $adj); $ry = ($ymax - $mt - $mb) / $max_y; } else { $rx = ($xmax - $mr - $ml) / ($max_x - $min_x + $prec); $ry = ($ymax - $mt - $mb) / $max_y; } $i = 0; $p = 0; $pp = 1; $l = 0; foreach $v (sort {$a <=> $b} (keys (%ll))) { my ($t1, $t2); if ($v < 60) { $t1 = log ($v) / log (10); $t2 = log ($v + 1) / log (10); } else { $t1 = log ($v) / log (10); $t2 = log ($v) / log (10) + $prec; } if ($WANT_FUTURE) { $t1 += 2 * $adj; $t2 += 2 * $adj; } $p += $ll{$v}; if ($p / $done * 10 > $pp) { $image->line ($ml + ($t2 - $min_x) * $rx, $mt, $ml + ($t2 - $min_x) * $rx, $ymax - $mb, gdStyled); $image->line ($ml + ($t2 - $min_x) * $rx, $mt - 3, $ml + ($t2 - $min_x) * $rx, $mt, $black); my $s = sprintf "%d%%", $pp++ * 10; my $ss = $ml + ($t2 - $min_x) * $rx - (gdSmallFont->width * length $s) / 2; if ($ss > $l + 3 * gdSmallFont->width) { $image->string (gdSmallFont, $ss, $mt - gdSmallFont->height - 5, $s, $black); $l = $ss; } } $image->filledRectangle ($ml + ($t1 - $min_x) * $rx, $ymax - $mb - $ll{$v} * $ry, $ml + ($t2 - $min_x) * $rx, $ymax - $mb, $blue); } if ($WANT_FUTURE) { $pf = 0; $ppf = 1; $l = $xmax; foreach $v (sort {$a <=> $b} (keys (%llf))) { my ($t1, $t2); if ($v == 0) { $t1 = $adj; $t2 = -$adj; } elsif ($v < 60) { $t1 = - $adj - log ($v) / log (10); $t2 = - $adj - log ($v + 1) / log (10); } else { $t1 = - $adj - log ($v) / log (10); $t2 = - $adj - (log ($v) / log (10) + $prec); } $pf += $llf{$v}; #printf "pf = $pf\t future = $future\t %d $ppf \n", $pf / $future * 10; if ($pf / $future * 10 > $ppf) { $image->line ($ml + ($t1 - $min_x + $adj) * $rx, $mt, $ml + ($t1 - $min_x + $adj) * $rx, $ymax - $mb, gdStyled); $image->line ($ml + ($t1 - $min_x + $adj) * $rx, $mt - 3, $ml + ($t1 - $min_x + $adj) * $rx, $mt, $black); my $s = sprintf "%d%%", $ppf++ * 10; my $ss = $ml + ($t1 - $min_x + $adj) * $rx - (gdSmallFont->width * length $s) / 2; if ($ss < $l - 3 * gdSmallFont->width) { $image->string (gdSmallFont, $ss, $mt - gdSmallFont->height - 5, $s, $black); $l = $ss; } } if ($v == 0) { $image->filledRectangle ($ml + ($adj + $t2 - $min_x) * $rx, $ymax - $mb - $llf{$v} * $ry, $ml + ($adj + $t1 - $min_x) * $rx, $ymax - $mb, $col1); # Axe $image->line ($ml + ($adj + ($t1 + $t2) / 2 - $min_x) * $rx, $mt - 3, $ml + ($adj + ($t1 + $t2) / 2 - $min_x) * $rx, $ymax - $mb, $black); $image->string (gdSmallFont, $ml + ($adj + ($t1 + $t2) / 2 - $min_x) * $rx - gdSmallFont->width, $mt - gdSmallFont->height - 5, "0%", $black); } else { $image->filledRectangle ($ml + ($adj + $t2 - $min_x) * $rx, $ymax - $mb - $llf{$v} * $ry, $ml + ($adj + $t1 - $min_x) * $rx, $ymax - $mb, $red); } } } my $s = "100%"; $image->string (gdSmallFont, $xmax - $mr - (gdSmallFont->width * length $s) / 2, $mt - gdSmallFont->height - 5, $s, $black); $image->line ($xmax - $mr, $mt -3, $xmax - $mr , $mt, $black); # Graduations @a = (1, 3, 7, 15, 30, # seconds 60, 180, 420, 1800, # minutes 3600, 10800, 43200, # hours 86400, 259200, 864000); # days # Labels @b = ("1s", "3s", "7s", "15s", "30s", "1mn", "3mn", "7mn", "30mn", "1h", "3h", "12h", "1day", "3days", "10days"); ($t1, $t2) = (1, 0); for ($i = 0; $i <= $#a; $i++) { $v = $a[$i]; next if (log ($v) / log (10) > $max_x); $image->line ($ml + (2 * $adj + log ($v) / log (10) - $min_x) * $rx, $ymax - $mb, $ml + (2 * $adj + log ($v) / log (10) - $min_x) * $rx, $ymax - $mb + 5, $black); $image->string (gdSmallFont, $ml + (2 * $adj + log ($v) / log (10) - $min_x) * $rx - length ("$b[$i]") * gdSmallFont->width / 2, $ymax - $mb + 7 + 9 * $t1, $b[$i], $black); $t1 = $t1 ? 0 : 1; if ($WANT_FUTURE) { my $t = log ($a[$i]) / log (10); if ($t <= - $min_x) { $image->line ($ml + (- log ($v) / log (10) - $min_x) * $rx, $ymax - $mb, $ml + (- log ($v) / log (10) - $min_x) * $rx, $ymax - $mb + 5, $black); $image->string (gdSmallFont, $ml + (- log ($v) / log (10) - $min_x) * $rx - length ("$b[$i]") * gdSmallFont->width / 2, $ymax - $mb + 7 + 9 * $t2, $b[$i], $black); } $t2 = $t2 ? 0 : 1; } } open (IMG, "> $out") || die "can open \"$out\": $!\n"; print IMG $image->gif; close (IMG); #$bad_date_delay{$s} -= $d; #$bad_date{$s}++; #print "Sort by delay:\n"; #foreach $host (sort {$bad_date_delay{$b} / $bad_date{$b} <=> # $bad_date_delay{$a} / $bad_date{$a}} # (keys (%bad_date_delay))) #{ # printf "%10d %10d %s\n", $bad_date_delay{$host} / $bad_date{$host}, # $bad_date{$host}, $host; #}