package Catalyst::View::RRDGraph; use strict; use warnings; use base 'Catalyst::View'; our $VERSION = '0.03'; use RRDs; use File::Temp qw(); sub new { my ($class, $c, $arguments) = @_; my $config = { 'IMG_DIR' => '/tmp/', 'IMG_FORMAT' => 'PNG', 'ON_ERROR_SERVE' => undef, %{ $class->config }, (defined($arguments)?%{$arguments}:()), }; my $self = $class->NEXT::new( $c, { %$config }, ); $self->config($config); return ($self); } sub process { my ($self, $c) = @_; my $props = $c->stash->{'graph'}; die "No graph in the stash" if (not defined $props); die "graph must be an ARRAYREF" if (ref($props) ne 'ARRAY'); my $tempfile = File::Temp->new( TEMPLATE => 'cat_view_rrd_XXXXXX', DIR => $self->config->{'IMG_DIR'}, SUFFIX => '.' . lc($self->config->{'IMG_FORMAT'})); RRDs::graph($tempfile->filename, '--imgformat', $self->config->{'IMG_FORMAT'}, @$props); if (RRDs::error) { $self->_handle_error($c, RRDs::error); return; } if (-s $tempfile->filename == 0) { $self->_handle_error($c, "RRDgraph is 0 bytes"); return; } $c->serve_static_file($tempfile->filename); } sub _handle_error { my ($self, $c, $error) = @_; if (not defined $self->config->{'ON_ERROR_SERVE'}){ Catalyst::Exception->throw($error); } elsif (ref($self->config->{'ON_ERROR_SERVE'}) eq 'CODE') { #Call the custom handler $self->config->{'ON_ERROR_SERVE'}($self, $c, $error); } else { $c->log->error($error); $c->serve_static_file($self->config->{'ON_ERROR_SERVE'}); } } #################### main pod documentation begin ################### ## Below is the stub of documentation for your module. ## You better edit it! =head1 NAME Catalyst::View::RRDGraph - RRD Graph View Class =head1 SYNOPSIS use the helper to create your View myapp_create.pl view RRDGraph RRDGraph from the controller: sub routine :Local { my ($self, $c) = @_; $c->stash->{'graph'} = [ "--lower-limit", "0", "--start", "end-1d", "--vertical-label", "My Label", "--height", 600, "--width", 300, "DEF:Data=/path/to/rrd.rrd:data:AVERAGE", "AREA:Data#0000FF:Data " ]; $c->forward('MyApp::View::RRDGraph'); } =head1 DESCRIPTION This view generates RRD graph images from the graph defintion placed in the stash. The controller is responsable of placing an ARRAYREF in B<$c->stash->{'graph'}> with the same data as to generate a graph with the RRDs module, except for I, that will be automatically generated by the view. =head1 CONFIGURATION Configurations for the view are: =head2 IMG_DIR Directory to generate temporary image files. Defaults to B =head2 IMG_FORMAT Image format for the generated files. 'PNG' by default. =head2 ON_ERROR_SERVE On error, if this config value is set, the file to which it points will be served (so you can serve an "error image" file to the user). Alternately, it can be set to a code reference, that will called with B<$self>, B<$c> and B<$error>. You can then generate your own content in this handler. Default (leaving undefined) is to throw an expception. See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more info. =head1 METHODS =head2 new Constructor. =head2 process Called internally by Catalyst when the view is used. =head1 AUTHOR Jose Luis Martinez CPAN ID: JLMARTIN CAPSiDE jlmartinez@capside.com http://www.pplusdomain.net =head1 THANKS To Ton Voon for sending in patches, tests, and ideas. =head1 COPYRIGHT This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The full text of the license can be found in the LICENSE file included with this module. =head1 SEE ALSO RRDs: http://oss.oetiker.ch/rrdtool/prog/RRDs.en.html RRD graph docs: http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html, http://oss.oetiker.ch/rrdtool/doc/rrdgraph_data.en.html, http://oss.oetiker.ch/rrdtool/doc/rrdgraph_graph.en.html =cut #################### main pod documentation end ################### 1; # The preceding line will help the module return a true value