#!/usr/bin/perl # # ping_chk.pl のログを集計して結果をpng画像として生成するperlスクリプト。 # # 注) # ・年をまたいだログに対しては処理できない(手抜き) # ・GDモジュールが必要 # ・perl cannot display Japanese. Moreover, I do not understand English. # # by mieki256 # 2003/04/09 ver0.01 月をまたいだログに対して正常に処理できるように修正 use GD; # ---------- 設定 # ログファイル $infile = "pinglog.txt"; # 出力画像ファイル $outfile = "pinglog.png"; # 何分おきに段落を変えるか $kmin = 15; # ---------- 設定ここまで &Message("This script totals the 'pingchk.pl' output logfile , and outputs a graph. The graph is png image."); # log 読み込み &Message("Loading logfile $infile ..."); open(IN,$infile) || &ErrMsg("Can't open $infile ."); @list = ; close(IN); # 有効行抽出 @ln = (); foreach (@list) { chop; next if /job\sstart/; next if /Interval/; next if /is\sdelete/; s%/% %g; s%:% %g; push(@ln,$_); } # 集計処理、png出力 &CountVotesImage; exit; # -------------------------------------------------- # 集計処理 (png出力) sub CountVotesImage { # fontの縦横幅を得る ($fw,$fh) = (gdSmallFont->width,gdSmallFont->height); # 画像サイズを得る ($year0,$mon0,$day0,$hour0,$min0,$sec0,$r0) = get_param($ln[0]); ($year1,$mon1,$day1,$hour1,$min1,$sec1,$r1) = get_param($ln[$#ln]); $range = get_range($year0,$mon0,$day0,$hour0,$year1,$mon1,$day1,$hour1); $x0 = 0; $y0 = 0; $x = 4; $y = 4; $xbase = $x + $fw * 21; $ybase = $y + $fh * 6; $draww = $kmin * 60; $drawh = ($range + 1) * int(60/$kmin) * $fh; $x1 = $xbase + $draww + $fw * 2; $y1 = $ybase + $drawh + $fh * 2; # 出力開始 &Message("Under graph creation ... "); # 新イメージ作成 $im = new GD::Image($x1,$y1); # 色確保 $white = $im->colorAllocate(255,255,255); $black = $im->colorAllocate(0,0,0); $red = $im->colorAllocate(255,0,0); $blue = $im->colorAllocate(0,0,255); $green = $im->colorAllocate(0,255,0); $gray = $im->colorAllocate(96,96,96); $gray2 = $im->colorAllocate(160,160,160); $gray3 = $im->colorAllocate(128,128,128); $nc = $blue; # no check 時の color # 非インターレース化 $im->interlaced('undef'); # bg = black $im->filledRectangle($x0,$y0,$x1-1,$y1-1,$black); # head 部描画 $im->string(gdSmallFont,$x,$y,"$year0/$mon0/$day0 $hour0:$min0:$sec0 -> $year1/$mon1/$day1 $hour1:$min1:$sec1",$white); $y += $fh; $im->string(gdSmallFont,$x,$y,"no check",$blue); $y += $fh; $im->string(gdSmallFont,$x,$y,"link ok",$green); $y += $fh; $im->string(gdSmallFont,$x,$y,"error",$red); $y += $fh; # 時間軸描画 $px = $xbase; $py = $ybase-8; $im->line($px,$py,$px+$kmin*60,$py,$white); for ( $i=0;$i<=$kmin*60;$i+=10) { $im->line($px+$i,$py-2,$px+$i,$py,$white); $im->line($px+$i,$py-4,$px+$i,$py,$white) if ($i % 30) == 0; if ( ($i % 60) == 0 ) { $im->line($px+$i,$py-6,$px+$i,$py,$white); $im->line($px+$i,$py+1,$px+$i,$y1-8,$gray); } } # 日毎の線を描画 $px = $xbase; $py = $ybase; for ( $m = $mon0; $m <= $mon1; $m ++ ) { for ( $d = (($m == $mon0)? $day0 : 1); $d <= (($m == $mon1)? $day1 : get_month_lastday($year0,$m)); $d++ ) { for ( $h = (($m == $mon0 && $d == $day0)? $hour0 : 0); $h <= (($m == $mon1 && $d == $day1)? $hour1 : 23); $h++ ) { for ( $min = 0; $min < 60 ; $min += $kmin ) { my $str = sprintf("%04d/%02d/%02d %02d:%02d:%02d",$year0,$m,$d,$h,$min,0); $im->string(gdSmallFont,$x,$py,"$str",$white); $im->line( $px, $py+$fh-2, $px+$kmin*60-1, $py+$fh-2, $nc ); $py += $fh; } $im->line( ($x + $fw * 11), $py, $x1-1, $py, $gray); } $im->line( 0, $py, $x1-1, $py, $gray2); } } # log結果を描画 &pinglogdraw; # ファイル出力 open(OUT,"> $outfile") || &ErrMsg("Can't open $outfile ."); binmode OUT; print OUT $im->png; close(OUT); &Message("Graph ($outfile) was generated from the log file ($infile)."); } # log結果を描画 sub pinglogdraw { my $old_r = ''; my $old_px = -1; my $old_py = -1; my $now_log; my($year0,$mon0,$day0,$hour0,$min0,$sec0,$r0) = get_param($ln[0]); foreach $now_log (@ln) { my($year1,$mon1,$day1,$hour1,$min1,$sec1,$r1) = get_param($now_log); my $px = ($min1 % $kmin) * 60 + $sec1 + $xbase; my $py = (((get_range($year0,$mon0,$day0,$hour0,$year1,$mon1,$day1,$hour1) * int(60/$kmin)) + int($min1/$kmin)) * $fh) + ($ybase + $fh - 2); if ( $old_r ne "." && $old_py != -1) { while( $old_py <= $py ) { if ( $old_py < $py ) { my $tx = ($kmin * 60 -1) + $xbase; $im->line($old_px,$old_py,$tx,$old_py,$red); $old_px = $xbase; } elsif ( $old_py == $py ) { $im->line($old_px,$old_py,$px,$old_py,$red); } $old_py += $fh; } } if ( $r1 eq '.' ) { $im->line($px,$py,$px,$py-1,$green); } else { $im->line($px,$py,$px,$py-($fh/2),$red); } $old_px = $px; $old_py = $py; $old_r = $r1; } } # 年、月、日、時、分、秒、及び結果を取得。結果以外は数値化する。 sub get_param { my($param) = @_; my($year,$mon,$day,$hour,$min,$sec,$r) = split(/ /,$param); $yaer = int($year); $mon = int($mon); $day = int($day); $hour = int($hour); $min = int($min); $sec = int($sec); return ($year,$mon,$day,$hour,$min,$sec,$r); } # 時間差を得る(単位:hour , 範囲を表すには1足りてないことに注意) sub get_range { my($year0,$mon0,$day0,$hour0,$year1,$mon1,$day1,$hour1) = @_; # &Message("$year0/$mon0/$day0 $hour0:00 - $year1/$mon1/$day1 $hour1:00"); my $range = 0; my $errmsg = "start = $year0/$mon0/$day0 $hour0:00 > end = $year1/$mon1/$day1 $hour1:00"; if ( $year0 == $year1 ) { if ( $mon0 == $mon1 ) { if ( $day0 == $day1 ) { if ( $hour0 <= $hour1 ) { $range = $hour1 - $hour0; } else { &ErrMsg($errmsg); } } elsif ( $day0 < $day1 ) { $range = (24 - $hour0) + $hour1 + (($day1 - $day0 - 1) * 24); } else { &ErrMsg($errmsg); } } elsif ( $mon0 < $mon1 ) { my $m; for ( $m = $mon0; $m <= $mon1; $m++ ) { if ( $m == $mon0 ) { $range = ((get_month_lastday($year0,$mon0) - $day0) * 24) + (24 - $hour0); } elsif ( $m == $mon1 ) { $range += ((($day1 - 1) * 24) + $hour1); } else { $range += (get_month_lastday($year0,$m) * 24); } } } else { &ErrMsg($errmsg); } } elsif ( $year0 < $year1 ) { # 年を越えた範囲は計算できないことにする(手抜き) &ErrMsg("start year $year0 != end year $year1"); } else { &ErrMsg($errmsg); } $range; } # その月の末日を計算(2行目は閏年の計算) # in: $year,$mon # out: $lastday sub get_month_lastday { my($year,$mon) = @_; $year = int($year); $mon = int($mon); my $lastday = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[$mon - 1] + ($mon == 2 && ($year % 4 == 0 && $year % 100 != 0 || $year % 400 == 0)); $lastday; } # (未使用) # 曜日を得る # in: $year,$mon,$day # $year = 年(4桁) # $mon = 月(1-12で。1月は1) # out: $week(0-6) sub getweek{ my($year,$mon,$day) = @_; $year = int($year); $mon = int($mon); $day = int($day); if ($month == 1 || $month == 2) { $year--; $month += 12; } int($year + int($year/4) - int($year/100) + int($year/400) + int((13*$month+8)/5) + $day) % 7; } # エラーメッセージ表示 & exit sub ErrMsg { my($msg) = @_; print "Error : $msg\n"; exit; } # メッセージ表示 sub Message { my($msg) = @_; print "$msg\n"; }