Changeset 327

Show
Ignore:
Timestamp:
12/03/06 05:44:08 (6 years ago)
Author:
lincoln
Message:

lies. damn lies. and statistics

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • util/server_daily_maint

    r326 r327  
    1414my $store_dir = $ENV{HOME} . "/whuffy.com/dev/stats";    # where we retrieve our feedback 
    1515my $graph_dir = $ENV{HOME} . "/whuffy.com/dev/feedback"; # where we store our graphs 
    16 my $debug = 1; 
     16my $debug = 0; 
    1717 
    1818use strict; 
     
    235235sub record_duration 
    236236{ 
    237         my ($where, $dur) = @_; 
    238         $where->{duration} += $dur; 
    239         $where->{duration_max} = $dur if (!defined $where->{duration_max}); 
    240         $where->{duration_max} = $dur if ($dur > $where->{duration_max}); 
    241         $where->{duration_min} = $dur if (!defined $where->{duration_min}); 
    242         $where->{duration_min} = $dur if ($dur < $where->{duration_max}); 
     237        my ($where, $suffix, $dur) = @_; 
     238        $suffix .= "_" if ($suffix ne ""); 
     239 
     240        $where->{$suffix."duration"} += $dur; 
     241        $where->{$suffix."duration_count"} ++; 
     242        $where->{$suffix."duration_max"} = $dur if (!defined $where->{$suffix."duration_max"}); 
     243        $where->{$suffix."duration_max"} = $dur if ($dur > $where->{$suffix."duration_max"}); 
     244        $where->{$suffix."duration_min"} = $dur if (!defined $where->{$suffix."duration_min"}); 
     245        $where->{$suffix."duration_min"} = $dur if ($dur < $where->{$suffix."duration_min"}); 
    243246} 
    244247 
     
    291294                printf " - gathering statistics from $store_dir/$file ($file_modtime)\n" if ($debug); 
    292295 
     296                my $parsed = 0; 
     297                $store->{per_hour}->[0]->{visits}++;             # total # of visits seen 
     298                $store->{total}->{visits}++; 
     299 
    293300                open(F,"<$store_dir/$file") || die "could not open $store_dir/$file: $!\n"; 
    294301                while(<F>) { 
     
    297304                                # shepherd status response 
    298305                                my ($sysid, $user_starttime, $duration, $gmt_offset, $components_used) = ($1,$2,$3,$4,$5); 
     306                                $parsed = 1; 
    299307 
    300308                                # 
    301309                                # usage statistics 
    302310                                # 
    303                                 $store->{per_hour}->[0]->{visits}++;             # total # of visits seen 
    304                                 $store->{total}->{visits}++; 
    305311 
    306312                                # shepherd's duration (total count, min, max, average from duration/visits) 
    307                                 &record_duration($store->{per_hour}->[0], $duration); 
    308                                 &record_duration($store->{total}, $duration); 
     313                                &record_duration($store->{per_hour}->[0], "", $duration); 
     314                                &record_duration($store->{total}, "", $duration); 
    309315 
    310316                                # list of sysid's seen (used to derive # unique users) 
     
    332338 
    333339                                my $g = "c_".$c."_success"; 
    334                                 $store->{per_hour}->[0]->{$g}->{counter}++; 
    335                                 $store->{total}->{$g}->{counter}++; 
     340                                $store->{per_hour}->[0]->{$g."_counter"}++; 
     341                                $store->{total}->{$g."_counter"}++; 
    336342 
    337343                                # duration (total count, min, max, average from duration/counter) 
    338                                 &record_duration($store->{per_hour}->[0]->{$g}, $c_dur); 
    339                                 &record_duration($store->{total}->{$g}, $c_dur); 
     344                                &record_duration($store->{per_hour}->[0], $g, $c_dur); 
     345                                &record_duration($store->{total}, $g, $c_dur); 
    340346 
    341347                                # version count 
    342                                 $store->{per_hour}->[0]->{$g}->{version_list}->{$c_ver}++; 
     348                                $store->{per_hour}->[0]->{$g."_version_list"}->{$c_ver}++; 
    343349                        } elsif ($_ =~ /^(\S+)\tFAIL\t(\S+)\t(\S+)\t(\S+)\t(\S+)\t(\S+)/) { 
    344350                                # fail line 
     
    346352 
    347353                                my $g = "c_".$c."_fail"; 
    348                                 $store->{per_hour}->[0]->{$g}->{counter}++; 
    349                                 $store->{total}->{$g}->{counter}++; 
     354                                $store->{per_hour}->[0]->{$g."_counter"}++; 
     355                                $store->{total}->{$g."_counter"}++; 
    350356 
    351357                                # duration (total count, min, max, average from duration/counter) 
    352                                 &record_duration($store->{per_hour}->[0]->{$g}, $c_dur); 
    353                                 &record_duration($store->{total}->{$g}, $c_dur); 
     358                                &record_duration($store->{per_hour}->[0], $g, $c_dur); 
     359                                &record_duration($store->{total}, $g, $c_dur); 
    354360 
    355361                                # version count 
    356                                 $store->{per_hour}->[0]->{$g}->{version_list}->{$c_ver}++; 
     362                                $store->{per_hour}->[0]->{$g."_version_list"}->{$c_ver}++; 
    357363                        } elsif ($_ =~ /^(\S+)\tstats\t(.*)$/) { 
    358364                                # component statistics line 
     
    361367                } 
    362368                close(F); 
     369 
     370                if (!$parsed) { 
     371                        # anonymous, old version or no details 
     372                        $store->{per_hour}->[0]->{visits_with_no_details}++; 
     373                        $store->{total}->{visits_with_no_details}++; 
     374                } 
    363375 
    364376                # rename processed files so we don't re-process them 
     
    390402sub report_count_data 
    391403{ 
    392         my ($field) = @_; 
     404        my ($field, $reptype) = @_; 
     405        $reptype = "all" if (!defined $reptype); 
     406 
    393407        my $r = ""; 
    394408 
    395         $r .= sprintf "<li>in last 60 minutes: <b>%s</b> (%s previous)<br>\n", 
    396                 numvar($store->{per_hour}->[0]->{$field},$field), numvar($store->{per_hour}->[1]->{$field},$field); 
     409        $r .= sprintf "<li>in last 60 minutes: <b>%s</b> (previous %s)<br>\n", 
     410                numvar($store->{per_hour}->[0]->{$field},$field), numvar($store->{per_hour}->[1]->{$field},$field) 
     411                if ($reptype eq "all"); 
     412 
    397413        $r .= sprintf "<li>in last 24 hours: <b>%s</b> (previous %s)<br>\n", 
    398414                numvar($store->{per_day}->[0]->{$field},$field), numvar($store->{per_day}->[1]->{$field},$field); 
     415 
    399416        $r .= sprintf "<li>in last 7 days: <b>%s</b> (previous %s)<br>\n", 
    400417                numvar($store->{per_week}->[0]->{$field},$field), numvar($store->{per_week}->[1]->{$field},$field); 
     418 
    401419        $r .= sprintf "<li>in last 30 days: <b>%s</b> (previous %s)<br>\n",  
    402                 numvar($store->{per_month}->[0]->{$field},$field), numvar($store->{per_month}->[1]->{$field},$field); 
     420                numvar($store->{per_month}->[0]->{$field},$field), numvar($store->{per_month}->[1]->{$field},$field) 
     421                if ($reptype eq "all"); 
     422 
    403423        $r .= sprintf "<li><b>TOTAL SEEN: <u>%s</u></b><br>\n", numvar($store->{total}->{$field},$field); 
    404424 
     
    412432        my $sec = shift; 
    413433 
    414         return sprintf "%dh %02dm %02ds", 
     434        return sprintf "%dh %02dm %02ds (%ds)", 
    415435                int($sec / 3600), 
    416436                int(($sec % 3600) / 60), 
    417                 $sec % 60; 
     437                $sec % 60, 
     438                $sec; 
    418439} 
    419440 
     
    446467                $max = $data{$k} if (!defined $max); 
    447468                $min = $data{$k} if ($data{$k} < $min); 
    448                 $max = $data{$k} if ($data{$k} > $min); 
     469                $max = $data{$k} if ($data{$k} > $max); 
    449470        } 
    450471 
     
    457478 
    458479        print "Generating bar graph $gname ..\n" if ($debug); 
    459  
    460480        my $graph = SVG::TT::Graph::Bar->new({ 
    461481                'show_graph_title' => 1, 
     
    487507sub graph_one_count_data 
    488508{ 
    489         my ($gname, $data, $title, $time_format, $timediv) = @_; 
     509        my ($gname, $title, $time_format, $timediv, $data) = @_; 
    490510        my $gheight = 120; 
    491511        my $gwidth = 250; 
    492512 
    493513        print "Generating graph $gname ..\n" if ($debug); 
    494  
    495514        # work out scale.. 
    496         my $min, my $max, my $valnum = 0; 
    497         foreach my $val (@$data) { 
    498                 $valnum++; 
    499                 next if ($valnum % 2 == 1); 
    500  
    501                 $min = $val if (!defined $min); 
    502                 $max = $val if (!defined $max); 
    503                 $min = $val if ($val < $min); 
    504                 $max = $val if ($val > $min); 
    505         } 
    506         my $scalediv = ($max - $min) / 3; 
     515        my $min, my $max; 
     516        foreach my $dset (@$data) { 
     517                my $valnum = 0; 
     518                foreach my $val (@$dset) { 
     519                        $valnum++; 
     520                        next if ($valnum % 2 == 1); 
     521 
     522                        $min = $val if (!defined $min); 
     523                        $max = $val if (!defined $max); 
     524                        $min = $val if ($val < $min); 
     525                        $max = $val if ($val > $max); 
     526                } 
     527        } 
     528        my $scalediv = ($max-$min)/3; 
    507529        $scalediv = 1 if ($scalediv < 1); 
    508530 
     
    524546                'timescale_divisions' => $timediv, 
    525547                }); 
    526         $graph->add_data({ 
    527                 'data' => $data, 
    528                 }); 
     548 
     549        foreach my $dset (@$data) { 
     550                $graph->add_data({ 
     551                        'data' => \@$dset, 
     552                        }); 
     553        } 
    529554 
    530555        open(SVG,">$graph_dir/$gname".".svg") || die "could not create $graph_dir/$gname".".svg: $!\n"; 
     
    540565sub graph_count_data 
    541566{ 
    542         my ($field, $max_hrs, $max_days, $max_weeks, $max_months) = @_; 
     567        my ($max_hrs, $max_days, $max_weeks, $max_months, @fields) = @_; 
    543568        my $r = ""; 
    544569 
    545570        # hours 
    546         my @d1; 
    547         for (my $i = ($max_hrs-1); $i >= 0; $i--) { 
    548                 my $val = numvar($store->{per_hour}->[$i]->{$field},$field,0); 
    549                 my $time_offset = $starttime + $store->{tzdiff} - (60*60*$i); 
    550                 push(@d1, strftime("%Y-%m-%d %H:%M:%S", localtime($time_offset)), $val); 
     571        if ($max_hrs > 0) { 
     572                my $fieldnum = 0, my $d, my $fielddesc = ""; 
     573                foreach my $field (@fields) { 
     574                        for (my $i = ($max_hrs-1); $i >= 0; $i--) { 
     575                                my $val = numvar($store->{per_hour}->[$i]->{$field},$field,0); 
     576                                $val /= numvar($store->{per_hour}->[$i]->{duration_count},$field,1) if ($field =~ /duration$/); 
     577                                my $time_offset = $starttime + $store->{tzdiff} - (60*60*$i); 
     578                                push(@{$d->[$fieldnum]}, strftime("%Y-%m-%d %H:%M:%S", localtime($time_offset)), $val); 
     579                        } 
     580                        $fieldnum++; 
     581                        $fielddesc .= $field."_"; 
     582                } 
     583                $r .= &graph_one_count_data($fielddesc."hr", "Last $max_hrs hours", "%a %H:%M", "6 hours", $d); 
    551584        } 
    552585 
    553586        # days 
    554         my @d2; 
    555         for (my $i = ($max_days-1); $i >= 0; $i--) { 
    556                 my $val = numvar($store->{per_day}->[$i]->{$field},$field,0); 
    557                 my $time_offset = $starttime + $store->{tzdiff} - (60*60*24*$i); 
    558                 push(@d2, strftime("%Y-%m-%d %H:%M:%S", localtime($time_offset)), $val); 
     587        if ($max_days > 0) { 
     588                my $fieldnum = 0, my $d, my $fielddesc = ""; 
     589                foreach my $field (@fields) { 
     590                        for (my $i = ($max_days-1); $i >= 0; $i--) { 
     591                                my $val = numvar($store->{per_day}->[$i]->{$field},$field,0); 
     592                                $val /= numvar($store->{per_hour}->[$i]->{duration_count},$field,1) if ($field =~ /^duration$/); 
     593                                my $time_offset = $starttime + $store->{tzdiff} - (60*60*24*$i); 
     594                                push(@{$d->[$fieldnum]}, strftime("%Y-%m-%d %H:%M:%S", localtime($time_offset)), $val); 
     595                        } 
     596                        $fieldnum++; 
     597                        $fielddesc .= $field."_"; 
     598                } 
     599                $r .= &graph_one_count_data($fielddesc."day", "Last $max_days days", "%a %e %b", "5 days", $d); 
    559600        } 
    560601 
    561602        # weeks 
    562         my @d3; 
    563         for (my $i = ($max_weeks-1); $i >= 0; $i--) { 
    564                 my $val = numvar($store->{per_week}->[$i]->{$field},$field,0); 
    565                 my $time_offset = $starttime + $store->{tzdiff} - (60*60*24*7*$i); 
    566                 push(@d3, strftime("%Y-%m-%d %H:%M:%S", localtime($time_offset)), $val); 
     603        if ($max_weeks > 0) { 
     604                my $fieldnum = 0, my $d, my $fielddesc = ""; 
     605                foreach my $field (@fields) { 
     606                        for (my $i = ($max_weeks-1); $i >= 0; $i--) { 
     607                                my $val = numvar($store->{per_week}->[$i]->{$field},$field,0); 
     608                                $val /= numvar($store->{per_hour}->[$i]->{duration_count},$field,1) if ($field =~ /^duration$/); 
     609                                my $time_offset = $starttime + $store->{tzdiff} - (60*60*24*7*$i); 
     610                                push(@{$d->[$fieldnum]}, strftime("%Y-%m-%d %H:%M:%S", localtime($time_offset)), $val); 
     611                        } 
     612                        $fieldnum++; 
     613                        $fielddesc .= $field."_"; 
     614                } 
     615                $r .= &graph_one_count_data($fielddesc."wk", "Last $max_weeks weeks", "%e %b %y", "3 weeks", $d); 
    567616        } 
    568617 
    569618        # months 
    570         my @d4; 
    571         for (my $i = ($max_months-1); $i >= 0; $i--) { 
    572                 my $val = numvar($store->{per_week}->[$i]->{$field},$field,0); 
    573                 my $time_offset = $starttime + $store->{tzdiff} - (60*60*24*30*$i); 
    574                 push(@d4, strftime("%Y-%m-%d %H:%M:%S", localtime($time_offset)), $val); 
    575         } 
    576  
    577         $r .= &graph_one_count_data($field."_hr", \@d1, "Last $max_hrs hours", "%a %H:%M", "6 hours") if (defined $max_hrs); 
    578         $r .= &graph_one_count_data($field."_day", \@d2, "Last $max_days days", "%a %e %b", "5 days") if (defined $max_days); 
    579         $r .= &graph_one_count_data($field."_wk", \@d3, "Last $max_weeks weeks", "%e %b %y", "3 weeks") if (defined $max_weeks); 
    580         $r .= &graph_one_count_data($field."_mn", \@d4, "Last $max_months months", "%b %y", "4 months") if (defined $max_months); 
     619        if ($max_months > 0) { 
     620                my $fieldnum = 0, my $d, my $fielddesc = ""; 
     621                foreach my $field (@fields) { 
     622                        for (my $i = ($max_months-1); $i >= 0; $i--) { 
     623                                my $val = numvar($store->{per_week}->[$i]->{$field},$field,0); 
     624                                $val /= numvar($store->{per_hour}->[$i]->{duration_count},$field,1) if ($field =~ /^duration$/); 
     625                                my $time_offset = $starttime + $store->{tzdiff} - (60*60*24*30*$i); 
     626                                push(@{$d->[$fieldnum]}, strftime("%Y-%m-%d %H:%M:%S", localtime($time_offset)), $val); 
     627                        } 
     628                        $fieldnum++; 
     629                        $fielddesc .= $field."_"; 
     630                } 
     631                $r .= &graph_one_count_data($fielddesc."mn", "Last $max_months months", "%b %y", "4 months", $d); 
     632        } 
     633 
    581634        return $r; 
    582635} 
     
    586639sub generate_reports 
    587640{ 
    588         open(F,">$graph_dir/main.html") || die "couldn't open $graph_dir for writing: $!\n"; 
    589  
    590         my $now = localtime($starttime); 
    591  
    592         print F <<EOF 
     641        my $hdr = " 
    593642<html> 
    594643<head> 
     
    603652body.home h2 { font: normal 24px/.8em Slyphaen, Times, serif; color: #DFB020; padding: 0; clear: both; margin: 20 0 10 0; } 
    604653body.home p { clear: both; } 
     654table { border-top: 1px dotted; padding: 3px; cellpadding: 3px; } 
     655td { border-bottom: 1px dotted; } 
    605656input { font: bold 12px Arial; } 
    606657</style> 
    607658</head> 
    608  
    609 <body class="home"> 
    610 <h1>Shepherd Overall statistics <font size=-1>(as of $now)</font></h1> 
    611 <table style='border: 1px dotted; border-collapse: separate; border-spacing: 1px dotted; padding: 3px; cellpadding: 3px;' align=left> 
    612 <tr> 
    613 EOF 
    614 ; 
    615         print F "<tr'><td align=left valign=top nowrap><h2>Shepherd usage</h2>\n"; 
    616         print F "Number of times shepherd reported in.<br>\n"; 
    617         print F report_count_data("visits"); 
    618         print F "</td><td nowrap colspan=4><br>"; 
    619         print F graph_count_data("visits",24,21,12,24); 
     659<body class='home'>"; 
     660 
     661        my $now = localtime($starttime); 
     662        open(F,">$graph_dir/index.html") || die "couldn't open $graph_dir/index.html for writing: $!\n"; 
     663        print F "$hdr<h1>Shepherd Overall statistics <font size=-1>(as of $now)</font></h1>\n"; 
     664        print F "<table align=left>\n"; 
     665        print F "<tr><td align=left valign=top nowrap><h2>Shepherd usage</h2>\n"; 
     666        print F "<b>Number of times shepherd reported in:</b> <font color=pink><i>(red)</i></font><br>\n"; 
     667        print F report_count_data("visits", "all"); 
     668        print F "<br><b>Reported in with no data:</b> <font color=lightblue><i>(blue)</i></font>\n"; 
     669        print F report_count_data("visits_with_no_details", "brief"); 
     670        print F "</td><td nowrap><br>"; 
     671        print F graph_count_data(24,21,12,24, "visits", "visits_with_no_details"); 
    620672        print F "</td></tr>\n"; 
    621673 
    622674        print F "<tr><td align=left valign=top nowrap><h2>Unique users</h2>\n"; 
    623         print F "Number of unique systems seen.<br>\n"; 
     675        print F "<b>Number of unique systems seen:</b> <font color=pink><i>(red)</i></font><br>\n"; 
    624676        print F report_count_data("seen_sysid_list"); 
    625         print F "</td><td nowrap colspan=4><br>"; 
    626         print F graph_count_data("seen_sysid_list",24,21,12,24); 
     677        print F "</td><td nowrap><br>"; 
     678        print F graph_count_data(24,21,12,24,"seen_sysid_list"); 
    627679        print F "</td></tr>\n"; 
    628680 
    629681        print F "<tr><td align=left valign=top nowrap><h2>Start time</h2>\n"; 
    630         print F "When shepherd checked in.<br>\n"; 
     682        print F "<b>When shepherd checked in:</b> <font color=pink><i>(red)</i></font><br>\n"; 
     683        print F "<i>(when shepherd is being run)</i><p>"; 
    631684        print F "(in 15 minute groups, time in GMT+10)"; 
    632         print F "</td><td nowrap colspan=2><br>"; 
     685        print F "</td><td nowrap><br>"; 
    633686        print F graph_hash_data("when_run_list", "per_day", 0, 7, "Last 7 days", 120, 500); 
    634         print F "</td><td nowrap colspan=2><br>"; 
    635687        print F graph_hash_data("when_run_list", "per_month", 0, 1, "Last 30 days", 120, 500); 
    636688        print F "</td></tr>\n"; 
    637689 
    638690        print F "<tr><td align=left valign=top nowrap><h2>Duration</h2>\n"; 
    639         print F "How long shepherd took to run.<br>\n"; 
    640         print F "</td><td nowrap align=left valign=top><br>"; 
    641         printf F "<li>in last 60 minutes:</b><ul><li>%s average (mean)<li>%s min<li>%s max</ul>\n", 
    642                 sec2hms(numvar($store->{per_hour}->[0]->{duration},"",0) / $store->{per_hour}->[0]->{visits}), 
    643                 sec2hms(numvar($store->{per_hour}->[0]->{duration_min},"",0)), 
    644                 sec2hms(numvar($store->{per_hour}->[0]->{duration_max},"",0)) 
    645                 if ((defined $store->{per_hour}->[0]->{visits}) && ($store->{per_hour}->[0]->{visits} > 0)); 
    646         print F "</td><td nowrap align=left valign=top><br>"; 
    647         printf F "<li>in last 7 days:</b><ul><li>%s average (mean)<li>%s min<li>%s max</ul>\n", 
    648                 sec2hms(numvar($store->{per_day}->[0]->{duration},"",0) / $store->{per_day}->[0]->{visits}), 
     691        print F "<b>How long shepherd took to run:</b><br>\n"; 
     692        printf F "<li><b>in last 24 hours:</b><br>". 
     693                "&nbsp;&nbsp;&nbsp;%s average <i><font color=pink>(red)</font></i><br>". 
     694                "&nbsp;&nbsp;&nbsp;%s min <i><font color=lightblue>(blue)</font></i><br>". 
     695                "&nbsp;&nbsp;&nbsp;%s max <i><font color=lightgreen>(green)</font></i><br>\n", 
     696                sec2hms(numvar($store->{per_day}->[0]->{duration},"",0) / $store->{per_hour}->[0]->{duration_count}), 
    649697                sec2hms(numvar($store->{per_day}->[0]->{duration_min},"",0)), 
    650698                sec2hms(numvar($store->{per_day}->[0]->{duration_max},"",0)) 
    651                 if ((defined $store->{per_day}->[0]->{visits}) && ($store->{per_day}->[0]->{visits} > 0)); 
    652         print F "</td><td nowrap align=left valign=top><br>"; 
    653         printf F "<li>in last 30 days:</b><ul><li>%s average (mean)<li>%s min<li>%s max</ul>\n", 
    654                 sec2hms(numvar($store->{per_month}->[0]->{duration},"",0) / $store->{per_month}->[0]->{visits}), 
     699                if ((defined $store->{per_hour}->[0]->{duration_count}) && ($store->{per_hour}->[0]->{duration_count} > 0)); 
     700        printf F "<li><b>in last month:</b><br>". 
     701                "&nbsp;&nbsp;&nbsp;%s average <i><font color=pink>(red)</font></i><br>". 
     702                "&nbsp;&nbsp;&nbsp;%s min <i><font color=lightblue>(blue)</font></i><br>". 
     703                "&nbsp;&nbsp;&nbsp;%s max <i><font color=lightgreen>(green)</font></i><br>\n", 
     704                sec2hms(numvar($store->{per_month}->[0]->{duration},"",0) / $store->{per_month}->[0]->{duration_count}), 
    655705                sec2hms(numvar($store->{per_month}->[0]->{duration_min},"",0)), 
    656706                sec2hms(numvar($store->{per_month}->[0]->{duration_max},"",0)) 
    657                 if ((defined $store->{per_month}->[0]->{visits}) && ($store->{per_month}->[0]->{visits} > 0)); 
    658         print F "</td><td nowrap align=left valign=top><br>"; 
    659         printf F "<li>OVERALL:</b><ul><li>%s average (mean)<li>%s min<li>%s max</ul>\n", 
    660                 sec2hms(numvar($store->{total}->{duration},"",0) / $store->{total}->{visits}), 
    661                 sec2hms(numvar($store->{total}->{duration_min},"",0)), 
    662                 sec2hms(numvar($store->{total}->{duration_max},"",0)) 
    663                 if ((defined $store->{total}->{visits}) && ($store->{total}->{visits} > 0)); 
     707                if ((defined $store->{per_month}->[0]->{duration_count}) && ($store->{per_month}->[0]->{duration_count} > 0)); 
     708        print F "</td><td nowrap align=left>"; 
     709        print F graph_count_data(24,21,12,24,"duration", "duration_min", "duration_max"); 
    664710        print F "</td></tr>\n"; 
    665711 
    666712        print F "<tr><td align=left valign=top nowrap><h2>Timezones</h2>\n"; 
    667         print F "Timezone setting on hosts.<br>\n"; 
    668         print F "</td><td nowrap colspan=4><br>"; 
     713        print F "<b>Where shepherd is being run:</b> <font color=pink><i>(red)</i></font><br>\n"; 
     714        print F "<i>(timezone setting of hosts)</i><p>"; 
     715        print F "</td><td nowrap><br>"; 
    669716        print F graph_hash_data("gmt_offset_list", "per_day", 0, 7, "Last 7 days", 120, 500); 
    670717        print F graph_hash_data("gmt_offset_list", "per_month", 0, 1, "Last 30 days", 120, 500); 
    671718        print F "</td></tr>\n"; 
    672719 
    673  
    674 # SHEPHERD 
    675 # what components were used (and in what order?) 
    676 # $store->{per_hour}->[0]->{components_used_order_list}->{$components_used}++; 
    677  
    678  
    679 # PER-COMPONENT 
    680 # my $g = "c_".$c."_success"; 
    681 # my $g = "c_".$c."_fail"; 
    682 # $store->{per_hour}->[0]->{$g}->{counter}++; 
    683 # $store->{total}->{$g}->{counter}++; 
    684  
    685 # duration (total count, min, max, average from duration/counter) 
    686 # &record_duration($store->{per_hour}->[0]->{$g}, $c_dur); 
    687 # &record_duration($store->{total}->{$g}, $c_dur); 
    688  
    689 # # version count 
    690 # $store->{per_hour}->[0]->{$g}->{version_list}->{$c_ver}++; 
    691  
    692         print F "</table><br clear=all>\n"; 
    693  
    694         print F "</body></html>\n"; 
    695  
    696 } 
    697  
    698 ############################################################################### 
    699  
    700  
     720        print F "<tr><td align=left valign=top nowrap colspan=2><h2>Components Used</h2>\n"; 
     721        #print F "<b>Components (and versions) being used</b><br>\n"; 
     722        printf F "<li><b>in last 24 hours:</b><br>"; 
     723        foreach my $c ( 
     724                sort { $store->{per_day}->[0]->{components_used_order_list}->{$b} <=> $store->{per_day}->[0]->{components_used_order_list}->{$a} } 
     725                keys %{($store->{per_day}->[0]->{components_used_order_list})}) { 
     726                my $val = $store->{per_day}->[0]->{components_used_order_list}->{$c}; 
     727                printf F "&nbsp;&nbsp;&nbsp;<b>%d time%s</b>: %s<br>\n", $val, ($val != 1 ? "s" : ""), $c; 
     728        } 
     729        printf F "<li><b>in last month:</b><br>"; 
     730        foreach my $c ( 
     731                sort { $store->{per_month}->[0]->{components_used_order_list}->{$b} <=> $store->{per_month}->[0]->{components_used_order_list}->{$a} } 
     732                keys %{($store->{per_month}->[0]->{components_used_order_list})}) { 
     733                my $val = $store->{per_month}->[0]->{components_used_order_list}->{$c}; 
     734                printf F "&nbsp;&nbsp;&nbsp;<b>%d time%s</b>: %s<br>\n", $val, ($val != 1 ? "s" : ""), $c; 
     735        } 
     736 
     737        # build a component list 
     738        my %clist; 
     739        foreach my $c (sort keys %{($store->{total})}) { 
     740                if (($c =~ /^c_(.*)_success_counter$/) || 
     741                    ($c =~ /^c_(.*)_fail_counter$/)) { 
     742                        # skip if any '/' chars in name 
     743                        next if ($1 =~ /\//); 
     744                        $clist{$1}++; 
     745                } 
     746        } 
     747 
     748        print F "<tr><td align=left valign=top nowrap colspan=2><h2>Detailed Component Statistics</h2>\n"; 
     749        print F "<p><table align=center>"; 
     750        my $ccount = 0; 
     751        foreach my $c (sort keys %clist) { 
     752                print F "</tr><tr>\n" if (($ccount % 4 == 0) && ($ccount > 0)); 
     753                print F "<td>\n"; 
     754                printf F "<b><a href='%s.html'>%s</a></b><br>\n", $c, $c; 
     755                print F "<b>Successful runs:</b><br>\n" . report_count_data("c_".$c."_success_counter", "brief"); 
     756                print F "<b>Failed runs:</b><br>\n" . report_count_data("c_".$c."_fail_counter", "brief"); 
     757                print F "</td>\n"; 
     758                $ccount++; 
     759        } 
     760        print F "</tr></table></td></tr></table><br clear=all></body></html>\n"; 
     761        close(F); 
     762 
     763        # 
     764        # iterate through every component we have seen, sorted alphabetically 
     765        # generate per-component statistics 
     766        # 
     767 
     768        foreach my $c (sort keys %clist) { 
     769                open(F,">$graph_dir/$c.html") || die "couldn't open $graph_dir/$c for writing: $!\n"; 
     770                print F "$hdr<h1>Component statistics: $c</h1>\n"; 
     771                print F "<table align=left>\n"; 
     772 
     773                print F "<tr><td align=left valign=top nowrap><h2>Success/Failure</h2>\n"; 
     774                print F "<i>(# of times called and return status)</i><br>\n"; 
     775                print F "<b>Successful runs:</b> <font color=pink><i>(red)</i></font><br>\n"; 
     776                print F report_count_data("c_".$c."_success_counter", "all"); 
     777                print F "<br><b>Failed runs:</b> <font color=lightblue><i>(blue)</i></font>\n"; 
     778                print F report_count_data("c_".$c."_fail_counter", "brief"); 
     779                print F "</td><td nowrap><br>"; 
     780                print F graph_count_data(24,21,12,24, "c_".$c."_success_counter", "c_".$c."_fail_counter"); 
     781                print F "</td></tr>\n"; 
     782 
     783                foreach my $w ("success", "fail") { 
     784                        my $g = "c_".$c."_".$w; 
     785 
     786                        print F "<tr><td align=left valign=top nowrap colspan=2><h2>Versions ($w)</h2>\n"; 
     787                        printf F "<li><b>in last 24 hours:</b><br>"; 
     788                        foreach my $c ( 
     789                                sort { $store->{per_day}->[0]->{$g."_version_list"}->{$b} <=> $store->{per_day}->[0]->{$g."_version_list"}->{$a} } 
     790                                keys %{($store->{per_day}->[0]->{$g."_version_list"})}) { 
     791                                my $val = $store->{per_day}->[0]->{$g."_version_list"}->{$c}; 
     792                                printf F "&nbsp;&nbsp;&nbsp;<b>%d time%s</b>: %s<br>\n", $val, ($val != 1 ? "s" : ""), $c; 
     793                        } 
     794                        printf F "<li><b>in last month:</b><br>"; 
     795                        foreach my $c ( 
     796                                sort { $store->{per_month}->[0]->{$g."_version_list"}->{$b} <=> $store->{per_month}->[0]->{$g."_version_list"}->{$a} } 
     797                                keys %{($store->{per_month}->[0]->{$g."_version_list"})}) { 
     798                                my $val = $store->{per_month}->[0]->{$g."_version_list"}->{$c}; 
     799                                printf F "&nbsp;&nbsp;&nbsp;<b>%d time%s</b>: %s<br>\n", $val, ($val != 1 ? "s" : ""), $c; 
     800                        } 
     801 
     802                        print F "<tr><td align=left valign=top nowrap><h2>Duration ($w)</h2>\n"; 
     803                        print F "<b>How long $c took to run ($w):</b><br>\n"; 
     804                        printf F "<li><b>in last 24 hours:</b><br>". 
     805                                "&nbsp;&nbsp;&nbsp;%s average <i><font color=pink>(red)</font></i><br>". 
     806                                "&nbsp;&nbsp;&nbsp;%s min <i><font color=lightblue>(blue)</font></i><br>". 
     807                                "&nbsp;&nbsp;&nbsp;%s max <i><font color=lightgreen>(green)</font></i><br>\n", 
     808                                sec2hms(numvar($store->{per_day}->[0]->{$g."_duration"},"",0) / $store->{per_hour}->[0]->{$g."_duration_count"}), 
     809                                sec2hms(numvar($store->{per_day}->[0]->{$g."_duration_min"},"",0)), 
     810                                sec2hms(numvar($store->{per_day}->[0]->{$g."_duration_max"},"",0)) 
     811                                if ((defined $store->{per_hour}->[0]->{$g."_duration_count"}) && ($store->{per_hour}->[0]->{$g."_duration_count"} > 0)); 
     812                        printf F "<li><b>in last month:</b><br>". 
     813                                "&nbsp;&nbsp;&nbsp;%s average <i><font color=pink>(red)</font></i><br>". 
     814                                "&nbsp;&nbsp;&nbsp;%s min <i><font color=lightblue>(blue)</font></i><br>". 
     815                                "&nbsp;&nbsp;&nbsp;%s max <i><font color=lightgreen>(green)</font></i><br>\n", 
     816                                sec2hms(numvar($store->{per_month}->[0]->{$g."_duration"},"",0) / $store->{per_month}->[0]->{$g."_duration_count"}), 
     817                                sec2hms(numvar($store->{per_month}->[0]->{$g."_duration_min"},"",0)), 
     818                                sec2hms(numvar($store->{per_month}->[0]->{$g."_duration_max"},"",0)) 
     819                                if ((defined $store->{per_month}->[0]->{$g."_duration_count"}) && ($store->{per_month}->[0]->{$g."_duration_count"} > 0)); 
     820                        print F "</td><td nowrap align=left>&nbsp;<br>"; 
     821                        print F graph_count_data(24,21,12,24,$g."_duration", $g."_duration_min", $g."_duration_max"); 
     822                        print F "</td></tr>\n"; 
     823                } 
     824 
     825                print F "</table><br clear=all></body></html>\n"; 
     826                close(F); 
     827        } 
     828} 
     829 
     830############################################################################### 
     831 
     832