From: <ha...@us...> - 2008-03-13 03:33:55
|
Revision: 1051 http://ganglia.svn.sourceforge.net/ganglia/?rev=1051&view=rev Author: hawson Date: 2008-03-12 20:33:57 -0700 (Wed, 12 Mar 2008) Log Message: ----------- Implement modular graphs. All specific graph definitions are handled a single .php file. Modified Paths: -------------- trunk/monitor-core/web/conf.php trunk/monitor-core/web/functions.php trunk/monitor-core/web/graph.php Added Paths: ----------- trunk/monitor-core/web/graph.d/ trunk/monitor-core/web/graph.d/cpu_report.php trunk/monitor-core/web/graph.d/load_report.php trunk/monitor-core/web/graph.d/mem_report.php trunk/monitor-core/web/graph.d/metric.php trunk/monitor-core/web/graph.d/network_report.php trunk/monitor-core/web/graph.d/packet_report.php trunk/monitor-core/web/graph.d/sample_report.php Modified: trunk/monitor-core/web/conf.php =================================================================== --- trunk/monitor-core/web/conf.php 2008-03-07 12:30:56 UTC (rev 1050) +++ trunk/monitor-core/web/conf.php 2008-03-13 03:33:57 UTC (rev 1051) @@ -25,6 +25,9 @@ # otherwise, change it if it is installed elsewhere (like /usr/bin) define("RRDTOOL", "/usr/bin/rrdtool"); + +# Location for modular-graph files. +$graphdir='./graph.d'; # # If you want to grab data from a different ganglia source specify it here. # Although, it would be strange to alter the IP since the Round-Robin Modified: trunk/monitor-core/web/functions.php =================================================================== --- trunk/monitor-core/web/functions.php 2008-03-07 12:30:56 UTC (rev 1050) +++ trunk/monitor-core/web/functions.php 2008-03-13 03:33:57 UTC (rev 1051) @@ -419,6 +419,10 @@ { return htmlentities( $string ); } +#------------------------------------------------------------------------------- +function sanitize ( $string ) { + return escapeshellcmd( clean_string( rawurldecode( $string ) ) ) ; +} #------------------------------------------------------------------------------- # If arg is a valid number, return it. Otherwise, return null. Added: trunk/monitor-core/web/graph.d/cpu_report.php =================================================================== --- trunk/monitor-core/web/graph.d/cpu_report.php (rev 0) +++ trunk/monitor-core/web/graph.d/cpu_report.php 2008-03-13 03:33:57 UTC (rev 1051) @@ -0,0 +1,77 @@ +<?php + + +/* Pass in by reference! */ +function graph_cpu_report ( &$rrdtool_graph ) { + + global $context, + $cpu_idle_color, + $cpu_nice_color, + $cpu_system_color, + $cpu_user_color, + $cpu_wio_color, + $hostname, + $rrd_dir, + $size; + + $rrdtool_graph['height'] += $size == 'medium' ? 28 : 0 ; + $rrdtool_graph['title'] = 'CPU'; + $rrdtool_graph['upper-limit'] = '100'; + $rrdtool_graph['lower-limit'] = '0'; + $rrdtool_graph['vertical-label'] = 'Percent'; + $rrdtool_graph['extras'] = '--rigid'; + + if($context != "host" ) { + + + /* If we are not in a host context, then we need to calculate the average */ + $series = + "DEF:'num_nodes'='${rrd_dir}/cpu_user.rrd':'num':AVERAGE " + . "DEF:'cpu_user'='${rrd_dir}/cpu_user.rrd':'sum':AVERAGE " + . "CDEF:'ccpu_user'=cpu_user,num_nodes,/ " + . "DEF:'cpu_nice'='${rrd_dir}/cpu_nice.rrd':'sum':AVERAGE " + . "CDEF:'ccpu_nice'=cpu_nice,num_nodes,/ " + . "DEF:'cpu_system'='${rrd_dir}/cpu_system.rrd':'sum':AVERAGE " + . "CDEF:'ccpu_system'=cpu_system,num_nodes,/ " + . "DEF:'cpu_idle'='${rrd_dir}/cpu_idle.rrd':'sum':AVERAGE " + . "CDEF:'ccpu_idle'=cpu_idle,num_nodes,/ " + . "AREA:'ccpu_user'#$cpu_user_color:'User CPU' " + . "STACK:'ccpu_nice'#$cpu_nice_color:'Nice CPU' " + . "STACK:'ccpu_system'#$cpu_system_color:'System CPU' "; + + if (file_exists("$rrd_dir/cpu_wio.rrd")) { + $series .= "DEF:'cpu_wio'='${rrd_dir}/cpu_wio.rrd':'sum':AVERAGE " + ."CDEF:'ccpu_wio'=cpu_wio,num_nodes,/ " + ."STACK:'ccpu_wio'#$cpu_wio_color:'WAIT CPU' "; + } + + $series .= "STACK:'ccpu_idle'#$cpu_idle_color:'Idle CPU' "; + } + // Context is not "host" + else { + + $rrdtool_graph['title'] .= " - $hostname"; + + $series ="DEF:'cpu_user'='${rrd_dir}/cpu_user.rrd':'sum':AVERAGE " + ."DEF:'cpu_nice'='${rrd_dir}/cpu_nice.rrd':'sum':AVERAGE " + ."DEF:'cpu_system'='${rrd_dir}/cpu_system.rrd':'sum':AVERAGE " + ."DEF:'cpu_idle'='${rrd_dir}/cpu_idle.rrd':'sum':AVERAGE " + ."AREA:'cpu_user'#$cpu_user_color:'User CPU' " + ."STACK:'cpu_nice'#$cpu_nice_color:'Nice CPU' " + ."STACK:'cpu_system'#$cpu_system_color:'System CPU' "; + + if (file_exists("$rrd_dir/cpu_wio.rrd")) { + $series .= "DEF:'cpu_wio'='${rrd_dir}/cpu_wio.rrd':'sum':AVERAGE "; + $series .= "STACK:'cpu_wio'#$cpu_wio_color:'WAIT CPU' "; + } + + $series .= "STACK:'cpu_idle'#$cpu_idle_color:'Idle CPU' "; + } + + + $rrdtool_graph['series'] = $series; + + return $rrdtool_graph; +} + +?> Added: trunk/monitor-core/web/graph.d/load_report.php =================================================================== --- trunk/monitor-core/web/graph.d/load_report.php (rev 0) +++ trunk/monitor-core/web/graph.d/load_report.php 2008-03-13 03:33:57 UTC (rev 1051) @@ -0,0 +1,48 @@ +<?php + + +/* Pass in by reference! */ +function graph_load_report ( &$rrdtool_graph ) { + + global $context, + $cpu_num_color, + $cpu_user_color, + $hostname, + $load_one_color, + $num_nodes_color, + $proc_run_color, + $rrd_dir, + $size; + + $rrdtool_graph['height'] += $size == 'medium' ? 28 : 0 ; + $rrdtool_graph['title'] = 'Load'; + $rrdtool_graph['lower-limit'] = '0'; + $rrdtool_graph['vertical-label'] = 'Load/Procs'; + $rrdtool_graph['extras'] = '--rigid'; + + $series = "DEF:'load_one'='${rrd_dir}/load_one.rrd':'sum':AVERAGE " + ."DEF:'proc_run'='${rrd_dir}/proc_run.rrd':'sum':AVERAGE " + ."DEF:'cpu_num'='${rrd_dir}/cpu_num.rrd':'sum':AVERAGE "; + + if( $context != 'host' ) { + $series .="DEF:'num_nodes'='${rrd_dir}/cpu_num.rrd':'num':AVERAGE "; + $series .= "LINE2:'num_nodes'#$num_nodes_color:'Nodes' "; + } + + if ($context == 'host') + $rrdtool_graph['title'] .= " - $hostname"; + + + $series .="AREA:'load_one'#$load_one_color:'1-min Load' "; + + $series .="LINE2:'cpu_num'#$cpu_num_color:'CPUs' "; + $series .="LINE2:'proc_run'#$proc_run_color:'Running Processes' "; + + + $rrdtool_graph['series'] = $series; + + return $rrdtool_graph; + +} + +?> Added: trunk/monitor-core/web/graph.d/mem_report.php =================================================================== --- trunk/monitor-core/web/graph.d/mem_report.php (rev 0) +++ trunk/monitor-core/web/graph.d/mem_report.php 2008-03-13 03:33:57 UTC (rev 1051) @@ -0,0 +1,58 @@ +<?php + + +/* Pass in by reference! */ +function graph_mem_report ( &$rrdtool_graph ) { + + global $context, + $hostname, + $mem_shared_color, + $mem_cached_color, + $mem_buffered_color, + $mem_swapped_color, + $mem_used_color, + $cpu_num_color, + $rrd_dir, + $size; + + $rrdtool_graph['height'] += $size == 'medium' ? 19 : 0 ; // Two lines of text in the legend + $rrdtool_graph['title'] = 'Memory'; + $rrdtool_graph['lower-limit'] = '0'; + $rrdtool_graph['vertical-label'] = 'Bytes'; + $rrdtool_graph['extras'] = '--rigid --base 1024'; + + if ($context == 'host') + $rrdtool_graph['title'] .= " - $hostname"; + + + $series = "DEF:'mem_total'='${rrd_dir}/mem_total.rrd':'sum':AVERAGE " + ."CDEF:'bmem_total'=mem_total,1024,* " + ."DEF:'mem_shared'='${rrd_dir}/mem_shared.rrd':'sum':AVERAGE " + ."CDEF:'bmem_shared'=mem_shared,1024,* " + ."DEF:'mem_free'='${rrd_dir}/mem_free.rrd':'sum':AVERAGE " + ."CDEF:'bmem_free'=mem_free,1024,* " + ."DEF:'mem_cached'='${rrd_dir}/mem_cached.rrd':'sum':AVERAGE " + ."CDEF:'bmem_cached'=mem_cached,1024,* " + ."DEF:'mem_buffers'='${rrd_dir}/mem_buffers.rrd':'sum':AVERAGE " + ."CDEF:'bmem_buffers'=mem_buffers,1024,* " + ."CDEF:'bmem_used'='bmem_total','bmem_shared',-,'bmem_free',-,'bmem_cached',-,'bmem_buffers',- " + ."AREA:'bmem_used'#$mem_used_color:'Memory Used' " + ."STACK:'bmem_shared'#$mem_shared_color:'Memory Shared' " + ."STACK:'bmem_cached'#$mem_cached_color:'Memory Cached' " + ."STACK:'bmem_buffers'#$mem_buffered_color:'Memory Buffered' "; + if (file_exists("$rrd_dir/swap_total.rrd")) { + $series .= "DEF:'swap_total'='${rrd_dir}/swap_total.rrd':'sum':AVERAGE " + ."DEF:'swap_free'='${rrd_dir}/swap_free.rrd':'sum':AVERAGE " + ."CDEF:'bmem_swapped'='swap_total','swap_free',-,1024,* " + ."STACK:'bmem_swapped'#$mem_swapped_color:'Memory Swapped' "; + } + $series .= "LINE2:'bmem_total'#$cpu_num_color:'Total In-Core Memory' "; + + + $rrdtool_graph['series'] = $series; + + return $rrdtool_graph; + +} + +?> Added: trunk/monitor-core/web/graph.d/metric.php =================================================================== --- trunk/monitor-core/web/graph.d/metric.php (rev 0) +++ trunk/monitor-core/web/graph.d/metric.php 2008-03-13 03:33:57 UTC (rev 1051) @@ -0,0 +1,127 @@ +<?php + +// This report is used for specific metric graphs at the bottom of the cluster_view page. + +/* Pass in by reference! */ +function graph_metric ( &$rrdtool_graph ) { + + global $context, + $default_metric_color, + $hostname, + $jobstart, + $load_color, + $max, + $meta_designator, + $metricname, + $min, + $range, + $rrd_dir, + $size, + $summary, + $value, + $vlabel; + + $rrdtool_graph['height'] += 0 ; //no fudge needed + + switch ($context) { + + case 'host': + + if ($summary) { + $rrdtool_graph['title'] = $hostname; + $prefix = $metricname; + } + else { + $rrdtool_graph['title'] = $metricname; + $prefix = $hostname; + } + + $prefix = $summary ? $metricname : $hostname; + $value = $value > 1000 + ? number_format($value) + : number_format($value,2); + + if ($range == 'job') { + $hrs = intval (-$jobrange / 3600); + $subtitle = "$prefix last ${hrs} (now $value)"; + } else { + $subtitle = "$prefix last $range (now $value)"; + } + + break; + + case 'meta': + $rrdtool_graph['title'] = "$meta_designator ". $rrdtool_graph['title'] ."last $range";; + break; + + case 'grid': + $rrdtool_graph['title'] = "$meta_designator ". $rrdtool_graph['title'] ."last $range"; + break; + + case 'cluster': + $rrdtool_graph['title'] = "$clustername " . $rrdtool_graph['title'] ."last $range"; + break; + + default: + + if ($size == 'small') { + $rrdtool_graph['title'] = $hostname; + } else if ($summary) { + $rrdtool_graph['title'] = $hostname; + } else { + $rrdtool_graph['title'] = $metricname; + } + + break; + + } + + if ($load_color) + $rrdtool_graph['color'] = "BACK#'$load_color'"; + + if (isset($max) && is_numeric($max)) + $rrdtool_graph['upper-limit'] = $max; + + if (isset($min) && is_numeric($min)) + $rrdtool_graph['lower-limit'] = $min; + + if ($vlabel ) { + // We should set $vlabel, even if it isn't used for spacing + // and alignment reasons. This is mostly for aesthetics + $temp_vlabel = trim($vlabel); + $rrdtool_graph['vertical-label'] = strlen($temp_vlabel) + ? $temp_vlabel + : ' '; + } else { + $rrdtool_graph['vertical-label'] = ' '; + } + /* else if ( isset($rrdtool_graph['lower-limit']) or + isset($rrdtool_graph['upper-limit']) ) { + $max = $max > 1000 + ? number_format($max) + : number_format($max,2); + $min = $min = 0 + ? $min + : number_format($min,2); + $rrdtool_graph['vertical-label'] = "'$min - $max'"; + } + else { + $rrdtool_graph['vertical-label'] = ""; + } + */ + + //# the actual graph... + $series = "DEF:sum=$rrd_dir/$metricname.rrd:sum:AVERAGE "; + $series .= "AREA:sum#$default_metric_color:'$subtitle' "; + + if ($jobstart) { + $series .= "VRULE:$jobstart#$jobstart_color "; + } + + $rrdtool_graph['series'] = $series; + + return $rrdtool_graph; + +} + +?> Added: trunk/monitor-core/web/graph.d/network_report.php =================================================================== --- trunk/monitor-core/web/graph.d/network_report.php (rev 0) +++ trunk/monitor-core/web/graph.d/network_report.php 2008-03-13 03:33:57 UTC (rev 1051) @@ -0,0 +1,35 @@ +<?php + + +/* Pass in by reference! */ +function graph_network_report ( &$rrdtool_graph ) { + + global $context, + $hostname, + $mem_cached_color, + $mem_used_color, + $cpu_num_color, + $rrd_dir, + $size; + + $rrdtool_graph['height'] += $size == 'medium' ? 28 : 0 ; + $rrdtool_graph['title'] = 'Network'; + $rrdtool_graph['lower-limit'] = '0'; + $rrdtool_graph['vertical-label'] = 'Bytes/sec'; + $rrdtool_graph['extras'] = '--rigid --base 1024'; + + if ($context == 'host') + $rrdtool_graph['title'] .= " - $hostname"; + + $series = "DEF:'bytes_in'='${rrd_dir}/bytes_in.rrd':'sum':AVERAGE " + ."DEF:'bytes_out'='${rrd_dir}/bytes_out.rrd':'sum':AVERAGE " + ."LINE2:'bytes_in'#$mem_cached_color:'In' " + ."LINE2:'bytes_out'#$mem_used_color:'Out' "; + + $rrdtool_graph['series'] = $series; + + return $rrdtool_graph; + +} + +?> Added: trunk/monitor-core/web/graph.d/packet_report.php =================================================================== --- trunk/monitor-core/web/graph.d/packet_report.php (rev 0) +++ trunk/monitor-core/web/graph.d/packet_report.php 2008-03-13 03:33:57 UTC (rev 1051) @@ -0,0 +1,35 @@ +<?php + + +/* Pass in by reference! */ +function graph_packet_report ( &$rrdtool_graph ) { + + global $context, + $hostname, + $mem_cached_color, + $mem_used_color, + $cpu_num_color, + $rrd_dir, + $size; + + $rrdtool_graph['height'] += $size == 'medium' ? 28 : 0 ; + $rrdtool_graph['title'] = 'Packets'; + $rrdtool_graph['lower-limit'] = '0'; + $rrdtool_graph['vertical-label'] = 'Packets/sec'; + $rrdtool_graph['extras'] = '--rigid --base 1024'; + + if ($context == 'host') + $rrdtool_graph['title'] .= " - $hostname"; + + $series = "DEF:'bytes_in'='${rrd_dir}/pkts_in.rrd':'sum':AVERAGE " + ."DEF:'bytes_out'='${rrd_dir}/pkts_out.rrd':'sum':AVERAGE " + ."LINE2:'bytes_in'#$mem_cached_color:'In' " + ."LINE2:'bytes_out'#$mem_used_color:'Out' "; + + $rrdtool_graph['series'] = $series; + + return $rrdtool_graph; + +} + +?> Added: trunk/monitor-core/web/graph.d/sample_report.php =================================================================== --- trunk/monitor-core/web/graph.d/sample_report.php (rev 0) +++ trunk/monitor-core/web/graph.d/sample_report.php 2008-03-13 03:33:57 UTC (rev 1051) @@ -0,0 +1,142 @@ +<?php + +/* Sample report template */ + +/* Instructions for adding custom reports + +1) Reports should have a primary function named: "<yourtesthere>_report". This + fuction will be called from the graph.php script automatically. + +2) The *_report script should return an array that contains at least the variables + listed below. Several have been pre-populated, and may not need to be changed. + However, you will have to alter at least these: $series, $title, $vertical_label + +3) An array variable is passed to the function in order to make sure that certain + variables are available for use. This is PASSED BY REFERENCE and CAN BE CHANGED + by your report function. + + +NOTE: These are all actually keys in a hash, not specific variables by themselves. + +A full list of variables that will be used: + + + $series (string: holds the meat of the rrdgraph definition) + $title (string: title of the report) + $vertical_label (label for Y-Axis.) + + $start (String: Start time of the graph, can usually be left alone) + $end (String: End time of the graph, also can usually be left alone) + + $width (Strings: Width and height of *graph*, the actual image will be + $height slightly larger due to text elements and padding. These + are normally set automatically, depending on the graph size + chosen from the web UI) + + $upper-limit (Strings: Maximum and minimum Y-value for the graph. RRDTool + $lower-limit normally will auto-scale the Y min and max to fit the + data. You may override this by setting these variables + to specific limits. The default value is a null string, + which will force the auto-scale behavior) + + $color (ARRAY: Sets one or more chart colors. Usually used for setting + the background color of the chart. Valid array keys are + BACK, CANVAS, SADEA, SHADEB, FONT, FRAME and ARROW. Usually, + only BACK is set). + + $extras (Any other custom rrdtool commands can be added to this + this variable. For example, setting a different --base + value or use a --logarithmic scale) + + +For more information and specifics, see the man page for 'rrdgraph'. + + +*/ + + +function graph_sample_report ( &$rrdtool_graph ) { + +/* this is just the cpu_report (from revision r920) as an example, but with extra comments */ + + // pull in a number of global variables, many set in conf.php (such as colors and $rrd_dir), + // but other from elsewhere, such as get_context.php + + global $context, + $cpu_idle_color, + $cpu_nice_color, + $cpu_system_color, + $cpu_user_color, + $cpu_wio_color, + $hostname, + $rrd_dir, + $size; + // + // You *MUST* set at least the 'title', 'vertical-label', and 'series' variables. + // Otherwise, the graph *will not work*. + // + $rrdtool_graph['title'] = 'Sample CPU Report'; + // This will be turned into: + // "Clustername $TITLE last $timerange", so keep it short + $rrdtool_graph['vertical-label'] = 'Sample Percent'; + $rrdtool_graph['height'] += $size == 'medium' ? 28 : 0 ; // Fudge to account for number of lines in the chart legend + $rrdtool_graph['upper-limit'] = '100'; + $rrdtool_graph['lower-limit'] = '0'; + $rrdtool_graph['extras'] = '--rigid'; + + /* Here we actually build the chart series. This is moderately complicated + to show off what you can do. For a simpler example, look at network_report.php */ + if($context != "host" ) { + + /* If we are not in a host context, then we need to calculate the average */ + $series = + "DEF:'num_nodes'='${rrd_dir}/cpu_user.rrd':'num':AVERAGE " + . "DEF:'cpu_user'='${rrd_dir}/cpu_user.rrd':'sum':AVERAGE " + . "CDEF:'ccpu_user'=cpu_user,num_nodes,/ " + . "DEF:'cpu_nice'='${rrd_dir}/cpu_nice.rrd':'sum':AVERAGE " + . "CDEF:'ccpu_nice'=cpu_nice,num_nodes,/ " + . "DEF:'cpu_system'='${rrd_dir}/cpu_system.rrd':'sum':AVERAGE " + . "CDEF:'ccpu_system'=cpu_system,num_nodes,/ " + . "DEF:'cpu_idle'='${rrd_dir}/cpu_idle.rrd':'sum':AVERAGE " + . "CDEF:'ccpu_idle'=cpu_idle,num_nodes,/ " + . "AREA:'ccpu_user'#$cpu_user_color:'User CPU' " + . "STACK:'ccpu_nice'#$cpu_nice_color:'Nice CPU' " + . "STACK:'ccpu_system'#$cpu_system_color:'System CPU' "; + + if (file_exists("$rrd_dir/cpu_wio.rrd")) { + $series .= "DEF:'cpu_wio'='${rrd_dir}/cpu_wio.rrd':'sum':AVERAGE " + ."CDEF:'ccpu_wio'=cpu_wio,num_nodes,/ " + ."STACK:'ccpu_wio'#$cpu_wio_color:'WAIT CPU' "; + } + + $series .= "STACK:'ccpu_idle'#$cpu_idle_color:'Idle CPU' "; + } + // Context is not "host" + else { + + $rrdtool_graph['title'] .= " - $hostname"; + + $series ="DEF:'cpu_user'='${rrd_dir}/cpu_user.rrd':'sum':AVERAGE " + . "DEF:'cpu_nice'='${rrd_dir}/cpu_nice.rrd':'sum':AVERAGE " + . "DEF:'cpu_system'='${rrd_dir}/cpu_system.rrd':'sum':AVERAGE " + . "DEF:'cpu_idle'='${rrd_dir}/cpu_idle.rrd':'sum':AVERAGE " + . "AREA:'cpu_user'#$cpu_user_color:'User CPU' " + . "STACK:'cpu_nice'#$cpu_nice_color:'Nice CPU' " + . "STACK:'cpu_system'#$cpu_system_color:'System CPU' "; + + if (file_exists("$rrd_dir/cpu_wio.rrd")) { + $series .= "DEF:'cpu_wio'='${rrd_dir}/cpu_wio.rrd':'sum':AVERAGE "; + $series .= "STACK:'cpu_wio'#$cpu_wio_color:'WAIT CPU' "; + } + + $series .= "STACK:'cpu_idle'#$cpu_idle_color:'Idle CPU' "; + } + + + // We have everything now, so add it to the array, and go on our way. + $rrdtool_graph['series'] = $series; + + return $rrdtool_graph; +} + +?> Modified: trunk/monitor-core/web/graph.php =================================================================== --- trunk/monitor-core/web/graph.php 2008-03-07 12:30:56 UTC (rev 1050) +++ trunk/monitor-core/web/graph.php 2008-03-13 03:33:57 UTC (rev 1051) @@ -9,64 +9,52 @@ # Graph specific variables # ATD - No need for escapeshellcmd or rawurldecode on $size or $graph. Not used directly in rrdtool calls. -$size = isset($_GET["z"]) && in_array( $_GET[ 'z' ], $graph_sizes_keys ) ? - $_GET["z"] : NULL; +$size = isset($_GET["z"]) && in_array( $_GET[ 'z' ], $graph_sizes_keys ) + ? $_GET["z"] + : NULL; + # ATD - TODO, should encapsulate these custom graphs in some type of container, then this code could check list of defined containers for valid graph labels. -$graph = isset($_GET["g"]) && in_array( $_GET['g'], array( 'cpu_report', 'mem_report', 'load_report', 'network_report', 'packet_report' ) ) ? - $_GET["g"] : NULL; -$grid = isset($_GET["G"]) ? - escapeshellcmd( clean_string( rawurldecode( $_GET["G"] ) ) ) : NULL; -$self = isset($_GET["me"]) ? - escapeshellcmd( clean_string( rawurldecode($_GET["me"] ) ) ) : NULL; -$max = isset($_GET["x"]) ? - clean_number( rawurldecode($_GET["x"] ) ) : NULL; -$min = isset($_GET["n"]) ? - clean_number( rawurldecode($_GET["n"] ) ) : NULL; -$value = isset($_GET["v"]) ? - clean_number( rawurldecode( $_GET["v"] ) ) : NULL; -$load_color = isset($_GET["l"]) && is_valid_hex_color( rawurldecode( $_GET[ 'l' ] ) ) ? - escapeshellcmd( rawurldecode( $_GET["l"] ) ) : NULL; -$vlabel = isset($_GET["vl"]) ? - escapeshellcmd( clean_string( rawurldecode( $_GET["vl"] ) ) ) : NULL; -$sourcetime = isset($_GET["st"]) ? - clean_number( $_GET["st"] ) : NULL; -$summary = isset($_GET["su"]) ? 1 : 0; -$debug = isset( $_GET[ 'debug' ] ) ? 1 : 0; +$graph = isset($_GET["g"]) ? sanitize ( $_GET["g"] ) : NULL; +$grid = isset($_GET["G"]) ? sanitize ( $_GET["G"] ) : NULL; +$self = isset($_GET["me"]) ? sanitize ( $_GET["me"] ) : NULL; +$vlabel = isset($_GET["vl"]) ? sanitize ( $_GET["vl"] ) : NULL; +$value = isset($_GET["v"]) ? sanitize ( $_GET["v"] ) : NULL; -# RFM - Define these variables to avoid "Undefined variable" errors being -# reported in ssl_error_log. -$command = ""; -$extras = ""; -$upper_limit = ""; -$lower_limit = ""; -$background = ""; -$vertical_label = ""; +$max = isset($_GET["x"]) ? clean_number ( sanitize ($_GET["x"] ) ) : NULL; +$min = isset($_GET["n"]) ? clean_number ( sanitize ($_GET["n"] ) ) : NULL; +$sourcetime = isset($_GET["st"]) ? clean_number ( sanitize( $_GET["st"] ) ) : NULL; + +$load_color = isset($_GET["l"]) && is_valid_hex_color( rawurldecode( $_GET[ 'l' ] ) ) + ? sanitize ( $_GET["l"] ) : NULL; +$summary = isset( $_GET["su"] ) ? 1 : 0; +$debug = isset( $_GET['debug'] ) ? 1 : 0; +$command = ''; + # Assumes we have a $start variable (set in get_context.php). # $graph_sizes and $graph_sizes_keys defined in conf.php. Add custom sizes there. -if( in_array( $size, $graph_sizes_keys ) ) { - $height = $graph_sizes[ $size ][ 'height' ]; - $width = $graph_sizes[ $size ][ 'width' ]; - $fudge_0 = $graph_sizes[ $size ][ 'fudge_0' ]; - $fudge_1 = $graph_sizes[ $size ][ 'fudge_1' ]; - $fudge_2 = $graph_sizes[ $size ][ 'fudge_2' ]; -} else { - $height = $graph_sizes[ 'default' ][ 'height' ]; - $width = $graph_sizes[ 'default' ][ 'width' ]; - $fudge_0 = $graph_sizes[ 'default' ][ 'fudge_0' ]; - $fudge_1 = $graph_sizes[ 'default' ][ 'fudge_1' ]; - $fudge_2 = $graph_sizes[ 'default' ][ 'fudge_2' ]; -} +$size = in_array( $size, $graph_sizes_keys ) ? $size : 'default'; + +$height = $graph_sizes[ $size ][ 'height' ]; +$width = $graph_sizes[ $size ][ 'width' ]; +$fudge_0 = $graph_sizes[ $size ][ 'fudge_0' ]; +$fudge_1 = $graph_sizes[ $size ][ 'fudge_1' ]; +$fudge_2 = $graph_sizes[ $size ][ 'fudge_2' ]; + +# +# Since the $command variable is explicitly set to an empty string, above, do we really need +# this check anymore? --jb Jan 2008 +# # This security fix was brought to my attention by Peter Vreugdenhil <pet...@sc...> # Dont want users specifying their own malicious command via GET variables e.g. # http://ganglia.mrcluster.org/graph.php?graph=blob&command=whoami;cat%20/etc/passwd # -if($command) - { - exit(); - } +if($command) { + error_log("Command variable sent, exiting!"); + exit(); +} switch ($context) { @@ -86,225 +74,67 @@ exit; } -$fudge = 0; -if ($graph) /* Canned graph request */ - { - if($graph == "cpu_report") - { - $fudge = $fudge_1; - $style = "CPU"; +# Set some standard defaults that don't need to change much +$rrdtool_graph = array( + 'start' => $start, + 'end' => $end, + 'width' => $width, + 'height' => $height, +); - $upper_limit = "--upper-limit 100 --rigid"; - $lower_limit = "--lower-limit 0"; - $vertical_label = "--vertical-label Percent "; +//error_log("Graph [$graph] in context [$context]"); - if($context != "host" ) - { - /* If we are not in a host context, then we need to calculate the average */ - $series = - "DEF:'num_nodes'='${rrd_dir}/cpu_user.rrd':'num':AVERAGE " - ."DEF:'cpu_user'='${rrd_dir}/cpu_user.rrd':'sum':AVERAGE " - ."CDEF:'ccpu_user'=cpu_user,num_nodes,/ " - ."DEF:'cpu_nice'='${rrd_dir}/cpu_nice.rrd':'sum':AVERAGE " - ."CDEF:'ccpu_nice'=cpu_nice,num_nodes,/ " - ."DEF:'cpu_system'='${rrd_dir}/cpu_system.rrd':'sum':AVERAGE " - ."CDEF:'ccpu_system'=cpu_system,num_nodes,/ " - ."DEF:'cpu_idle'='${rrd_dir}/cpu_idle.rrd':'sum':AVERAGE " - ."CDEF:'ccpu_idle'=cpu_idle,num_nodes,/ " - ."AREA:'ccpu_user'#$cpu_user_color:'User CPU' " - ."STACK:'ccpu_nice'#$cpu_nice_color:'Nice CPU' " - ."STACK:'ccpu_system'#$cpu_system_color:'System CPU' "; - if (file_exists("$rrd_dir/cpu_wio.rrd")) { - $series .= "DEF:'cpu_wio'='${rrd_dir}/cpu_wio.rrd':'sum':AVERAGE " - ."CDEF:'ccpu_wio'=cpu_wio,num_nodes,/ " - ."STACK:'ccpu_wio'#$cpu_wio_color:'WAIT CPU' "; - } - $series .= "STACK:'ccpu_idle'#$cpu_idle_color:'Idle CPU' "; - } - else - { - $series ="DEF:'cpu_user'='${rrd_dir}/cpu_user.rrd':'sum':AVERAGE " - ."DEF:'cpu_nice'='${rrd_dir}/cpu_nice.rrd':'sum':AVERAGE " - ."DEF:'cpu_system'='${rrd_dir}/cpu_system.rrd':'sum':AVERAGE " - ."DEF:'cpu_idle'='${rrd_dir}/cpu_idle.rrd':'sum':AVERAGE " - ."AREA:'cpu_user'#$cpu_user_color:'User CPU' " - ."STACK:'cpu_nice'#$cpu_nice_color:'Nice CPU' " - ."STACK:'cpu_system'#$cpu_system_color:'System CPU' "; - if (file_exists("$rrd_dir/cpu_wio.rrd")) { - $series .= "DEF:'cpu_wio'='${rrd_dir}/cpu_wio.rrd':'sum':AVERAGE " - ."STACK:'cpu_wio'#$cpu_wio_color:'WAIT CPU' "; - } - $series .= "STACK:'cpu_idle'#$cpu_idle_color:'Idle CPU' "; - } - } - else if ($graph == "mem_report") - { - $fudge = $fudge_0; - $style = "Memory"; +/* If we have $graph, then a specific report was requested, such as "network_report" or + * "cpu_report. These graphs usually have some special logic and custom handling required, + * instead of simply plotting a single metric. If $graph is not set, then we are (hopefully), + * plotting a single metric, and will use the commands in the metric.php file. + * + * With modular graphs, we look for a "${graph}.php" file, and if it exists, we + * source it, and call a pre-defined function name. The current scheme for the function + * names is: 'graph_' + <name_of_report>. So a 'cpu_report' would call graph_cpu_report(), + * which would be found in the cpu_report.php file. + * + * These functions take the $rrdtool_graph array as an argument. This variable is + * PASSED BY REFERENCE, and will be modified by the various functions. Each key/value + * pair represents an option/argument, as passed to the rrdtool program. Thus, + * $rrdtool_graph['title'] will refer to the --title option for rrdtool, and pass the array + * value accordingly. + * + * There are two exceptions to: the 'extras' and 'series' keys in $rrdtool_graph. These are + * assigned to $extras and $series respectively, and are treated specially. $series will contain + * the various DEF, CDEF, RULE, LINE, AREA, etc statements that actually plot the charts. The + * rrdtool program requires that this come *last* in the argument string; we make sure that it + * is put in it's proper place. The $extras variable is used for other arguemnts that may not + * fit nicely for other reasons. Complicated requests for --color, or adding --ridgid, for example. + * It is simply a way for the graph writer to add an arbitrary options when calling rrdtool, and to + * forcibly override other settings, since rrdtool will use the last version of an option passed. + * (For example, if you call 'rrdtool' with two --title statements, the second one will be used.) + * + * See $graphdir/sample.php for more documentation, and details on the + * common variables passed and used. + */ - $lower_limit = "--lower-limit 0 --rigid"; - $extras = "--base 1024"; - $vertical_label = "--vertical-label Bytes"; +// No report requested, so use 'metric' +if (!$graph) { + $graph = 'metric'; +} - $series = "DEF:'mem_total'='${rrd_dir}/mem_total.rrd':'sum':AVERAGE " - ."CDEF:'bmem_total'=mem_total,1024,* " - ."DEF:'mem_shared'='${rrd_dir}/mem_shared.rrd':'sum':AVERAGE " - ."CDEF:'bmem_shared'=mem_shared,1024,* " - ."DEF:'mem_free'='${rrd_dir}/mem_free.rrd':'sum':AVERAGE " - ."CDEF:'bmem_free'=mem_free,1024,* " - ."DEF:'mem_cached'='${rrd_dir}/mem_cached.rrd':'sum':AVERAGE " - ."CDEF:'bmem_cached'=mem_cached,1024,* " - ."DEF:'mem_buffers'='${rrd_dir}/mem_buffers.rrd':'sum':AVERAGE " - ."CDEF:'bmem_buffers'=mem_buffers,1024,* " - ."CDEF:'bmem_used'='bmem_total','bmem_shared',-,'bmem_free',-,'bmem_cached',-,'bmem_buffers',- " - ."AREA:'bmem_used'#$mem_used_color:'Memory Used' " - ."STACK:'bmem_shared'#$mem_shared_color:'Memory Shared' " - ."STACK:'bmem_cached'#$mem_cached_color:'Memory Cached' " - ."STACK:'bmem_buffers'#$mem_buffered_color:'Memory Buffered' "; - if (file_exists("$rrd_dir/swap_total.rrd")) { - $series .= "DEF:'swap_total'='${rrd_dir}/swap_total.rrd':'sum':AVERAGE " - ."DEF:'swap_free'='${rrd_dir}/swap_free.rrd':'sum':AVERAGE " - ."CDEF:'bmem_swapped'='swap_total','swap_free',-,1024,* " - ."STACK:'bmem_swapped'#$mem_swapped_color:'Memory Swapped' "; - } - $series .= "LINE2:'bmem_total'#$cpu_num_color:'Total In-Core Memory' "; - } - else if ($graph == "load_report") - { - $fudge = $fudge_2; - $style = "Load"; +$graph_file = "$graphdir/$graph.php"; - $lower_limit = "--lower-limit 0 --rigid"; - $vertical_label = "--vertical-label 'Load/Procs'"; +if ( is_readable($graph_file) ) { + include_once($graph_file); + + $graph_function = "graph_${graph}"; + $graph_function($rrdtool_graph); // Pass by reference call, $rrdtool_graph modified inplace +} +else { + /* Bad stuff happened. */ + error_log("Tried to load graph file [$graph_file], but failed. Invalid graph, aborting."); + exit(); +} + - $series = "DEF:'load_one'='${rrd_dir}/load_one.rrd':'sum':AVERAGE " - ."DEF:'proc_run'='${rrd_dir}/proc_run.rrd':'sum':AVERAGE " - ."DEF:'cpu_num'='${rrd_dir}/cpu_num.rrd':'sum':AVERAGE "; - if( $context != "host" ) - { - $series .="DEF:'num_nodes'='${rrd_dir}/cpu_num.rrd':'num':AVERAGE "; - } - $series .="AREA:'load_one'#$load_one_color:'1-min Load' "; - if( $context != "host" ) - { - $series .= "LINE2:'num_nodes'#$num_nodes_color:'Nodes' "; - } - $series .="LINE2:'cpu_num'#$cpu_num_color:'CPUs' "; - $series .="LINE2:'proc_run'#$proc_run_color:'Running Processes' "; - } - else if ($graph == "network_report") - { - $fudge = $fudge_2; - $style = "Network"; - - $lower_limit = "--lower-limit 0 --rigid"; - $extras = "--base 1024"; - $vertical_label = "--vertical-label 'Bytes/sec'"; - - $series = "DEF:'bytes_in'='${rrd_dir}/bytes_in.rrd':'sum':AVERAGE " - ."DEF:'bytes_out'='${rrd_dir}/bytes_out.rrd':'sum':AVERAGE " - ."LINE2:'bytes_in'#$mem_cached_color:'In' " - ."LINE2:'bytes_out'#$mem_used_color:'Out' "; - } - else if ($graph == "packet_report") - { - $fudge = $fudge_2; - $style = "Packets"; - - $lower_limit = "--lower-limit 0 --rigid"; - $extras = "--base 1024"; - $vertical_label = "--vertical-label 'Packets/sec'"; - - $series = "DEF:'bytes_in'='${rrd_dir}/pkts_in.rrd':'sum':AVERAGE " - ."DEF:'bytes_out'='${rrd_dir}/pkts_out.rrd':'sum':AVERAGE " - ."LINE2:'bytes_in'#$mem_cached_color:'In' " - ."LINE2:'bytes_out'#$mem_used_color:'Out' "; - } - else - { - /* Got a strange value for $graph */ - exit(); - } - } -else - { - /* Custom graph */ - $style = ""; - - $subtitle = $metricname; - if ($context == "host") - { - if ($summary) - $prefix = $metricname; - else - $prefix = $hostname; - - $value = $value>1000 ? number_format($value) : number_format($value, 2); - - if ($range=="job") { - $hrs = intval( -$jobrange / 3600 ); - $subtitle = "$prefix last ${hrs}h (now $value)"; - } - else - $subtitle = "$prefix last $range (now $value)"; - } - - if (is_numeric($max)) - $upper_limit = "--upper-limit '$max' "; - if (is_numeric($min)) - $lower_limit ="--lower-limit '$min' "; - - if ($vlabel) - $vertical_label = "--vertical-label '$vlabel'"; - else if ($upper_limit or $lower_limit) { - if (!$min and !$max) { - $vertical_label = "--vertical-label ' '"; - } else { - $max = $max>100 ? number_format($max) : number_format($max, 2); - $min = $min>0 ? number_format($min,2) : $min; - - $vertical_label ="--vertical-label '$min - $max' "; - } - } - - $rrd_file = "$rrd_dir/$metricname.rrd"; - $series = "DEF:'sum'='$rrd_file':'sum':AVERAGE " - ."AREA:'sum'#$default_metric_color:'$subtitle' "; - if ($jobstart) - $series .= "VRULE:$jobstart#$jobstart_color "; - } - -# Set the graph title. -if($context == "meta") - { - $title = "$self $meta_designator $style last $range"; - } -else if ($context == "grid") - { - $title = "$grid $meta_designator $style last $range"; - } -else if ($context == "cluster") - { - $title = "$clustername $style last $range"; - } -else - { - if ($load_color) - $background = "--color BACK#'$load_color'"; - - if ($size == "small") - $title = $hostname; - else if ($style) - $title = "$hostname $style last $range"; - else if ($summary) - $title = "$hostname"; - else if ($metrictitle) - $title = $metrictitle; - else - $title = $metricname; - } - # Calculate time range. if ($sourcetime) { @@ -314,17 +144,47 @@ } # Fix from Phil Radden, but step is not always 15 anymore. if ($range=="month") - $end = floor($end / 672) * 672; + $rrdtool_graph['end'] = floor($rrdtool_graph['end'] / 672) * 672; -# -# Generate the rrdtool graph command. -# -$fudge += $height; -$command = RRDTOOL . " graph - --start $start --end $end ". - "--width $width --height $fudge $upper_limit $lower_limit ". - "--title '$title' $vertical_label $extras $background ". - $series; +# Tidy up the title a bit +if ($context != 'host') + $rrdtool_graph['title'] = "$clustername " . $rrdtool_graph['title'] . " last $range"; +//-------------------------------------------------------------------------------------- + +// We must have a 'series' value, or this is all for naught +if (!array_key_exists('series', $rrdtool_graph) || !strlen($rrdtool_graph['series']) ) { + error_log("\$series invalid for this graph request ".$_SERVER['PHP_SELF']); + exit(); +} + +$command = RRDTOOL . " graph - "; + +// The order of the other arguments isn't important, except for the +// 'extras' and 'series' values. These two require special handling. +// Otherwise, we just loop over them later, and tack $extras and +// $series onto the end of the command. +foreach ( array_keys ( $rrdtool_graph) as $key) { + + if ( preg_match('/extras|series/', $key )) + continue; + + $value = $rrdtool_graph[$key]; + + if (preg_match('/\W/', $value)) { + //more than alphanumerics in value, so quote it + $value = "'$value'"; + } + $command .= " --$key $value"; +} + +// And finish up with the two variables that need special handling. +// See above for how these are created +$command .= array_key_exists('extras', $rrdtool_graph) ? ' '.$rrdtool_graph['extras'].' ' : ''; +$command .= " $rrdtool_graph[series]"; + +//error_log("Final command: $command"); + # Did we generate a command? Run it. if($command) { @@ -344,4 +204,3 @@ } ?> - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |