JPRED-2 Initial commit of software for the Jpred website (some files excluded due...
[jpred.git] / websoft / bin / jpred_stats.pl
1 #!/usr/bin/perl
2
3 =head1 NAME
4
5 jpred_stats.pl - Collate Monthly and Daily usage statistics for the Jpred server
6
7 =cut
8
9 use strict;
10 use warnings;
11 use GD::Graph::bars;
12 use Getopt::Long;
13 use Pod::Usage;
14
15 # path for nicer fonts for the graph labels
16 my $FONTPATH = "$ENV{HOME}/bin/fonts/";
17
18 my $help;
19 my $man;
20 my $outPath = '.';
21 my $file = '/grid/default/common/accounting';
22
23 GetOptions(
24         'source=s' => \$file,
25         'path=s' => \$outPath,
26    'h|?' => \$help,
27    'help' => \$help,
28    'man' => \$man,
29 ) or pod2usage(0);
30
31 pod2usage(-verbose => 1) if $help;
32 pod2usage(-verbose => 2) if $man;
33
34 pod2usage(-msg => "$outPath doesn't exist please give a valid path", -verbose => 0) if (!-e $outPath);
35
36 my @abbr = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
37
38 open (my $MONF, ">$outPath/monthly.csv") or die "ERROR - unable to open \'$outPath/monthly.csv\': $!";
39 open (my $DAYF, ">$outPath/daily.csv") or die "ERROR - unable to open \'$outPath/daily.csv\': $!";
40
41 my %stats;
42 my %dayStats;
43
44 my $currMon = extract_stats(\%stats, \%dayStats, $file);
45
46 my @monthly;
47 my $i = 0;
48 #print "Monthly summary.\n";
49 ## Sort by and then by month and output/store usage data for each month
50 foreach my $yr (sort {$a <=> $b} keys %stats) {
51         #printf "\n%d\n", $yr + 1900;
52    foreach my $mon (sort {$a <=> $b} keys %{$stats{$yr}}) {
53         #print "$abbr[$mon]: $stats{$yr}{$mon}\n";
54       my $date = sprintf "%s %02d", $abbr[$mon], $yr-100;
55       print $MONF "$date,$stats{$yr}{$mon}\n";
56       $monthly[0][$i] = $date;
57       $monthly[1][$i] = $stats{$yr}{$mon};
58       ++$i;
59    }
60 }
61 draw_graph(\@monthly, 'Month', 'Monthly Breakdown of JNet Usage');
62
63 my @daily;
64 $i = 0;
65 #print "\nDaily summary for $abbr[$currMon]\n";
66 ## Sort by date and ouput/store data for the current month.
67 foreach my $day (sort {$a <=> $b} keys %dayStats) {
68         #printf "%02d: %d\n", $day, $dayStats{$day};
69    printf $DAYF "%02d,%d\n", $day, $dayStats{$day};
70    $daily[0][$i] = $day;
71    $daily[1][$i] = $dayStats{$day};
72    ++$i;
73 }
74 die "ERROR - No data for current month ($abbr[$currMon])" if (!@daily);
75 draw_graph(\@daily, 'Date', "Daily Breakdown for $abbr[$currMon]");
76
77 $i = 0;
78 my @week;
79 foreach my $num (-7..-1) {
80         next if (!$daily[0][$num]);
81         $week[0][$i] = sprintf "%02d/%02d", $daily[0][$num], $currMon+1;
82         $week[1][$i] = $daily[1][$num];
83         ++$i;
84 }
85 draw_sm_graph(\@week);
86 exit;
87
88 sub extract_stats {
89    my ($statsRef, $dayRef, $file) = @_;
90    
91    open (my $FH, $file) or die "ERROR - can't open file \'$file\': $!";
92
93    my ($currMon, $currYr) = (localtime())[4,5];
94
95    while (<$FH>) {
96            next unless /www-jpred/;
97       my @F = split(/:/, $_);
98       die "ERROR - not enough fileds found in source file \'$file\'. Is the file correct and in the correct format?" if (9 > scalar @F);
99       #the 9th field is the date in Unix time. Extract the day, month and year from it.
100       my ($day, $mnth, $year) = (localtime($F[8]))[3..5];
101       next if ($year == 70);            # ignore jobs with invalid dates
102       next if ($F[8] < 1148338800);     # ignore jobs prior to 1 May 2006
103
104       if (($mnth == $currMon) && ($year == $currYr)) {
105            $dayRef->{$day}++;
106       }
107       $statsRef->{$year}{$mnth}++;
108    }
109    close($FH);
110    die "ERROR - no valid data found in \'$file\'" unless $statsRef;  # die if there's no data in $statsRef
111    return ($currMon);
112 }
113
114 sub draw_graph {
115    
116    my ($dataref, $x_label, $title) = @_;
117    
118    my $graph = GD::Graph::bars->new(700, 400);
119
120    $graph->set_title_font("$FONTPATH/VeraBd.ttf", 12);
121    $graph->set_x_label_font("$FONTPATH/VeraBd.ttf", 8);
122    $graph->set_y_label_font("$FONTPATH/VeraBd.ttf", 8);
123    $graph->set_x_axis_font("$FONTPATH/Vera.ttf", 6);
124    $graph->set_y_axis_font("$FONTPATH/Vera.ttf", 8);
125    $graph->set( 
126       x_label           => $x_label,
127       y_label           => 'No. JNet Submissions',
128       title             => $title,
129       shadow_depth      => -2,
130       shadowclr         => 'gray',
131       x_labels_vertical => 1,
132       borderclrs                        => undef,
133       bar_width                 => 1,
134       bar_spacing                       => 4
135    ) or die $graph->error;
136
137    my $gd = $graph->plot($dataref) or die $graph->error;
138
139    open(IMG, ">$outPath/jnet_${x_label}_stats.png") or die $!;
140    binmode IMG;
141    print IMG $gd->png;
142    close(IMG);
143
144 }
145
146 sub draw_sm_graph {
147
148    my ($dataref) = @_;
149
150    my $graph = GD::Graph::bars->new(250, 150);
151
152    $graph->set_y_label_font("$FONTPATH/VeraBd.ttf", 8);
153    $graph->set_x_axis_font("$FONTPATH/Vera.ttf", 8);
154    $graph->set_y_axis_font("$FONTPATH/Vera.ttf", 8);
155    $graph->set(
156       y_label           => 'No. Jobs',
157       x_labels_vertical => 1,
158       borderclrs                        => undef,
159       bar_width                 => 15,
160       accentclr         => 'lbrown',
161       dclrs             => [ qw(dbrown dpurple) ],
162       bar_spacing                       => 2
163    ) or die $graph->error;
164
165    my $gd = $graph->plot($dataref) or die $graph->error;
166
167    open(IMG, ">$outPath/jnet_stats.png") or die $!;
168    binmode IMG;
169    print IMG $gd->png;
170    close(IMG);
171
172 }
173
174
175 =head1 SYNOPSIS
176
177 jpred_stats.pl [--path <path>] [--source <file>]
178    
179 =head1 DESCRIPTION
180
181 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.
182
183 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.
184
185 =head1 OPTIONS
186
187 =over
188
189 =item --path <path>
190
191 Path to where you want the output saved. [default: <current directory>]
192
193 =item --source <file>
194
195 Source of Sun Grid Engine usage log file. [default: /grid/default/common/accounting]
196
197 =item --help
198
199 Display help.
200
201 =item --man
202
203 Display man page.
204
205 =back
206
207 By default the script with use the current known SGE logfile and output the data to current directory.
208
209 =head1 AUTHOR
210
211 Chris Cole <christian@cole.name>
212
213 =cut