CGI::Application::GDGraph::lines_ap - Perl extension for CGI::Application, using GDGraph and CGI::Session
my $session_file_directory = '/<path>/<to>/<session>/<file>/directory>'; # NB: session_file_directory must be writable by user under which the web server runs # instantiate the graph application object and run it # my $graph = CGI::Application::GDGraph::lines_ap->new( TMPL_PATH => $path_to_templates, PARAMS => { 'DAT' => $dat, 'legend' => \@legend, 'x_size' => 600, 'y_size' => 300, 'x_label' => 'X LABEL HERE', 'y_label' => 'Y LABEL HERE', 'page_title' => 'GRAPH TITLE HERE', 'tmpl' => $html_template, 'session_dir'=> $session_file_directory, 'fgclr' => '#222222', 'labelclr' => '#777777', 'legendclr' => '#666666', 'textclr' => '#666666', } ); $graph->x_label_ratio("25"); $graph->run();
where :
TMPL_PATH => $path_to_templates,
is the directory location of the HTML template (see EXAMPLES)
'DAT' => $dat,
is a reference to a data structure (see EXAMPLES for an expanation of it's composition)
'legend' => \@legend,
is a reference to a list containing the name of each data series in the order that they appear in the 'DAT' structure
'x_size' => 600, 'y_size' => 300,
specifies the size of the graph to be generated along it's X and Y axis in pixels respectively
'x_label' => 'X LABEL HERE', 'y_label' => 'Y LABEL HERE',
gives the graph label names for the X and Y axis respectively
'page_title' => 'GRAPH TITLE HERE',
is the tile of the graph page and is rendered in HTML
'tmpl' => $html_template,
file name of the 'template' file to render HTML (see EXAMPLES for further details)
'session' => $session_file_dir,
where the session data is to be held - this must be WRITABLE by the user that your web server runs under (/tmp on UNIX systems would be an example of a directory like this)
'fgclr' => '#222222', 'labelclr' => '#777777', 'legendclr' => '#666666', 'textclr' => '#666666',
are the colors defined each by hex values for each of the graph's textual and line items
$graph->x_label_ratio("25");
is and optional parameter specifying the maximum amount of values to be shown in the 'X' access
This module is written with a view to its use in the area of performance and availablity management of small to large computer systems where data such as CPU, disk, swap usage are more easily interpreted when plotted as graphical images. This need not be the only application of this module as any numeric 'tabular' data may be plotted using this method.
Although it is easy to generate graphs 'on the fly' using GD and the Perl module GD::Graph, having a re-usable module that can be customised and rapidly deployed throughout a web infrastucture can cut out a lot of 'cutting and pasting'.
The combination of CGI::Application, CGI::Session and GD::Graph into this 'wrapper' module seeks to make this task easier and quicker.
An on line graph together with an HTML page in which to render it that is itself 'template driven' should be easy to set up within the framework that this module has to offer. Session state data is maintained by CGI::Session so there is little need to transfer complex 'CGI parameter based' data between the outer web application and this module. Thus data transfer is simplified and potentialy more secure.
The following examples use the following preamble which instantiates a new instance of this module.
Each example uses an HTML template file as defined in 'EXAMPLE TEMPLATE' (below)
#!/usr/bin/perl -w use strict; use CGI::Application::GDGraph::lines_ap; use GD::Graph::Data; # if we want to query a database use DBI; my $path_to_templates = '/<path>/<to>/<templates>/<dir>'; my $html_template = '<template filename>'; my $session_file_directory = '/<path>/<to>/<session>/<file>/directory>'; # NB: session_file_directory must be writable by user under which the web server runs # obtain a reference to a data structure that holds the data # to be graphed my $dat = &get_raw_data; # populate a list with names for each data set or column (this could also be the product of an SQL query) my @legend = qw(CPU Swap Load_Avg); my $graph = CGI::Application::GDGraph::lines_ap->new( TMPL_PATH => $path_to_templates, PARAMS => { 'DAT' => $dat, 'legend' => \@legend, 'x_size' => 600, 'y_size' => 300, 'x_label' => 'X LABEL HERE', 'y_label' => 'Y LABEL HERE', 'page_title' => 'GRAPH TITLE HERE', 'tmpl' => $html_template, 'session_dir'=> $session_file_directory, 'fgclr' => '#222222', 'labelclr' => '#777777', 'legendclr' => '#666666', 'textclr' => '#666666', } ); $graph->x_label_ratio("25"); $graph->run();
The line 'use GD::Graph::Data' is only used when GD::Graph::Data is used to populate the data structure for passing to the 'lines' graph object
How you arrive at a data structure that is referenced to by the '$dat' reference is the subject of the following sub headings, each of which provide a different version of the function '&get_raw_data'
# get_raw_data # accepts no parameters and returns a reference to a data structure sub get_raw_data { my $session = new CGI::Session( undef, $cgi, {Directory=>$session_file_directory} ); $session -> expire('+1h'); return $session->param('GRAPH_DATA'); } .....
and then somewhere else under another script or application
# some function or other that generates data and stores into suitable data structure # $session->param( "GRAPH_DAT", \@dat);
where the appropriate measures have been taken to start up a CGI::Session - see CGI::Session's docs for this
# get_raw_data # accepts no parameters and returns a reference to a data structure sub get_raw_data { my (%attr) = ( PrintError => 0, RaiseError => 0 ); # instantiate a new Data object with a reference called '$dat' my $dat = GD::Graph::Data->new(); # connect to our database my $dbh = DBI->connect( "DBI:mysql:<mysqldatabase_name>:<hostname_of_mysql_server>" . ";mysql_read_default_file=/etc/my.cnf", '<username>', '<password>', \%attr ) or die "Unable for connect to server"; # set up the sql query my $sql = "select datetime, cpu, swap, load_avg from my_data order by datetime desc limit 288; # prepare and run the query my @row = (); my $sth = $dbh->prepare($sql) || die "sql failed"; $sth->execute; # collect the results and save into the data structure while (@row = $sth->fetchrow_array) { $dat->add_point(@row); } return \@dat; }
The following is an example of how an SQL query could be used to insert data into a data structure for use in a graph object.
The data structure is built from scratch, not using GD::Graph::Data methods and the data is added a 'column' or 'data set' at a time. In the case of this example, this suits the nature of the data that is being queried. A table of data that contains a single column of figures together with an 'id' and 'datetime' column is queried in a for loop.
# get_raw_data # accepts no parameters and returns a reference to a data structure sub get_raw_data { my (%attr) = ( PrintError => 0, RaiseError => 0 ); my $dbh = DBI->connect( "DBI:mysql:<mysqldatabase_name>:<hostname_of_mysql_server>" . ";mysql_read_default_file=/etc/my.cnf", '<username>', '<password>', \%attr ) or die "Unable for connect to server"; # a list of 'ids' that could themselves be the product of a parameter passed to this script # or another SQL query my @ids = qw (26133 26135 26133); my $col = 0; my @dat = (); # iterate the list of 'ids' and insert a column of figures at a time into the data structure foreach my $id (@ids) { my $sql = "select datetime, stat from my_data where id = $id order by datetime desc limit 288; my @row = (); my $sth = $dbh->prepare($sql) || die "sql failed"; $sth->execute; my $row=0; $col++; while (@row = $sth->fetchrow_array) { my ($datetime, $stat) = @row; $dat[0][$row] = $datetime; $dat[$col][$row] = $stat; $row++; } } return \@dat; }
sub get_raw_data { my $CSV = '/<path>/<to>/<csv>/<data file>'; my $delim = ","; my $dat = GD::Graph::Data->new(); $dat->read(file => $CSV, delimiter => $delim); } The CSV data refered to by '$CSV' must contain a string with the path to a filename that contains comma separated data in a structure as outlined in 'SAMPLE CSV DATA' (below)
# This is a comment, and will be ignored Jan,12,24,40 Feb,13,37,34 # March is missing Mar Apr,9,18,23 May,40,20,99 Jun,50,40,23.8
<head> <title><TMPL_VAR NAME="page_title"></title> </head> <body> <table border=1> <tr> <td align="center"><H1><TMPL_VAR NAME="page_title"></H1></td> </tr> <tr> <td><img src = "/cgi-bin/<TMPL_VAR NAME="graph_img">"></td> </tr> </table> </body>
The following documents the internal methods or subroutines of the CGI::Appliciation::GDGraph::lines_ap object. For the most part it is expected for this section to be ignored by users of the module. However, if you wish to 'extend' the functionality of this module by creating a class of your own that 'inherits' from this module, this may be of more interest.
the method that 'starts up' a CGI::Application and dictates the number of 'run modes' and the 'default start mode' which is here defined as 'graph_html' - which produces the HTML in which a graph will be called using an 'img' tag. Run mode is defined by the CGI parameter 'rm' which can only be 'graph_img' or 'graph_html' in this applicaton.
changing or overriding this subroutine would alter the way the whole module behaves. It is likely that you don't want to do this and starting your own CGI::Applicatoin may be a better option
The follwoing run modes are defined:
graph_img
in this run mode, it is expected that the application will produce binary graphics data together with a corresponding mime type. Its output is to SDTOUT (straight to the browser)
graph_html
this is the DEFAULT run mode and this will output HMTL using a template file that has been provided. The template file MUST have an appropriate '<IMG=""> tag pointing back to this module - see EXAMPLES for 'TEMPLATE'
accepts the following required cgi parameters:
legend
a reference to a list of values that represent the names of each consecutive data set in the graph
x_size
an integer that is used to set the X size of the graph image
y_size
an integer that is used to set the Y size of the graph image
this method does not return any values. It is normal for CGI::Application run-time methods to return their 'output' which is sent by CGI::Application to STDOUT. 'Printing' to STDOUT within in CGI::Application method is not supported but in this case HAS been done in order that the image file may be sent straight to STDOUT by the method and not itself having to be buffered by the module.
This method therefore 'returns' an empty string post to it 'printing' to STDOUT itself.
accepts the following required CGI parameters:
$dat
a reference to the data structure (a list of lists or the data structue returned by GD::Graph::Data). This is stored into the session object which then serializes this data and writes it to disk for this session
$session_dir
the directory file location that session data is stored
graph_html returns a single scalar '$output' which is html for CGI::application to send to STDOUT for rendering by the client browser.
a call to the internal method _html is intended that this part of the html page can be extended by a.n.other module that inherits from this one without having to paste the whole graph_html method into the new one. This was an idea in development and therefore may be removed in later releases.
GD - must be installed and running on the system and available as binaries
http://www.boutell.com/gd/
Perl Modules that this is a part of or uses:
CGI::Application - this 'is a' CGI::Application
CGI::Session - to manage session data
GD::Graph::Data - to import data to GD::Graph
GD::Graph::lines_ap - the GD Perl Graphing module itself
there is no mailing list as to yet for this module (CGI::Application::GDGraph::lines_ap) but there is a wiki for CGI::Application under which this module runs as an application:
http://twiki.med.yale.edu/twiki2/bin/view/CGIapp/WebHome
http://www.jonblog.net - hosts a wiki and blog that has details of this module (CGI::Application::GDGraph::lines_ap) and other things
Jon Brookes, <jonbrookes@bigfoot.com<gt>
thanks and gratis to :
Birmingham PM, Barbie for help, patches and suggestions
likely, this is pre-beta ALPHA release and has only been tested on 2 different platforms and 3 systems.
one of he 'test scripts' is known to give errors on some systems where a checksum is returned from the PNG file that is created that differs from that of the origonal system.
any bug reports to the author please : jonbrooke@bigfoot.com
significant testing and the addition of more meaningful test scripts
improved API to support more / all current parameters as offered by GD::Graph
incorporation of other graph 'types' - for example Pie, Mixed, Bar
inclusion of both CGI and method parameter validation
Copyright 2004 by jonbrookes
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
To install CGI::Application::GDGraph::lines_ap, copy and paste the appropriate command in to your terminal.
cpanm
cpanm CGI::Application::GDGraph::lines_ap
CPAN shell
perl -MCPAN -e shell install CGI::Application::GDGraph::lines_ap
For more information on module installation, please visit the detailed CPAN module installation guide.