![]() ![]() |
hotsanic |
Subversion Repositories: |
Compare with Previous - Blame - Download
## $Id: HotSaNICdiagram.pm,v 1.29 2004/09/19 10:07:19 bernisys Exp $#package HotSaNICdiagram;use RRDs;($VERSION = '$Revision: 1.29 $') =~ s/.*(\d+\.\d+).*/$1/;my @Weekday=("Sun","Mon","Tue","Wed","Thu","Fri","Sat");######################################################################## evaluates some diagram properties from the given range## Usage:# ($description,$file_description,$build_interval,$diagram_range,$timestring)=get_diagram_properties($range);#sub get_diagram_properties {my ($range)=@_;my ($descr,$file,$build,$fullrange);if ($range eq "1h") { $descr="hour"; $file=$descr; $build=0; $fullrange=3600; }elsif ($range eq "6h") { $descr="6 hours"; $file="6h"; $build=30; $fullrange=21600; }elsif ($range eq "1day") { $descr="day"; $file=$descr; $build=120; $fullrange=86400; }elsif ($range eq "1week") { $descr="week"; $file=$descr; $build=1000; $fullrange=604800; }elsif ($range eq "1month") { $descr="month"; $file=$descr; $build=4300; $fullrange=2592000; }elsif ($range eq "1year") { $descr="year"; $file=$descr; $build=52500; $fullrange=31536000; }($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);$year+=1900;$mon++;if ($mon<10) { $mon="0".$mon; }if ($mday<10) { $mday="0".$mday; }if ($hour<10) { $hour="0".$hour; }if ($min<10) { $min="0".$min; }$buildtime="$Weekday[$wday] $year-$mon-$mday $hour:$min";return ($descr,$file,$build,$fullrange,$buildtime);}######################################################################## Creates a diagram from the options passed within a config hash## Usage:# graph(%CONFIGHASH);## Hints:# The hash has to contain the following items:## %CONFIGHASH=( FILENAME => "full path to output file without suffix"# FORMAT => "gif" # ("png" or "gif")# INTERVAL => <seconds between neccessary update># FORCE => 0 for automatic checking, >0 forces plot# RANGE => plot range of diagram (1year 6h 1h ...)# DEBUGLEVEL => everything >1 plots complete optiin array# OPTIONS => array of options that will be passed tpo RRDs# assign it like this: => [(@a1,@a2,...)]#sub graph {my %CONF=@_;my $FILE=$CONF{FILENAME}.".".$CONF{FORMAT};my $TEMPFILE=$CONF{FILENAME}."-temp.".$CONF{FORMAT};my @OPTIONS=@{$CONF{OPTIONS}};if (! -e $FILE) { $CONF{FORCE}++; }else { $CONF{FORCE}++ if time >= (stat($FILE))[9]+$CONF{INTERVAL}; }if ($CONF{FORCE} > 0) {if ($CONF{DEBUGLEVEL} > 1) { print join("\n",$TEMPFILE,@OPTIONS),"\n"; }my ($prints,$xs,$ys)=RRDs::graph $TEMPFILE,@OPTIONS;if ($ERROR = RRDs::error) { print time," ",$CONF{MODNAME},": $ERROR\n"; }else {rename $TEMPFILE,$FILE;printf " %9s %4d x %4d %s\n", $CONF{RANGE},$xs,$ys,$FILE;}}}sub check_args {my $OPT=0;$FORCE=0;$DEBUGLEVEL=-1;%PLOT=();foreach (@_) {$FORCE=1 if $_ eq "a";$DEBUGLEVEL=100 if $_ eq "d";if ($OPT==1) { $PLOT{$_}=1; $OPT=0; }$OPT=1 if $_ eq "g";if ( ($_ eq "?") or ($_ eq "h") ) {print "options:\ng <name> only graph item <name>(can be used multiple times, default: plot all)\na plot all time-graphs of selected items(default: plot only expired graphs)\nd enable debug mode (prints all graph options -much output!)\n? or h display this help-text\n";exit;}}return ($FORCE,$DEBUGLEVEL,%PLOT);}######################################### get_common_options calculates an array of common module-specific and# global diagram options to be passed to RRDs::graph. it accepts a hash# containing both modulespecific and global settings.#sub get_common_options {my %CONFIG=@_;my @OPTIONS=();if ($CONFIG{GRAPH_RIGID} == 1 ) { push @OPTIONS,"-r"; }if ($CONFIG{GRAPH_FORCE_LEGEND} == 1 ) { push @OPTIONS,"-F"; }if ($CONFIG{GRAPH_STYLE} eq "log" ) {push @OPTIONS,"-o";$CONFIG{GRAPH_MIN}=$CONFIG{GRAPH_MIN_LOG};}if (defined $CONFIG{GRAPH_BASE}) {if ( ($CONFIG{GRAPH_BASE} eq "percent") or ($CONFIG{GRAPH_BASE} eq "%") ) {if (defined $CONFIG{GRAPH_MAX}) { $CONFIG{GRAPH_MAX}*=100; }if (defined $CONFIG{GRAPH_MIN}) { $CONFIG{GRAPH_MIN}*=100; }}if ($CONFIG{GRAPH_BASE} eq "bits") {if (defined $CONFIG{GRAPH_MAX}) { $CONFIG{GRAPH_MAX}*=8; }if (defined $CONFIG{GRAPH_MIN}) { $CONFIG{GRAPH_MIN}*=8; }}elsif ($CONFIG{GRAPH_BASE} eq "ms") {if (defined $CONFIG{GRAPH_MAX}) { $CONFIG{GRAPH_MAX}/=1000; }if (defined $CONFIG{GRAPH_MIN}) { $CONFIG{GRAPH_MIN}/=1000; }}elsif ($CONFIG{GRAPH_BASE} eq "us") {if (defined $CONFIG{GRAPH_MAX}) { $CONFIG{GRAPH_MAX}/=1000000; }if (defined $CONFIG{GRAPH_MIN}) { $CONFIG{GRAPH_MIN}/=1000000; }}}push @OPTIONS,("-i", # graphic interlaced mode"-w",$CONFIG{WIDTH}, # drawing area width"-h",$CONFIG{HEIGHT}, # drawing area height"-b",$CONFIG{GRAPH_UNIT}, # value of "1k" (1000 or 1024)"-u",$CONFIG{GRAPH_MAX}, # upper initial border"-l",$CONFIG{GRAPH_MIN}, # lower initial border"-a",uc($CONFIG{IMAGEFORMAT}) # image format);return @OPTIONS;}######################################################################## generates an array suitable to feed to RRDs::graph to build a graph# including a legend with the desired consolidation functions.## Usage:# insert_data(type,var,color,description,legends,unit,use_SI);## type: AREA LINE1 LINE2 LINE3 STACK## var: RRD variable to be graphed and variables which will# be assigned to min, average, max and now. They# have to be separated by spaces. If less than five# variables are stated, the LAST entry will be copied# to the remaining positions.# If you just want to insert a legend without adding a# graph, the first element must be a numerical zero "0"# The "description" can be used for padding the legend.## color: graph's color in RRDs::graph notation ( RRGGBB )## description: name of the graph or short description that will be# used in the legend## legends: one or more space-separated occurances of:# min avg max cur now ("now" is the same as "cur")## unit: the unit that will be appended after the last legend## use_SI: 0 -> just print the plain value# 1 -> print values in SI units (micro, milli, kilo, mega, ...)# -1 -> same as "1", but SI-units will be added without a space## EXAMPLE:## insert_data("AREA","abc xyz","#0000ff","test legend","min max","bytes",1);## -> draw a blue area with the rrd variable "abc" and add a corrosponding# legend to it, but refer the legend to the variable "xyz". The legend# will use SI-units and the unit "bytes". It will look like this:## [#] test legend (min: 1.23k max: 12.34M bytes)#sub insert_data {my $graphtype=shift || "LINE1";my $rrdvar=shift || "";my $color=shift || "000000";my $description=shift || "";my $legends=shift || "min avg max";my $unit=shift || "";my $use_SI_units=shift || 0;my @legends=split / /,$legends;my @vars=split / /,$rrdvar;while ($#vars<4) { push @vars,$vars[$#vars]; }my $lead="";my @array=();if ($vars[0] ne "0") { push @array,"$graphtype:$vars[0]#$color:$description"; $description=""; }else { $lead=" "; }$SI="";if ($use_SI_units == 1) { $SI=" %s"; }elsif ($use_SI_units == -1) { $SI="%s"; }if ($unit ne "") { $unit=" $unit"; }my $num=0;foreach $legend (@legends) {my $open="";my $close="";if ($num == 0) { $open="$lead$description$lead("; }if ($num == $#legends) { $close="$unit)\\n"; }$num++;if ($legend eq "min") { push @array,"GPRINT:$vars[1]:MIN:$open"."min\\:%7.2lf$SI$close"; }elsif ($legend eq "avg") { push @array,"GPRINT:$vars[2]:AVERAGE:$open"."avg\\:%7.2lf$SI$close"; }elsif ($legend eq "max") { push @array,"GPRINT:$vars[3]:MAX:$open"."max\\:%7.2lf$SI$close"; }elsif ($legend eq "now") { push @array,"GPRINT:$vars[4]:LAST:$open"."now\\:%7.2lf$SI$close"; }elsif ($legend eq "cur") { push @array,"GPRINT:$vars[4]:LAST:$open"."now\\:%7.2lf$SI$close"; }$description="";$lead="";}return @array;}######################################################################## generates an array suitable to feed to RRDs::graph to build a min/max# graph including a legend with the desired consolidation functions.## Usage:# insert_minmax(var,areacolor,bordercolor,description,unit,use_SI);## var: RRD variables to be graphed and assigned to min and max.# They have to be separated by spaces.# If you just want to insert a legend without adding a# graph, the first element must be a numerical zero "0"# The "description" can be used for padding the legend.## areacolor: graph area color in RRDs::graph notation ( #RRGGBB )## bordercolor: border color in RRDs::graph notation ( #RRGGBB )## description: short description that will be appended in the legend## unit: the unit that will be appended after the last legend## use_SI: 0 -> just print the plain value# 1 -> print values in SI units (micro, milli, kilo, mega, ...)# -1 -> same as "1", but SI-units will be added without a space## EXAMPLE:## insert_data("AREA","abc xyz","0000ff","test legend","min max","bytes",1);## -> draw a blue area with the rrd variable "abc" and add a corrosponding# legend to it, but refer the legend to the variable "xyz". The legend# will use SI-units and the unit "bytes". It will look like this:## [#] test legend (min: 1.23k max: 12.34M bytes)#sub insert_minmax {my $rrdvar=shift || "";my $areacolor=shift || "000000";my $bordercolor=shift || "";my $description=shift || "";my $unit=shift || "";my $use_SI_units=shift || 0;my @vars=split / /,$rrdvar;my $lead="";my @array=();if ($vars[0] ne "0") {push @array,("CDEF:negmin$vars[0]=$vars[0],0,LT,$vars[0],0,IF","CDEF:negmax$vars[1]=$vars[1],0,LT,$vars[1],0,IF","AREA:$vars[1]#$areacolor:$description","AREA:$vars[0]#FFFFFF:","AREA:negmin$vars[0]#$areacolor:","AREA:negmax$vars[1]#FFFFFF:");if ($bordercolor ne "") {push @array,("LINE1:$vars[0]#$bordercolor:","LINE1:$vars[1]#$bordercolor:");}$description="";}else { $lead=" "; }if (! defined $vars[2]) { push @vars,$vars[0]; }if (! defined $vars[3]) { push @vars,$vars[1]; }$SI="";if ($use_SI_units == 1) { $SI=" %s"; }elsif ($use_SI_units == -1) { $SI="%s"; }if ($unit ne "") { $unit=" $unit"; }push @array,("GPRINT:$vars[2]:MIN:$lead$description$lead(min\\:%7.2lf$SI","GPRINT:$vars[2]:MAX:$lead$description$lead/%7.2lf$SI","GPRINT:$vars[3]:MIN:max\\:%7.2lf$SI","GPRINT:$vars[3]:MAX:/%7.2lf$SI$unit)\\n");return @array;}######################################################################## generates an array suitable to feed to RRDs::graph to mark# areas of unknown values## Usage:# insert_unknown_area($vars,$color,$description);## vars: space separated list of all variables to be taken# into account. If one of them is unknown, the area# will be marked## color: graph's color in RRDs::graph notation ( RRGGBB )## description: some additional legend that will (if defined) show# up in brackets after the string "data unknown".#sub insert_unknown_area {my $vars=shift;my $color=shift || "ffffa0";my $description=shift || "";if ($description ne "") { $description=" ($description)"; }# the scaring ;) definition of "wrongdata":# if TIME < now { if x unknown { INF else 0 } else 0 }# CDEF:wrongdata=TIME,$DATE,LT,x,UN,INF,0,IF,0,IF \# where "x" is the result of the addition of all variablesmy @vars=split /\s+/,$vars;my $string=shift @vars;if (@vars) { $string = $string.",".join (",+,",@vars).",+"; }return ("CDEF:wrongdata=TIME,".time.",LT,$string,UN,INF,0,IF,0,IF","AREA:wrongdata#$color:data unknown$description\\n","CDEF:wrongdatainv=0,wrongdata,-","AREA:wrongdatainv#$color:");}sub insert_lines {my %CONFIG=@_;my @array=("HRULE:0#000000");if (defined $CONFIG{GRAPH_ADDLINE}) {foreach (@{$CONFIG{GRAPH_ADDLINE}}) {my ($pos,$color,$comment)=split /,/;if (defined $CONFIG{$color}) { $color=$CONFIG{$color}; }push @array,"HRULE:$pos#$color:$comment";}}return @array}sub insert_vars {my $dbname=shift;my $dbvar=shift;my $graphvar=shift;my $which=shift;my @array=();foreach my $consolidation (split /\s+/,$which) {my $consname=lc $consolidation;if ($consname eq "average") { $consname="avg"; }push @array,"DEF:$graphvar"."_"."$consname=$dbname:$dbvar:$consolidation"}return @array;}1;