]> git.sur5r.net Git - bacula/bacula/blob - gui/bweb/cgi/bgraph.pl
ebl add more graph type
[bacula/bacula] / gui / bweb / cgi / bgraph.pl
1 #!/usr/bin/perl -w
2 use strict;
3
4 =head1 LICENSE
5
6     Copyright (C) 2006 Eric Bollengier
7         All rights reserved.
8
9     This program is free software; you can redistribute it and/or modify
10     it under the terms of the GNU General Public License as published by
11     the Free Software Foundation; either version 2 of the License, or
12     any later version.
13
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18
19     You should have received a copy of the GNU General Public License
20     along with this program; if not, write to the Free Software
21     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
23 =head1 VERSION
24
25     $Id$
26
27 =cut
28
29 use Bweb;
30
31 use Data::Dumper;
32 use CGI;
33
34 use POSIX qw/strftime/;
35
36 my $conf = new Bweb::Config(config_file => '/etc/bweb/config');
37 $conf->load();
38
39 my $bweb = new Bweb(info => $conf);
40 $bweb->connect_db();
41 my $dbh = $bweb->{dbh};
42 my $debug = $bweb->{debug};
43
44 my $graph = CGI::param('graph') || 'job_size';
45 my $legend = CGI::param('legend') || 'on' ;
46 $legend = ($legend eq 'on')?1:0;
47
48 my $arg = $bweb->get_form(qw/width height limit offset age
49                              jfilesets level status jjobnames jclients/);
50
51 my ($limitq, $label) = $bweb->get_limit(age   => $arg->{age},
52                                         limit => $arg->{limit},
53                                         offset=> $arg->{offset},
54                                         order => 'Job.StartTime ASC',
55                                         );
56
57 my $statusq='';
58 if ($arg->{status} and $arg->{status} ne 'Any') {
59     $statusq = " AND Job.JobStatus = '$arg->{status}' ";
60 }
61     
62 my $levelq='';
63 if ($arg->{level} and $arg->{level} ne 'Any') {
64     $levelq = " AND Job.Level = '$arg->{level}' ";
65
66
67 my $filesetq='';
68 if ($arg->{jfilesets}) {
69     $filesetq = " AND FileSet.FileSet IN ($arg->{qfilesets}) ";
70
71
72 my $jobnameq='';
73 if ($arg->{jjobnames}) {
74     $jobnameq = " AND Job.Name IN ($arg->{jjobnames}) ";
75 } else {
76     $arg->{jjobnames} = 'all';  # skip warning
77
78
79 my $clientq='';
80 if ($arg->{jclients}) {
81     $clientq = " AND Client.Name IN ($arg->{jclients}) ";
82 } else {
83     $arg->{jclients} = 'all';   # skip warning
84 }
85
86 my $gtype = CGI::param('gtype') || 'bars';
87
88 print CGI::header('image/png');
89
90 sub get_graph
91 {
92     my (@options) = @_;
93     my $graph;
94     if ($gtype eq 'lines') {
95         use GD::Graph::lines;
96         $graph = GD::Graph::lines->new ( $arg->{width}, $arg->{height} );
97
98     } elsif ($gtype eq 'bars') {
99         use GD::Graph::bars;
100         $graph = GD::Graph::bars->new ( $arg->{width}, $arg->{height} );
101
102     } elsif ($gtype eq 'linespoints') {
103         use GD::Graph::linespoints;
104         $graph = GD::Graph::linespoints->new ( $arg->{width}, $arg->{height} );
105
106     } elsif ($gtype eq 'bars3d') {
107         use GD::Graph::bars3d;
108         $graph = GD::Graph::bars3d->new ( $arg->{width}, $arg->{height} );
109
110     } else {
111         return undef;
112     }
113
114     $graph->set('x_label' => 'Time',
115                 'x_number_format' => sub { strftime('%D', localtime($_[0])) },
116                 'x_tick_number' => 1,
117                 @options,
118                 );
119
120     return $graph;
121 }
122
123 sub make_tab
124 {
125     my ($all_row) = @_;
126
127     my $i=0;
128     my $last_date=0;
129
130     my $ret = {};
131     
132     foreach my $row (@$all_row) {
133         my $label = $row->[1] . "/" . $row->[2] ; # client/backup name
134
135         $ret->{date}->[$i]   = $row->[0];       
136         $ret->{$label}->[$i] = $row->[3];
137         $i++;
138         $last_date = $row->[0];
139     }
140
141     # insert a fake element
142     foreach my $elt ( keys %{$ret}) {
143         $ret->{$elt}->[$i] =  undef;
144     }
145
146     $ret->{date}->[$i] = $last_date + 1;
147
148     my $date = $ret->{date} ;
149     delete $ret->{date};
150
151     return ($date, $ret);
152 }
153
154 sub make_tab_sum
155 {
156     my ($all_row) = @_;
157
158     my $i=0;
159     my $last_date=0;
160
161     my $ret = {};
162     
163     foreach my $row (@$all_row) {
164         $ret->{date}->[$i]   = $row->[0];       
165         $ret->{nb}->[$i] = $row->[1];
166         $i++;
167     }
168
169     return ($ret);
170 }
171
172 if ($graph eq 'job_size') {
173
174     my $query = "
175 SELECT 
176        UNIX_TIMESTAMP(Job.StartTime)    AS starttime,
177        Client.Name                      AS clientname,
178        Job.Name                         AS jobname,
179        Job.JobBytes                     AS jobbytes
180 FROM Job, Client, FileSet
181 WHERE Job.ClientId = Client.ClientId
182   AND Job.FileSetId = FileSet.FileSetId
183   AND Job.Type = 'B'
184   $clientq
185   $statusq
186   $filesetq
187   $levelq
188   $jobnameq
189 $limitq
190 ";
191
192     print STDERR $query if ($debug);
193
194     my $obj = get_graph('title' => "Job Size : $arg->{jclients}/$arg->{jjobnames}",
195                         'y_label' => 'Size',
196                         'y_min_value' => 0,
197                         'y_number_format' => \&Bweb::human_size,
198                         );
199
200     my $all = $dbh->selectall_arrayref($query) ;
201
202     my ($d, $ret) = make_tab($all);
203     if ($legend) {
204         $obj->set_legend(keys %$ret);
205     }
206     print $obj->plot([$d, values %$ret])->png;
207 }
208
209 if ($graph eq 'job_file') {
210
211     my $query = "
212 SELECT 
213        UNIX_TIMESTAMP(Job.StartTime)    AS starttime,
214        Client.Name                      AS clientname,
215        Job.Name                         AS jobname,
216        Job.JobFiles                     AS jobfiles
217 FROM Job, Client, FileSet
218 WHERE Job.ClientId = Client.ClientId
219   AND Job.FileSetId = FileSet.FileSetId
220   AND Job.Type = 'B'
221   $clientq
222   $statusq
223   $filesetq
224   $levelq
225   $jobnameq
226 $limitq
227 ";
228
229     print STDERR $query if ($debug);
230
231     my $obj = get_graph('title' => "Job Files : $arg->{jclients}/$arg->{jjobnames}",
232                         'y_label' => 'Number Files',
233                         'y_min_value' => 0,
234                         );
235
236     my $all = $dbh->selectall_arrayref($query) ;
237
238     my ($d, $ret) = make_tab($all);
239     if ($legend) {
240         $obj->set_legend(keys %$ret);
241     }
242     print $obj->plot([$d, values %$ret])->png;
243 }
244
245 elsif ($graph eq 'job_rate') {
246
247     my $query = "
248 SELECT 
249        UNIX_TIMESTAMP(Job.StartTime)                          AS starttime,
250        Client.Name                      AS clientname,
251        Job.Name                         AS jobname,
252        Job.JobBytes /
253        ($bweb->{sql}->{SEC_TO_INT}(
254                           $bweb->{sql}->{UNIX_TIMESTAMP}(EndTime)  
255                         - $bweb->{sql}->{UNIX_TIMESTAMP}(StartTime)) + 0.01) 
256          AS rate
257
258 FROM Job, Client, FileSet
259 WHERE Job.ClientId = Client.ClientId
260   AND Job.FileSetId = FileSet.FileSetId
261   AND Job.Type = 'B'
262   $clientq
263   $statusq
264   $filesetq
265   $levelq
266   $jobnameq
267 $limitq
268 ";
269
270     print STDERR $query if ($debug);
271
272     my $obj = get_graph('title' => "Job Rate : $arg->{jclients}/$arg->{jjobnames}",
273                         'y_label' => 'Rate b/s',
274                         'y_min_value' => 0,
275                         'y_number_format' => \&Bweb::human_size,
276                         );
277
278     my $all = $dbh->selectall_arrayref($query) ;
279
280     my ($d, $ret) = make_tab($all);    
281     if ($legend) {
282         $obj->set_legend(keys %$ret);
283     }
284     print $obj->plot([$d, values %$ret])->png;
285 }
286
287
288
289 elsif ($graph eq 'job_duration') {
290
291     my $query = "
292 SELECT 
293        UNIX_TIMESTAMP(Job.StartTime)                           AS starttime,
294        Client.Name                                             AS clientname,
295        Job.Name                                                AS jobname,
296   $bweb->{sql}->{SEC_TO_INT}(  $bweb->{sql}->{UNIX_TIMESTAMP}(EndTime)  
297                              - $bweb->{sql}->{UNIX_TIMESTAMP}(StartTime)) 
298          AS duration
299 FROM Job, Client, FileSet
300 WHERE Job.ClientId = Client.ClientId
301   AND Job.FileSetId = FileSet.FileSetId
302   AND Job.Type = 'B'
303   $clientq
304   $statusq
305   $filesetq
306   $levelq
307   $jobnameq
308 $limitq
309 ";
310
311     print STDERR $query if ($debug);
312
313     my $obj = get_graph('title' => "Job Duration : $arg->{jclients}/$arg->{jjobnames}",
314                         'y_label' => 'Duration',
315                         'y_min_value' => 0,
316                         'y_number_format' => \&Bweb::human_sec,
317                         );
318     my $all = $dbh->selectall_arrayref($query) ;
319
320     my ($d, $ret) = make_tab($all);
321     if ($legend) {
322         $obj->set_legend(keys %$ret);
323     }
324     print $obj->plot([$d, values %$ret])->png;
325
326
327 # number of job per day/hour
328 } elsif ($graph =~ /^job_(count|sum|avg)_((p?)(day|hour|month))$/) {
329     my $t = $1;
330     my $d = uc($2);
331     my $per_t = $3;
332     my ($limit, $label) = $bweb->get_limit(age   => $arg->{age},
333                                            limit => $arg->{limit},
334                                            offset=> $arg->{offset},
335                                            groupby => "A",
336                                            );
337     my @arg;                    # arg for plotting
338
339     if (!$per_t) {              # much better aspect
340         $gtype = 'lines';
341     } else {
342         push @arg, ("x_number_format" => undef,
343                     "x_min_value" => 0,
344                     );
345     }
346
347     if ($t eq 'sum' or $t eq 'avg') {
348         push @arg, ('y_number_format' => \&Bweb::human_size);
349     }
350
351     my $query = "
352 SELECT
353      " . ($per_t?"":"UNIX_TIMESTAMP") . "(" . $bweb->{sql}->{"STARTTIME_$d"} . ") AS A,
354      $t(JobBytes)                  AS nb
355 FROM Job, Client, FileSet
356 WHERE Job.ClientId = Client.ClientId
357   AND Job.FileSetId = FileSet.FileSetId
358   AND Job.Type = 'B'
359   $clientq
360   $statusq
361   $filesetq
362   $levelq
363   $jobnameq
364 $limit
365 ";
366
367     print STDERR $query  if ($debug);
368
369     my $obj = get_graph('title' => "Job $t : $arg->{jclients}/$arg->{jjobnames}",
370                         'y_label' => $t,
371                         'y_min_value' => 0,
372                         @arg,
373                         );
374
375     my $all = $dbh->selectall_arrayref($query) ;
376     my ($ret) = make_tab_sum($all);
377
378     print $obj->plot([$ret->{date}, $ret->{nb}])->png;    
379 }
380