--- parse_log.cgi 2003/10/05 22:26:34 1.3 +++ parse_log.cgi 2003/10/06 22:32:06 1.5 @@ -13,11 +13,13 @@ use Data::Sorting qw(:arrays); use Time::ParseDate; use Time::Available; +use Cache::FileCache; use Data::Dumper; my $date_fmt = "%Y-%m-%d"; -my $date_time_fmt = "%Y-%m-%d %H:%M:%S"; +#my $date_time_fmt = "%Y-%m-%d %H:%M:%S"; +my $date_time_fmt = "%a %Y-%m-%d %H:%M:%S"; my $from_date = "now - 6 months"; my $to_date = "now"; @@ -28,7 +30,7 @@ my $from_time_interval = "7:00"; my $to_time_interval = "17:00"; -my $debug=1; +my $debug=0; $debug++ if (grep(/-v/,@ARGV)); $debug++ if (grep(/-d/,@ARGV)); @@ -49,19 +51,19 @@ my @sg_selected = $q->param('sg_filter'); # init misc sort parametars -my @sort; +my @sort_rules; my $order; my %sort_param; my ($usort,$dsort); if ($q->param('usort')) { $sort_param{'usort'} = $q->param('usort'); $q->delete('usort'); - @sort = ( -compare => 'numeric', $sort_param{'usort'} ); + @sort_rules = ( -compare => 'numeric', scalar $sort_param{'usort'} ); } if ($q->param('dsort')) { $sort_param{'dsort'} = $q->param('dsort'); $q->delete('dsort'); - @sort = ( -compare => 'numeric', -order=>'reverse', $sort_param{'dsort'} ); + @sort_rules = ( -compare => 'numeric', -order=>'reverse', scalar $sort_param{'dsort'} ); } # make interval @@ -74,6 +76,9 @@ $working_days=new Time::Available(start=>$q->param('from_time_interval'),end=>$q->param('to_time_interval'),dayMask=>$dayMask); } +# init cache and setup expriration +my $cache = new Cache::FileCache({ default_expires_in => '10 min' }); + # # This option (activated via command switch -r) will reset failure duration # if repeated failure on same group/service happend. @@ -118,66 +123,74 @@ # my %fail; -my %downtime; # total downtime -my %sg_filter; # filter for service/group -my %sg_count; # count number of downtimes - -my $log_file="/home/dpavlin/mon-log/sap.log"; - -my @data; - -open(LOG, $log_file) || die "$log_file: $!"; - -while() { - chomp; - if (/^(failure|up)\s+(\S+)\s+(\S+)\s+(\d+)\s+\(([^)]+)\)\s+(.+)$/) { - my ($status,$group,$service,$utime,$date,$desc) = ($1,$2,$3,$4,$5,$6); - my $id = "$group/$service"; - if ($status eq "up" && defined($fail{$id})) { - if (grep(m;$group/$service;,@sg_selected)) { - push @data, { - 'sg'=>"$group/$service", - 'from'=>$fail{$id}, - 'to'=>$utime, - 'dur'=>($utime - $fail{$id}), - 'int'=>$working_days->interval($utime,$fail{$id}), - 'desc'=>$desc }; - $downtime{"$group/$service"} += ($utime - $fail{$id}), - $sg_count{"$group/$service"}++; - } - $sg_filter{"$group/$service"}++; - delete $fail{$id}; - } elsif ($status eq "up") { - if ($print_orphans && grep(m;$group/$service;,@sg_selected)) { - push @data, { - 'sg'=>"$group/$service", - 'from'=>-1, - 'to'=>$utime, - 'desc'=>$desc }; - $sg_count{"$group/$service"}++; - } - delete $fail{$id}; - $sg_filter{"$group/$service"}++; - } elsif (defined($fail{$id})) { - if ($rep_reset && grep(m;$group/$service;,@sg_selected)) { - push @data, { - 'sg'=>"$group/$service", - 'from'=>$fail{$id}, - 'to'=>$utime, - 'dur'=>($utime - $fail{$id}), - 'int'=>$working_days->interval($utime,$fail{$id}), - 'desc'=>'[failure again]'}; - $downtime{"$group/$service"} += ($utime - $fail{$id}), +my $sg_filter; # filter for service/group + +my $log_file="/var/log/mon/sap.log"; + +my $data; + +# generate unique key for this data and options +my $cache_key="monlog".join("|",@sg_selected)."|".$print_orphans."|".$rep_reset; + +# debug disables cache +if (! $debug) { + $data = $cache->get( $cache_key ); + $sg_filter = $cache->get("sg_filter $cache_key"); +} + +if (!$data || !$sg_filter) { + + open(LOG, $log_file) || die "$log_file: $!"; + + while() { + chomp; + if (/^(failure|up)\s+(\S+)\s+(\S+)\s+(\d+)\s+\(([^)]+)\)\s+(.+)$/) { + my ($status,$group,$service,$utime,$date,$desc) = ($1,$2,$3,$4,$5,$6); + my $id = "$group/$service"; + if ($status eq "up" && defined($fail{$id})) { + if (grep(m;$group/$service;,@sg_selected)) { + push @$data, { + 'sg'=>"$group/$service", + 'from'=>$fail{$id}, + 'to'=>$utime, + 'dur'=>($utime-$fail{id}), + 'desc'=>$desc }; + } + $sg_filter->{"$group/$service"}++; + delete $fail{$id}; + } elsif ($status eq "up") { + if ($print_orphans && grep(m;$group/$service;,@sg_selected)) { + push @$data, { + 'sg'=>"$group/$service", + 'from'=>-1, + 'to'=>$utime, + 'dur'=>0, + 'desc'=>$desc }; + } + delete $fail{$id}; + $sg_filter->{"$group/$service"}++; + } elsif (defined($fail{$id})) { + if ($rep_reset && grep(m;$group/$service;,@sg_selected)) { + push @$data, { + 'sg'=>"$group/$service", + 'from'=>$fail{$id}, + 'to'=>$utime, + 'dur'=>($utime-$fail{id}), + 'desc'=>'[failure again]'}; + $fail{$id} = $utime; + } + $sg_filter->{"$group/$service"}++; + } else { $fail{$id} = $utime; - $sg_count{"$group/$service"}++; } - $sg_filter{"$group/$service"}++; - } else { - $fail{$id} = $utime; } } + close(LOG); + + $cache->set($cache_key, $data); + $cache->set("sg_filter $cache_key", $sg_filter); + } -close(LOG); # generate output # @@ -191,26 +204,26 @@ Tr(td( em("Show just service/group:"),br, checkbox_group(-name=>'sg_filter', - -values=>[keys %sg_filter], - -default=>[keys %sg_filter], + -values=>[keys %$sg_filter], + -default=>[keys %$sg_filter], -linebreak=>'true', ), ),td( em("Other options:"),br, - $q->checkbox(-name=>'rep_reset',-checked=>0, + $q->checkbox(-name=>'rep_reset',-default=>0, -label=>"show repeated failures on same service as individual failures"), br, - $q->checkbox(-name=>'print_orphans',-checked=>0, + $q->checkbox(-name=>'print_orphans',-default=>0, -label=>"show records which are not complete in this interval"), br, - $q->checkbox(-name=>'use_date_limit',-checked=>1, + $q->checkbox(-name=>'use_date_limit',-default=>1, -label=>"use date limit from:"), $q->textfield(-name=>'from_date',-size=>20,-default=>$from_date), " to: ", $q->textfield(-name=>'to_date',-size=>20,-default=>$to_date), small('Using Time::ParseDate'), br, - $q->checkbox(-name=>'use_time_limit',-checked=>1, + $q->checkbox(-name=>'use_time_limit',-default=>1, -label=>"use time limit for each day:"), $q->textfield(-name=>'from_time_interval',-size=>8,-default=>$from_time_interval), " to: ", @@ -233,14 +246,21 @@ # dump report # +my %dir_html_entity = ( +# 'u' => '⇑', +# 'd' => '⇓' + 'u' => '▲', + 'd' => '▼', +); + sub sort_link { my $q = shift || return; my $col = shift || return; my $dir = lc(shift) || return; if ($sort_param{$dir.'sort'} && $sort_param{$dir.'sort'} eq $col) { - return '&'.$dir.'Arr;'; + return $dir_html_entity{$dir}; } else { - return '&'.$dir.'Arr;'; + return ''.$dir_html_entity{$dir}.''; } } @@ -257,46 +277,58 @@ # sort data # -my @sorted = sorted_array(@data, @sort); -#my @sorted = @data; +my @sorted = sorted_array( @$data, @sort_rules ); -print "-- sort: ",Dumper(@sort)," (data: ".@data." sorted: ".@sorted.") --\n",br,"-- dayMask: $dayMask --\n",br if ($debug); +print "-- sort: ",Dumper(@sort_rules)," (data: ".@$data." sorted: ".@sorted.") --\n",br,"-- dayMask: $dayMask --\n",br,"-- cache_key: $cache_key --\n",br if ($debug); print start_table({-border=>1,-cellspacing=>0,-cellpadding=>2,-width=>'100%'}); print Tr( th("group/service"), - th({-bgcolor=>'#f0f0f0'}, + th({-bgcolor=>'#f0f0f0'},''. &sort_link($q,'from','u').' from '. - &sort_link($q,'from','d'), + &sort_link($q,'from','d').'', br,$from_html ), - th( + th( ''. &sort_link($q,'to','u').' to '. - &sort_link($q,'to','d'), + &sort_link($q,'to','d').'', br,$to_html ), - th({-bgcolor=>'#e0e0e0'}, + th({-bgcolor=>'#e0e0e0'},''. &sort_link($q,'dur','u').' duration '. - &sort_link($q,'dur','d') + &sort_link($q,'dur','d').'' ), th("description") ) if (scalar @sorted > 0); +my $downtime; # total downtime +my $downinterval; # total downtime in time interval +my $sg_count; # count number of downtimes + foreach my $row (@sorted) { next if ($q->param('use_date_limit') && ($row->{from} < $from_time || $row->{to} > $to_time)); my ($from,$dur,$int) = ('unknown','unknown','unknown'); + if ($row->{from} != -1 ) { $from = d($row->{from}); - $dur = dur($row->{dur}); - $int = dur($row->{int}); + $dur = $row->{to} - $row->{from}; + $downtime->{$row->{sg}} += $dur; + if ($q->param('use_time_limit')) { + $int = $working_days->interval($row->{from},$row->{to}); + $dur = dur($int)."
∑ ".dur($dur).""; + $downinterval->{$row->{sg}} += $int; + } else { + $dur = dur($dur); + } } + $sg_count->{$row->{sg}}++; + print Tr( td({-align=>'left',-valign=>'center'},$row->{sg}), td({-align=>'right',-bgcolor=>'#f0f0f0'},$from), td({-align=>'right'},d($row->{to})), td({-align=>'center',-bgcolor=>'#e0e0e0'},$dur), - td({-align=>'center',-bgcolor=>'#e0e0e0'},$int), td({-align=>'left'},$row->{desc}), ),"\n"; } @@ -304,10 +336,16 @@ # dump totals # -foreach my $sg (keys %downtime) { -print Tr(td({-colspan=>3,-align=>'right'},"total for $sg:"), - td({-bgcolor=>'#e0e0e0',-align=>'right'},dur($downtime{$sg})), - td(small("in ".$sg_count{$sg}." failures"))),"\n"; +foreach my $sg (keys %$downtime) { + my $dur; + if ($downinterval->{$sg}) { + $dur=dur($downinterval->{$sg})."
∑ ".dur($downtime->{$sg}).""; + } else { + $dur=dur($downtime->{sg}); + } + print Tr(td({-colspan=>3,-align=>'right'},"total for $sg:"), + td({-bgcolor=>'#e0e0e0',-align=>'right'},$dur), + td(small("in ".$sg_count->{$sg}." failures"))),"\n"; } print end_table,