JPRED-2 Initial commit of software for the Jpred website (some files excluded due...
[jpred.git] / websoft / bin / jpred_stats.pl
diff --git a/websoft/bin/jpred_stats.pl b/websoft/bin/jpred_stats.pl
new file mode 100755 (executable)
index 0000000..724930c
--- /dev/null
@@ -0,0 +1,213 @@
+#!/usr/bin/perl
+
+=head1 NAME
+
+jpred_stats.pl - Collate Monthly and Daily usage statistics for the Jpred server
+
+=cut
+
+use strict;
+use warnings;
+use GD::Graph::bars;
+use Getopt::Long;
+use Pod::Usage;
+
+# path for nicer fonts for the graph labels
+my $FONTPATH = "$ENV{HOME}/bin/fonts/";
+
+my $help;
+my $man;
+my $outPath = '.';
+my $file = '/grid/default/common/accounting';
+
+GetOptions(
+       'source=s' => \$file,
+       'path=s' => \$outPath,
+   'h|?' => \$help,
+   'help' => \$help,
+   'man' => \$man,
+) or pod2usage(0);
+
+pod2usage(-verbose => 1) if $help;
+pod2usage(-verbose => 2) if $man;
+
+pod2usage(-msg => "$outPath doesn't exist please give a valid path", -verbose => 0) if (!-e $outPath);
+
+my @abbr = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
+
+open (my $MONF, ">$outPath/monthly.csv") or die "ERROR - unable to open \'$outPath/monthly.csv\': $!";
+open (my $DAYF, ">$outPath/daily.csv") or die "ERROR - unable to open \'$outPath/daily.csv\': $!";
+
+my %stats;
+my %dayStats;
+
+my $currMon = extract_stats(\%stats, \%dayStats, $file);
+
+my @monthly;
+my $i = 0;
+#print "Monthly summary.\n";
+## Sort by and then by month and output/store usage data for each month
+foreach my $yr (sort {$a <=> $b} keys %stats) {
+       #printf "\n%d\n", $yr + 1900;
+   foreach my $mon (sort {$a <=> $b} keys %{$stats{$yr}}) {
+       #print "$abbr[$mon]: $stats{$yr}{$mon}\n";
+      my $date = sprintf "%s %02d", $abbr[$mon], $yr-100;
+      print $MONF "$date,$stats{$yr}{$mon}\n";
+      $monthly[0][$i] = $date;
+      $monthly[1][$i] = $stats{$yr}{$mon};
+      ++$i;
+   }
+}
+draw_graph(\@monthly, 'Month', 'Monthly Breakdown of JNet Usage');
+
+my @daily;
+$i = 0;
+#print "\nDaily summary for $abbr[$currMon]\n";
+## Sort by date and ouput/store data for the current month.
+foreach my $day (sort {$a <=> $b} keys %dayStats) {
+       #printf "%02d: %d\n", $day, $dayStats{$day};
+   printf $DAYF "%02d,%d\n", $day, $dayStats{$day};
+   $daily[0][$i] = $day;
+   $daily[1][$i] = $dayStats{$day};
+   ++$i;
+}
+die "ERROR - No data for current month ($abbr[$currMon])" if (!@daily);
+draw_graph(\@daily, 'Date', "Daily Breakdown for $abbr[$currMon]");
+
+$i = 0;
+my @week;
+foreach my $num (-7..-1) {
+       next if (!$daily[0][$num]);
+       $week[0][$i] = sprintf "%02d/%02d", $daily[0][$num], $currMon+1;
+       $week[1][$i] = $daily[1][$num];
+       ++$i;
+}
+draw_sm_graph(\@week);
+exit;
+
+sub extract_stats {
+   my ($statsRef, $dayRef, $file) = @_;
+   
+   open (my $FH, $file) or die "ERROR - can't open file \'$file\': $!";
+
+   my ($currMon, $currYr) = (localtime())[4,5];
+
+   while (<$FH>) {
+          next unless /www-jpred/;
+      my @F = split(/:/, $_);
+      die "ERROR - not enough fileds found in source file \'$file\'. Is the file correct and in the correct format?" if (9 > scalar @F);
+      #the 9th field is the date in Unix time. Extract the day, month and year from it.
+      my ($day, $mnth, $year) = (localtime($F[8]))[3..5];
+      next if ($year == 70);           # ignore jobs with invalid dates
+      next if ($F[8] < 1148338800);     # ignore jobs prior to 1 May 2006
+
+      if (($mnth == $currMon) && ($year == $currYr)) {
+          $dayRef->{$day}++;
+      }
+      $statsRef->{$year}{$mnth}++;
+   }
+   close($FH);
+   die "ERROR - no valid data found in \'$file\'" unless $statsRef;  # die if there's no data in $statsRef
+   return ($currMon);
+}
+
+sub draw_graph {
+   
+   my ($dataref, $x_label, $title) = @_;
+   
+   my $graph = GD::Graph::bars->new(700, 400);
+
+   $graph->set_title_font("$FONTPATH/VeraBd.ttf", 12);
+   $graph->set_x_label_font("$FONTPATH/VeraBd.ttf", 8);
+   $graph->set_y_label_font("$FONTPATH/VeraBd.ttf", 8);
+   $graph->set_x_axis_font("$FONTPATH/Vera.ttf", 6);
+   $graph->set_y_axis_font("$FONTPATH/Vera.ttf", 8);
+   $graph->set( 
+      x_label           => $x_label,
+      y_label           => 'No. JNet Submissions',
+      title             => $title,
+      shadow_depth      => -2,
+      shadowclr         => 'gray',
+      x_labels_vertical        => 1,
+      borderclrs                       => undef,
+      bar_width                        => 1,
+      bar_spacing                      => 4
+   ) or die $graph->error;
+
+   my $gd = $graph->plot($dataref) or die $graph->error;
+
+   open(IMG, ">$outPath/jnet_${x_label}_stats.png") or die $!;
+   binmode IMG;
+   print IMG $gd->png;
+   close(IMG);
+
+}
+
+sub draw_sm_graph {
+
+   my ($dataref) = @_;
+
+   my $graph = GD::Graph::bars->new(250, 150);
+
+   $graph->set_y_label_font("$FONTPATH/VeraBd.ttf", 8);
+   $graph->set_x_axis_font("$FONTPATH/Vera.ttf", 8);
+   $graph->set_y_axis_font("$FONTPATH/Vera.ttf", 8);
+   $graph->set(
+      y_label           => 'No. Jobs',
+      x_labels_vertical => 1,
+      borderclrs                        => undef,
+      bar_width                 => 15,
+      accentclr                => 'lbrown',
+      dclrs            => [ qw(dbrown dpurple) ],
+      bar_spacing                       => 2
+   ) or die $graph->error;
+
+   my $gd = $graph->plot($dataref) or die $graph->error;
+
+   open(IMG, ">$outPath/jnet_stats.png") or die $!;
+   binmode IMG;
+   print IMG $gd->png;
+   close(IMG);
+
+}
+
+
+=head1 SYNOPSIS
+
+jpred_stats.pl [--path <path>] [--source <file>]
+   
+=head1 DESCRIPTION
+
+Script to collate the usage statistics for the Jpred server. The stats are subdivided by month and then my day for he current month only.
+
+The outputs are two graph images <jnet_Month_stats.png> and <jnet_Date_stats.png> and two comma separated files (<monthly.csv> and <daily.csv>) containing the raw data.
+
+=head1 OPTIONS
+
+=over
+
+=item --path <path>
+
+Path to where you want the output saved. [default: <current directory>]
+
+=item --source <file>
+
+Source of Sun Grid Engine usage log file. [default: /grid/default/common/accounting]
+
+=item --help
+
+Display help.
+
+=item --man
+
+Display man page.
+
+=back
+
+By default the script with use the current known SGE logfile and output the data to current directory.
+
+=head1 AUTHOR
+
+Chris Cole <christian@cole.name>
+
+=cut