Call us Today +49 7543 609337-0
Log In

Today we’re going to add a new functionality to Cacti to support gradients within the Cacti graphs supporting AREA graph items.
This involves editing the lib/rrd.php file so the changes will be gone after an update of Cacti. Nevertheless it’s easy to re-add as the file doesn’t change much between version upgrades.

Requirements

In order for this to work you will have to use a rrdtool version > 1.0

Adding The Gradient Support

In order to add the gradient support, we are going to add some new functions to the rrd.php file. The first function will allow the addition of gradients for AREA items while the second function will allow us to define the gradient end color as a brighter or darkened version of the original color being used wihtin the graph template.

The gradient Function

This function is based on a function of the PNG4Nagios project. The original version is available here and released under the GPLv2.

function gradient($vname=FALSE, $start_color='#0000a0', $end_color='#f0f0f0', $label=FALSE, $steps=20, $lower=FALSE, $alpha='FF'){
        $label = preg_replace("/'/","",$label);
        if(preg_match('/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i',$start_color,$matches)){
            $r1=hexdec($matches[1]);
            $g1=hexdec($matches[2]);
            $b1=hexdec($matches[3]);
        }
        if(preg_match('/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i',$end_color,$matches)){
            $r2=hexdec($matches[1]);
            $g2=hexdec($matches[2]);
            $b2=hexdec($matches[3]);
        }
        $diff_r=$r2-$r1;
        $diff_g=$g2-$g1;
        $diff_b=$b2-$b1;
        $spline =  "";
        $spline_vname = "var".substr(sha1(rand()),1,4);
        $vnamet = $vname.substr(sha1(rand()),1,4);
        if(preg_match('/^([0-9]{1,3})%$/', $lower, $matches)){
            $lower   = $matches[1];
            $spline .= sprintf("CDEF:%sminimum=%s,100,/,%d,* ".RRD_NL, $vnamet, $vname, $lower);
        }elseif(preg_match('/^([0-9]+)$/', $lower, $matches)){
            $lower   = $matches[1];
            $spline .= sprintf("CDEF:%sminimum=%s,%d,- ".RRD_NL, $vnamet, $vname, $lower);
        }else{
            $lower   = 0;
            $spline .= sprintf("CDEF:%sminimum=%s,%s,- ".RRD_NL, $vnamet, $vname, $vname);
        }
        for ($i=$steps; $i>0; $i--){
            $spline .=  sprintf("CDEF:%s%d=%s,%sminimum,-,%d,/,%d,*,%sminimum,+ ".RRD_NL,$spline_vname,$i,$vname,$vnamet,$steps,$i,$vnamet);
        }
        // We don't use alpha blending for the area right now
        $alpha = 'ff';
        for ($i=$steps; $i>0; $i--){
            $factor=$i / $steps;
            $r=round($r1 + $diff_r * $factor);
            $g=round($g1 + $diff_g * $factor);
            $b=round($b1 + $diff_b * $factor);
            if (($i==$steps) and ($label!=FALSE) and (strlen($label)>2) ){
                $spline .=  sprintf("AREA:%s%d#%02X%02X%02X%s:\"%s\" ".RRD_NL, $spline_vname,$i,$r,$g,$b,$alpha,$label);
            }else{
                $spline .=  sprintf("AREA:%s%d#%02X%02X%02X%s ".RRD_NL, $spline_vname,$i,$r,$g,$b,$alpha);
            }
        }
        $spline .=  sprintf("AREA:%s%d#%02X%02X%02X%s ".RRD_NL, $spline_vname,$steps,$r2,$g2,$b2,'00',$label);
        return $spline;
    }

 

The colourBrightness Function

The following function is based on the CSSColor project. The original version of the code is available here, the project itself is availabl from this site. The project is released under the GPLv2.

function colourBrightness($hex, $percent) {
        // Work out if hash given
        $hash = '';
        if (stristr($hex,'#')) {
                $hex = str_replace('#','',$hex);
                $hash = '#';
        }
        /// HEX TO RGB
        $rgb = array(hexdec(substr($hex,0,2)), hexdec(substr($hex,2,2)), hexdec(substr($hex,4,2)));
        //// CALCULATE
        for ($i=0; $i<3; $i++) {                 // See if brighter or darker                 
                if ($percent > 0) {
                        // Lighter
                        $rgb[$i] = round($rgb[$i] * $percent) + round(255 * (1-$percent));
                } else {
                        // Darker
                        $positivePercent = $percent - ($percent*2);
                        $rgb[$i] = round($rgb[$i] * (1-$positivePercent)); // round($rgb[$i] * (1-$positivePercent));
                }
                // In case rounding up causes us to go to 256
                if ($rgb[$i] > 255) {
                        $rgb[$i] = 255;
                }
        }
        //// RBG to Hex
        $hex = '';
        for($i=0; $i < 3; $i++) {
                // Convert the decimal digit to hex
                $hexDigit = dechex($rgb[$i]);
                // Add a leading zero if necessary
                if(strlen($hexDigit) == 1) {
                $hexDigit = "0" . $hexDigit;
                }
                // Append to the hex string
                $hex .= $hexDigit;
        }
        return $hash.$hex;
}

Both of these functions need to be added at the bottom of the following file:

/path/to/cacti/lib/rrd.php

Now we also need to change a few lines for the rrd graph creation.

Cacti 0.8.x

The following code needs to be edited/changed at around line 1375 of the same file:

File: lib/rrd.php, Line: 1375

if (preg_match("/^AREA$/", $graph_item_types{$graph_item["graph_type_id"]})) {
$graph_item_stack_type = $graph_item_types{$graph_item["graph_type_id"]};
$graph_variables["text_format"][$graph_item_id] = str_replace(":", "\:", $graph_variables["text_format"][$graph_item_id]); /* escape colons */
// $txt_graph_items .= $graph_item_types{$graph_item["graph_type_id"]} . ":" . $data_source_name . $graph_item_color_code . ":" . cacti_escapeshellarg($graph_variables["text_format"][$graph_item_id] . $hardreturn[$graph_item_id]) . " ";
$end_color = colourBrightness("#" . $graph_item["hex"],-0.4); // End color is a 40% (0.4) darkened (negative number) version of the original color
$txt_graph_items .= gradient($data_source_name,$graph_item_color_code,$end_color.$graph_item["alpha"],cacti_escapeshellarg($graph_variables["text_format"][$graph_item_id] . $hardreturn[$graph_item_id]),20,false,$graph_item["alpha"]);
$need_rrd_nl = FALSE;
}elseif (preg_match("/^LINE[123]$/", $graph_item_types{$graph_item["graph_type_id"]})) {
$graph_item_stack_type = $graph_item_types{$graph_item["graph_type_id"]};
$graph_variables["text_format"][$graph_item_id] = str_replace(":", "\:", $graph_variables["text_format"][$graph_item_id]); /* escape colons */
$txt_graph_items .= $graph_item_types{$graph_item["graph_type_id"]} . ":" . $data_source_name . $graph_item_color_code . ":" . cacti_escapeshellarg($graph_variables["text_format"][$graph_item_id] . $hardreturn[$graph_item_id]) . " ";

}elseif ($graph_item_types{$graph_item["graph_type_id"]} == "STACK") {

Cacti 1.x.x

The following code needs to be edited/changed at around line 1982 of the same file:

File: lib/rrd.php, Line: 1982

case GRAPH_ITEM_TYPE_AREA:
 $graph_variables['text_format'][$graph_item_id] = rrdtool_escape_string(htmlspecialchars($graph_variables['text_format'][$graph_item_id] != '' ? str_pad($graph_variables['text_format'][$graph_item_id], $pad_number):'', ENT_QUOTES, 'UTF-8'));
 $end_color = colourBrightness("#" . $graph_item["hex"],-0.4); // End color is a 40% (0.4) darkened (negative number) version of the original color
 $txt_graph_items .= gradient($data_source_name,$graph_item_color_code,$end_color.$graph_item["alpha"],cacti_escapeshellarg($graph_variables["text_format"][$graph_item_id] . $hardreturn[$graph_item_id]),20,false,$graph_item["alpha"]);
// $txt_graph_items .= $graph_item_types[$graph_item['graph_type_id']] . ':' . $data_source_name . $graph_item_color_code . ':' . cacti_escapeshellarg($graph_variables['text_format'][$graph_item_id] . $hardreturn[$graph_item_id]) . ' ';

if ($graph_item['shift'] == CHECKED && $graph_item['value'] > 0) { # create a SHIFT statement
 $txt_graph_items .= RRD_NL . 'SHIFT:' . $data_source_name . ':' . $graph_item['value'];
 }

break;

Now look at any of the graphs and enjoy the gradient appearance !

Downloads

Download Link Cacti Version
cacti_gradient_088b 0.8.8b
cacti_gradient_1.x.x 1.1.25

 

Sample Graphs

 

3 thoughts on “Gradient support for Cacti Graphs”

Leave a Reply