diff options
Diffstat (limited to 'torrus/perllib/Torrus/Renderer/RRDtool.pm')
-rw-r--r-- | torrus/perllib/Torrus/Renderer/RRDtool.pm | 993 |
1 files changed, 993 insertions, 0 deletions
diff --git a/torrus/perllib/Torrus/Renderer/RRDtool.pm b/torrus/perllib/Torrus/Renderer/RRDtool.pm new file mode 100644 index 000000000..db0cc54a9 --- /dev/null +++ b/torrus/perllib/Torrus/Renderer/RRDtool.pm @@ -0,0 +1,993 @@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: RRDtool.pm,v 1.1 2010-12-27 00:03:44 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +package Torrus::Renderer::RRDtool; + +use strict; + +use Torrus::ConfigTree; +use Torrus::RPN; +use Torrus::Log; + +use RRDs; + +# All our methods are imported by Torrus::Renderer; + +my %rrd_graph_opts = + ( + 'start' => '--start', + 'end' => '--end', + 'width' => '--width', + 'height' => '--height' + ); + +my @arg_arrays = qw(opts defs bg hwtick hrule hwline line fg); + + +sub render_rrgraph +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + my $view = shift; + my $outfile = shift; + + if( not $config_tree->isLeaf($token) ) + { + Error("Token $token is not a leaf"); + return undef; + } + + my $obj = {'args' => {}, 'dname' => 'A'}; + + foreach my $arrayName ( @arg_arrays ) + { + $obj->{'args'}{$arrayName} = []; + } + + push( @{$obj->{'args'}{'opts'}}, + $self->rrd_make_opts( $config_tree, $token, $view, + \%rrd_graph_opts, ) ); + + push( @{$obj->{'args'}{'opts'}}, + $self->rrd_make_graph_opts( $config_tree, $token, $view ) ); + + my $dstype = $config_tree->getNodeParam($token, 'ds-type'); + + if( $dstype eq 'rrd-multigraph' ) + { + $self->rrd_make_multigraph( $config_tree, $token, $view, $obj ); + } + else + { + my $leaftype = $config_tree->getNodeParam($token, 'leaf-type'); + + # Handle DEFs and CDEFs + # At the moment, we call the DEF as 'A'. Could change in the future + if( $leaftype eq 'rrd-def' ) + { + push( @{$obj->{'args'}{'defs'}}, + $self->rrd_make_def( $config_tree, $token, + $obj->{'dname'} ) ); + + if( $self->rrd_check_hw( $config_tree, $token, $view ) ) + { + $self->rrd_make_holtwinters( $config_tree, $token, + $view, $obj ); + } + } + elsif( $leaftype eq 'rrd-cdef' ) + { + my $expr = $config_tree->getNodeParam($token, 'rpn-expr'); + push( @{$obj->{'args'}{'defs'}}, + $self->rrd_make_cdef($config_tree, $token, + $obj->{'dname'}, $expr) ); + } + else + { + Error("Unsupported leaf-type: $leaftype"); + return undef; + } + + $self->rrd_make_graphline( $config_tree, $token, $view, $obj ); + } + + $self->rrd_make_hrules( $config_tree, $token, $view, $obj ); + if( not $Torrus::Renderer::ignoreDecorations ) + { + $self->rrd_make_decorations( $config_tree, $token, $view, $obj ); + } + + # We're all set + + + my @args; + foreach my $arrayName ( @arg_arrays ) + { + push( @args, @{$obj->{'args'}{$arrayName}} ); + } + Debug("RRDs::graph arguments: " . join(' ', @args)); + + $self->tz_set(); + &RRDs::graph( $outfile, @args ); + $self->tz_restore(); + my $ERR=RRDs::error; + if( $ERR ) + { + my $path = $config_tree->path($token); + Error("$path $view: Error during RRD graph: $ERR"); + return undef; + } + + return( $config_tree->getParam($view, 'expires')+time(), 'image/png' ); +} + + +my %rrd_print_opts = + ( + 'start' => '--start', + 'end' => '--end', + ); + + + +sub render_rrprint +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + my $view = shift; + my $outfile = shift; + + if( not $config_tree->isLeaf($token) ) + { + Error("Token $token is not a leaf"); + return undef; + } + + my @arg_opts; + my @arg_defs; + my @arg_print; + + push( @arg_opts, $self->rrd_make_opts( $config_tree, $token, $view, + \%rrd_print_opts, ) ); + + my $dstype = $config_tree->getNodeParam($token, 'ds-type'); + + if( $dstype eq 'rrd-multigraph' ) + { + Error("View type rrprint is not supported ". + "for DS type rrd-multigraph"); + return undef; + } + + my $leaftype = $config_tree->getNodeParam($token, 'leaf-type'); + + # Handle DEFs and CDEFs + # At the moment, we call the DEF as 'A'. Could change in the future + my $dname = 'A'; + if( $leaftype eq 'rrd-def' ) + { + push( @arg_defs, + $self->rrd_make_def( $config_tree, $token, $dname ) ); + } + elsif( $leaftype eq 'rrd-cdef' ) + { + my $expr = $config_tree->getNodeParam($token, 'rpn-expr'); + push( @arg_defs, + $self->rrd_make_cdef($config_tree, $token, $dname, $expr) ); + } + else + { + Error("Unsupported leaf-type: $leaftype"); + return undef; + } + + foreach my $cf ( split(',', $config_tree->getParam($view, 'print-cf')) ) + { + push( @arg_print, sprintf( 'PRINT:%s:%s:%%le', $dname, $cf ) ); + } + + # We're all set + + my @args = ( @arg_opts, @arg_defs, @arg_print ); + Debug("RRDs::graph arguments: " . join(' ', @args)); + + my $printout; + $self->tz_set(); + ($printout, undef, undef) = RRDs::graph('/dev/null', @args); + $self->tz_restore(); + my $ERR=RRDs::error; + if( $ERR ) + { + my $path = $config_tree->path($token); + Error("$path $view: Error during RRD graph: $ERR"); + return undef; + } + + if( not open(OUT, ">$outfile") ) + { + Error("Cannot open $outfile for writing: $!"); + return undef; + } + else + { + printf OUT ("%s\n", join(':', @{$printout})); + close OUT; + } + + return( $config_tree->getParam($view, 'expires')+time(), 'text/plain' ); +} + + + +sub rrd_make_multigraph +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + my $view = shift; + my $obj = shift; + + my @dsNames = + split(',', $config_tree->getNodeParam($token, 'ds-names') ); + + # We need this to refer to some existing variable name + $obj->{'dname'} = $dsNames[0]; + + # Analyze the drawing order + my %dsOrder; + foreach my $dname ( @dsNames ) + { + my $order = $config_tree->getNodeParam($token, 'line-order-'.$dname); + $dsOrder{$dname} = defined( $order ) ? $order : 100; + } + + my $disable_legend = $config_tree->getParam($view, 'disable-legend'); + $disable_legend = + (defined($disable_legend) and $disable_legend eq 'yes') ? 1:0; + + # make DEFs and Line instructions + + my $do_gprint = 0; + + if( not $disable_legend ) + { + $do_gprint = $self->rrd_if_gprint( $config_tree, $token ); + if( $do_gprint ) + { + $self->rrd_make_gprint_header( $config_tree, $token, $view, $obj ); + } + } + + foreach my $dname ( sort {$dsOrder{$a} <=> $dsOrder{$b}} @dsNames ) + { + my $dograph = 1; + my $ignoreViews = + $config_tree->getNodeParam($token, 'ignore-views-'.$dname); + if( defined( $ignoreViews ) and + grep {$_ eq $view} split(',', $ignoreViews) ) + { + $dograph = 0; + } + + my $gprint_this = $do_gprint; + if( $do_gprint ) + { + my $ds_nogprint = + $config_tree->getNodeParam($token, 'disable-gprint-'.$dname); + if( defined( $ds_nogprint ) and $ds_nogprint eq 'yes' ) + { + $gprint_this = 0; + } + } + + my $legend; + + if( $dograph or $gprint_this ) + { + my $expr = $config_tree->getNodeParam($token, 'ds-expr-'.$dname); + push( @{$obj->{'args'}{'defs'}}, + $self->rrd_make_cdef($config_tree, $token, $dname, $expr) ); + + $legend = + $config_tree->getNodeParam($token, 'graph-legend-'.$dname); + if( defined( $legend ) ) + { + $legend =~ s/:/\\:/g; + } + else + { + $legend = ''; + } + } + + if( $gprint_this ) + { + $self->rrd_make_gprint( $dname, $legend, + $config_tree, $token, $view, $obj ); + if( not $dograph ) + { + push( @{$obj->{'args'}{'line'}}, + 'COMMENT:' . $legend . '\l'); + } + } + else + { + # For datasource that disables gprint, there's no reason + # to print the label + $legend = ''; + } + + if( $dograph ) + { + my $linestyle = + $self->mkline( $config_tree->getNodeParam + ($token, 'line-style-'.$dname) ); + + my $linecolor = + $self->mkcolor( $config_tree->getNodeParam + ($token, 'line-color-'.$dname) ); + + my $alpha = + $config_tree->getNodeParam($token, 'line-alpha-'.$dname); + if( defined( $alpha ) ) + { + $linecolor .= $alpha; + } + + my $stack = + $config_tree->getNodeParam($token, 'line-stack-'.$dname); + if( defined( $stack ) and $stack eq 'yes' ) + { + $stack = ':STACK'; + } + else + { + $stack = ''; + } + + push( @{$obj->{'args'}{'line'}}, + sprintf( '%s:%s%s%s%s', $linestyle, $dname, + $linecolor, + length($legend) > 0 ? ':'.$legend.'\l' : '', + $stack ) ); + + } + } +} + + +# Check if Holt-Winters stuff is needed +sub rrd_check_hw +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + my $view = shift; + + my $use_hw = 0; + my $nodeHW = $config_tree->getNodeParam($token, 'rrd-hwpredict'); + if( defined($nodeHW) and $nodeHW eq 'enabled' ) + { + my $viewHW = $config_tree->getParam($view, 'rrd-hwpredict'); + my $varNoHW = $self->{'options'}->{'variables'}->{'NOHW'}; + + if( (not defined($viewHW) or $viewHW ne 'disabled') and + (not $varNoHW) ) + { + $use_hw = 1; + } + } + return $use_hw; +} + + +sub rrd_make_holtwinters +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + my $view = shift; + my $obj = shift; + + my $dname = $obj->{'dname'}; + + push( @{$obj->{'args'}{'defs'}}, + $self->rrd_make_def( $config_tree, $token, + $dname . 'pred', 'HWPREDICT' ) ); + push( @{$obj->{'args'}{'defs'}}, + $self->rrd_make_def( $config_tree, $token, + $dname . 'dev', 'DEVPREDICT' ) ); + # Upper boundary definition + push( @{$obj->{'args'}{'defs'}}, + sprintf( 'CDEF:%supper=%spred,%sdev,2,*,+', + $dname, $dname, $dname ) ); + + # Lower boundary definition + push( @{$obj->{'args'}{'defs'}}, + sprintf( 'CDEF:%slower=%spred,%sdev,2,*,-', + $dname, $dname, $dname ) ); + + # Failures definition + push( @{$obj->{'args'}{'defs'}}, + $self->rrd_make_def( $config_tree, $token, + $dname . 'fail', 'FAILURES' ) ); + + # Generate H-W Boundary Lines + + # Boundary style + my $hw_bndr_style = $config_tree->getParam($view, 'hw-bndr-style'); + $hw_bndr_style = 'LINE1' unless defined $hw_bndr_style; + $hw_bndr_style = $self->mkline( $hw_bndr_style ); + + my $hw_bndr_color = $config_tree->getParam($view, 'hw-bndr-color'); + $hw_bndr_color = '#FF0000' unless defined $hw_bndr_color; + $hw_bndr_color = $self->mkcolor( $hw_bndr_color ); + + push( @{$obj->{'args'}{'hwline'}}, + sprintf( '%s:%supper%s:%s', + $hw_bndr_style, $dname, $hw_bndr_color, + $Torrus::Renderer::hwGraphLegend ? 'Boundaries\n':'' ) ); + push( @{$obj->{'args'}{'hwline'}}, + sprintf( '%s:%slower%s', + $hw_bndr_style, $dname, $hw_bndr_color ) ); + + # Failures Tick + + my $hw_fail_color = $config_tree->getParam($view, 'hw-fail-color'); + $hw_fail_color = '#FFFFA0' unless defined $hw_fail_color; + $hw_fail_color = $self->mkcolor( $hw_fail_color ); + + push( @{$obj->{'args'}{'hwtick'}}, + sprintf( 'TICK:%sfail%s:1.0:%s', + $dname, $hw_fail_color, + $Torrus::Renderer::hwGraphLegend ? 'Failures':'') ); +} + +sub rrd_make_graphline +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + my $view = shift; + my $obj = shift; + + my $legend; + + my $disable_legend = $config_tree->getParam($view, 'disable-legend'); + if( not defined($disable_legend) or $disable_legend ne 'yes' ) + { + $legend = $config_tree->getNodeParam($token, 'graph-legend'); + if( defined( $legend ) ) + { + $legend =~ s/:/\\:/g; + } + } + + if( not defined( $legend ) ) + { + $legend = ''; + } + + my $styleval = $config_tree->getNodeParam($token, 'line-style'); + if( not defined( $styleval ) or length( $styleval ) == 0 ) + { + $styleval = $config_tree->getParam($view, 'line-style'); + } + + my $linestyle = $self->mkline( $styleval ); + + my $colorval = $config_tree->getNodeParam($token, 'line-color'); + if( not defined( $colorval ) or length( $colorval ) == 0 ) + { + $colorval = $config_tree->getParam($view, 'line-color'); + } + + my $linecolor = $self->mkcolor( $colorval ); + + if( $self->rrd_if_gprint( $config_tree, $token ) ) + { + $self->rrd_make_gprint_header( $config_tree, $token, $view, $obj ); + + $self->rrd_make_gprint( $obj->{'dname'}, $legend, + $config_tree, $token, $view, $obj ); + } + + push( @{$obj->{'args'}{'line'}}, + sprintf( '%s:%s%s%s', $linestyle, $obj->{'dname'}, $linecolor, + length($legend) > 0 ? ':'.$legend.'\l' : '' ) ); +} + + +# Generate RRDtool arguments for HRULE's + +sub rrd_make_hrules +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + my $view = shift; + my $obj = shift; + + my $hrulesList = $config_tree->getParam($view, 'hrules'); + if( defined( $hrulesList ) ) + { + foreach my $hruleName ( split(',', $hrulesList ) ) + { + # The presence of this parameter is checked by Validator + my $valueParam = + $config_tree->getParam( $view, 'hrule-value-'.$hruleName ); + my $value = $config_tree->getNodeParam( $token, $valueParam ); + + if( defined( $value ) ) + { + my $color = + $config_tree->getParam($view, 'hrule-color-'.$hruleName); + $color = $self->mkcolor( $color ); + + my $legend = + $config_tree->getNodeParam($token, + 'hrule-legend-'.$hruleName); + + my $arg = sprintf( 'HRULE:%e%s', $value, $color ); + if( defined( $legend ) and $legend =~ /\S/ ) + { + $arg .= ':' . $legend . '\l'; + } + push( @{$obj->{'args'}{'hrule'}}, $arg ); + } + } + } +} + + +sub rrd_make_decorations +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + my $view = shift; + my $obj = shift; + + my $decorList = $config_tree->getParam($view, 'decorations'); + my $ignore_decor = + $config_tree->getNodeParam($token, 'graph-ignore-decorations'); + if( defined( $decorList ) and + (not defined($ignore_decor) or $ignore_decor ne 'yes') ) + { + my $decor = {}; + foreach my $decorName ( split(',', $decorList ) ) + { + my $order = + $config_tree->getParam($view, 'dec-order-' . $decorName); + $decor->{$order} = {'def' => [], 'line' => ''}; + + my $style = + $self->mkline( $config_tree-> + getParam($view, 'dec-style-' . $decorName) ); + my $color = + $self->mkcolor( $config_tree-> + getParam($view, 'dec-color-' . $decorName) ); + my $expr = $config_tree-> + getParam($view, 'dec-expr-' . $decorName); + + push( @{$decor->{$order}{'def'}}, + $self->rrd_make_cdef( $config_tree, $token, $decorName, + $obj->{'dname'} . ',POP,' . $expr ) ); + + $decor->{$order}{'line'} = + sprintf( '%s:%s%s', $style, $decorName, $color ); + } + + foreach my $order ( sort {$a<=>$b} keys %{$decor} ) + { + my $array = $order < 0 ? 'bg':'fg'; + + push( @{$obj->{'args'}{'defs'}}, @{$decor->{$order}{'def'}} ); + push( @{$obj->{'args'}{$array}}, $decor->{$order}{'line'} ); + } + } +} + +# Takes the parameters from the view, and composes the list of +# RRDtool arguments + +sub rrd_make_opts +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + my $view = shift; + my $opthash = shift; + + my @args = (); + foreach my $param ( keys %{$opthash} ) + { + my $value = + $self->{'options'}->{'variables'}->{'G' . $param}; + + if( not defined( $value ) ) + { + $value = $config_tree->getParam( $view, $param ); + } + + if( defined( $value ) ) + { + if( ( $param eq 'start' or $param eq 'end' ) and + defined( $self->{'options'}->{'variables'}->{'NOW'} ) ) + { + my $now = $self->{'options'}->{'variables'}->{'NOW'}; + if( index( $value , 'now' ) >= 0 ) + { + $value =~ s/now/$now/; + } + elsif( $value =~ /^(\-|\+)/ ) + { + $value = $now . $value; + } + } + push( @args, $opthash->{$param}, $value ); + } + } + + my $params = $config_tree->getParam($view, 'rrd-params'); + if( defined( $params ) ) + { + push( @args, split('\s+', $params) ); + } + + my $scalingbase = $config_tree->getNodeParam($token, 'rrd-scaling-base'); + if( defined($scalingbase) and $scalingbase == 1024 ) + { + push( @args, '--base', '1024' ); + } + + return @args; +} + + +sub rrd_make_graph_opts +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + my $view = shift; + + my @args = ( '--imgformat', 'PNG' ); + + my $graph_log = $config_tree->getNodeParam($token, 'graph-logarithmic'); + if( defined($graph_log) and $graph_log eq 'yes' ) + { + push( @args, '--logarithmic' ); + } + + my $disable_title = + $config_tree->getParam($view, 'disable-title'); + if( not defined( $disable_title ) or $disable_title ne 'yes' ) + { + my $title = $config_tree->getNodeParam($token, 'graph-title'); + if( not defined( $title ) or length( $title ) == 0 ) + { + $title = ' '; + } + push( @args, '--title', $title ); + } + + my $disable_vlabel = + $config_tree->getParam($view, 'disable-vertical-label'); + if( not defined( $disable_vlabel ) or $disable_vlabel ne 'yes' ) + { + my $vertical_label = + $config_tree->getNodeParam($token, 'vertical-label'); + if( defined( $vertical_label ) and length( $vertical_label ) > 0 ) + { + push( @args, '--vertical-label', $vertical_label ); + } + } + + my $ignore_limits = $config_tree->getParam($view, 'ignore-limits'); + if( not defined($ignore_limits) or $ignore_limits ne 'yes' ) + { + my $ignore_lower = $config_tree->getParam($view, 'ignore-lower-limit'); + if( not defined($ignore_lower) or $ignore_lower ne 'yes' ) + { + my $limit = + $config_tree->getNodeParam($token, 'graph-lower-limit'); + if( defined($limit) and length( $limit ) > 0 ) + { + push( @args, '--lower-limit', $limit ); + } + } + + my $ignore_upper = $config_tree->getParam($view, 'ignore-upper-limit'); + if( not defined($ignore_upper) or $ignore_upper ne 'yes' ) + { + my $limit = + $config_tree->getNodeParam($token, 'graph-upper-limit'); + if( defined($limit) and length( $limit ) > 0 ) + { + push( @args, '--upper-limit', $limit ); + } + } + + my $rigid_boundaries = + $config_tree->getNodeParam($token, 'graph-rigid-boundaries'); + if( defined($rigid_boundaries) and $rigid_boundaries eq 'yes' ) + { + push( @args, '--rigid' ); + } + } + + if( scalar( @Torrus::Renderer::graphExtraArgs ) > 0 ) + { + push( @args, @Torrus::Renderer::graphExtraArgs ); + } + + return @args; +} + + +sub rrd_make_def +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + my $dname = shift; + my $cf = shift; + + my $datafile = $config_tree->getNodeParam($token, 'data-file'); + my $dataddir = $config_tree->getNodeParam($token, 'data-dir'); + my $rrdfile = $dataddir.'/'.$datafile; + if( not -r $rrdfile ) + { + my $path = $config_tree->path($token); + Error("$path: No such file or directory: $rrdfile"); + return undef; + } + + my $ds = $config_tree->getNodeParam($token, 'rrd-ds'); + if( not defined $cf ) + { + $cf = $config_tree->getNodeParam($token, 'rrd-cf'); + } + return sprintf( 'DEF:%s=%s:%s:%s', + $dname, $rrdfile, $ds, $cf ); +} + + + +my %cfNames = + ( 'AVERAGE' => 1, + 'MIN' => 1, + 'MAX' => 1, + 'LAST' => 1 ); + +# Moved the validation part to Torrus::ConfigTree::Validator +sub rrd_make_cdef +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + my $dname = shift; + my $expr = shift; + + my @args = (); + + # We will name the DEFs as $dname.sprintf('%.2d', $ds_couter++); + my $ds_couter = 1; + + my $rpn = new Torrus::RPN; + + # The callback for RPN translation + my $callback = sub + { + my ($noderef, $timeoffset) = @_; + + my $function; + if( $noderef =~ s/^(.+)\@// ) + { + $function = $1; + } + + my $cf; + if( defined( $function ) and $cfNames{$function} ) + { + $cf = $function; + } + + my $leaf = length($noderef) > 0 ? + $config_tree->getRelative($token, $noderef) : $token; + + my $varname = $dname . sprintf('%.2d', $ds_couter++); + push( @args, + $self->rrd_make_def( $config_tree, $leaf, $varname, $cf ) ); + return $varname; + }; + + $expr = $rpn->translate( $expr, $callback ); + push( @args, sprintf( 'CDEF:%s=%s', $dname, $expr ) ); + return @args; +} + + +sub rrd_if_gprint +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + + my $disable = $config_tree->getNodeParam($token, 'graph-disable-gprint'); + if( defined( $disable ) and $disable eq 'yes' ) + { + return 0; + } + return 1; +} + +sub rrd_make_gprint +{ + my $self = shift; + my $vname = shift; + my $legend = shift; + my $config_tree = shift; + my $token = shift; + my $view = shift; + my $obj = shift; + + my @args = (); + + my $gprintValues = $config_tree->getParam($view, 'gprint-values'); + if( defined( $gprintValues ) and length( $gprintValues ) > 0 ) + { + foreach my $gprintVal ( split(',', $gprintValues ) ) + { + my $format = + $config_tree->getParam($view, 'gprint-format-' . $gprintVal); + push( @args, 'GPRINT:' . $vname . ':' . $format ); + } + } + + push( @{$obj->{'args'}{'line'}}, @args ); +} + + +sub rrd_make_gprint_header +{ + my $self = shift; + my $config_tree = shift; + my $token = shift; + my $view = shift; + my $obj = shift; + + my $gprintValues = $config_tree->getParam($view, 'gprint-values'); + if( defined( $gprintValues ) and length( $gprintValues ) > 0 ) + { + my $gprintHeader = $config_tree->getParam($view, 'gprint-header'); + if( defined( $gprintHeader ) and length( $gprintHeader ) > 0 ) + { + push( @{$obj->{'args'}{'line'}}, + 'COMMENT:' . $gprintHeader . '\l' ); + } + } +} + + +sub mkcolor +{ + my $self = shift; + my $color = shift; + + my $recursionLimit = 100; + + while( $color =~ /^\#\#(\S+)$/ ) + { + if( $recursionLimit-- <= 0 ) + { + Error('Color recursion is too deep'); + $color = '#000000'; + } + else + { + my $colorName = $1; + $color = $Torrus::Renderer::graphStyles{$colorName}{'color'}; + if( not defined( $color ) ) + { + Error('No color is defined for ' . $colorName); + $color = '#000000'; + } + } + } + return $color; +} + +sub mkline +{ + my $self = shift; + my $line = shift; + + if( $line =~ /^\#\#(\S+)$/ ) + { + my $lineName = $1; + $line = $Torrus::Renderer::graphStyles{$lineName}{'line'}; + if( not defined( $line ) ) + { + Error('No line style is defined for ' . $lineName); + $line = 'LINE1'; + } + } + return $line; +} + + +sub tz_set +{ + my $self = shift; + + if( defined $ENV{'TZ'} ) + { + Debug("Previous TZ value: " . $ENV{'TZ'}); + $self->{'tz_defined'} = 1; + } + else + { + $self->{'tz_defined'} = 0; + } + + if( defined( my $newTZ = $self->{'options'}->{'variables'}->{'TZ'} ) ) + { + Debug("Setting TZ to " . $newTZ); + $self->{'tz_old'} = $ENV{'TZ'}; + $ENV{'TZ'} = $newTZ; + $self->{'tz_changed'} = 1; + } + else + { + $self->{'tz_changed'} = 0; + } +} + +sub tz_restore +{ + my $self = shift; + + if( $self->{'tz_changed'} ) + { + if( $self->{'tz_defined'} ) + { + Debug("Restoring TZ back to " . $self->{'tz_old'}); + $ENV{'TZ'} = $self->{'tz_old'}; + } + else + { + Debug("Restoring TZ back to undefined"); + delete $ENV{'TZ'}; + } + } +} + + +1; + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: |