#!/usr/bin/php -q This script is only meant to run at the command line."); } /* We are not talking to the browser */ $no_http_headers = true; $dir = dirname(__FILE__); chdir($dir); if (strpos($dir, 'spikekill') !== false) { chdir('../../'); } $using_cacti = false; /* setup defaults */ $debug = FALSE; $dryrun = FALSE; $avgnan = 'avg'; $rrdfile = ""; $std_kills = TRUE; $var_kills = TRUE; $html = FALSE; if ($using_cacti) { $method = read_config_option("spikekill_method"); $numspike = read_config_option("spikekill_number"); $stddev = read_config_option("spikekill_deviations"); $percent = read_config_option("spikekill_percent"); $outliers = read_config_option("spikekill_outliers"); }else{ $method = 1; // Standard Deviation $numspike = 10; $stddev = 10; $percent = 500; $outliers = 5; } /* process calling arguments */ $parms = $_SERVER["argv"]; array_shift($parms); foreach($parms as $parameter) { @list($arg, $value) = @explode("=", $parameter); switch ($arg) { case "--method": case "-M": if ($value == "variance") { $method = 2; }elseif ($value == "stddev") { $method = 1; }else{ echo "FATAL: You must specify either 'stddev' or 'variance' as methods.\n\n"; display_help(); exit; } break; case "--avgnan": case "-A": if ($value == "avg") { $avgnan = "avg"; }elseif ($value == "nan") { $avgnan = "nan"; }else{ echo "FATAL: You must specify either 'avg' or 'nan' as replacement methods.\n\n"; display_help(); exit; } break; case "--rrdfile": case "-R": $rrdfile = $value; if (!file_exists($rrdfile)) { echo "FATAL: File '$rrdfile' does not exist.\n"; exit; } if (!is_writable($rrdfile)) { echo "FATAL: File '$rrdfile' is not writable by this account.\n"; exit; } break; case "--stddev": case "-S": $stddev = $value; if (!is_numeric($stddev) || ($stddev < 1)) { echo "FATAL: Standard Deviation must be a positive integer.\n\n"; display_help(); exit; } break; case "--outliers": case "-O": $outliers = $value; if (!is_numeric($outliers) || ($outliers < 1)) { echo "FATAL: The number of outliers to exlude must be a positive integer.\n\n"; display_help(); exit; } break; case "--percent": case "-P": $percent = $value/100; if (!is_numeric($percent) || ($percent <= 0)) { echo "FATAL: Percent deviation must be a positive floating point number.\n\n"; display_help(); exit; } break; case "--html": $html = TRUE; break; case "-d": case "--debug": $debug = TRUE; break; case "-D": case "--dryrun": $dryrun = TRUE; break; case "--number": case "-n": $numspike = $value; if (!is_numeric($numspike) || ($numspike < 1)) { echo "FATAL: Number of spikes to remove must be a positive integer\n\n"; display_help(); exit; } break; case "-h": case "-v": case "-V": case "--version": case "--help": display_help(); exit; default: print "ERROR: Invalid Parameter " . $parameter . "\n\n"; display_help(); exit; } } /* additional error check */ if ($rrdfile == "") { echo "FATAL: You must specify an RRDfile!\n\n"; display_help(); exit; } /* determine the temporary file name */ $seed = mt_rand(); if ($config["cacti_server_os"] == "win32") { $tempdir = getenv("TEMP"); $xmlfile = $tempdir . "/" . str_replace(".rrd", "", basename($rrdfile)) . ".dump." . $seed; }else{ $tempdir = "/tmp"; $xmlfile = "/tmp/" . str_replace(".rrd", "", basename($rrdfile)) . ".dump." . $seed; } if ($html) { echo ""; } if ($using_cacti) { cacti_log("NOTE: Removing Spikes for '$rrdfile', Method:'$method'", false, "WEBUI"); } /* execute the dump command */ echo ($html ? "\n":"\n"); if ($using_cacti) { shell_exec(read_config_option("path_rrdtool") . " dump $rrdfile > $xmlfile"); }else{ shell_exec("rrdtool dump $rrdfile > $xmlfile"); } /* read the xml file into an array*/ if (file_exists($xmlfile)) { $output = file($xmlfile); /* remove the temp file */ unlink($xmlfile); }else{ if ($using_cacti) { echo ($html ? "\n":"\n"); }else{ echo ($html ? "\n":"\n"); } exit; } /* process the xml file and remove all comments */ $output = removeComments($output); /* Read all the rra's ds values and obtain the following pieces of information from each rra archive. * numsamples - The number of 'valid' non-nan samples * sumofsamples - The sum of all 'valid' samples. * average - The average of all samples * standard_deviation - The standard deviation of all samples * max_value - The maximum value of all samples * min_value - The minimum value of all samples * max_cutoff - Any value above this value will be set to the average. * min_cutoff - Any value lower than this value will be set to the average. This will end up being a n-dimensional array as follows: rra[x][ds#]['totalsamples']; rra[x][ds#]['numsamples']; rra[x][ds#]['sumofsamples']; rra[x][ds#]['average']; rra[x][ds#]['stddev']; rra[x][ds#]['max_value']; rra[x][ds#]['min_value']; rra[x][ds#]['max_cutoff']; rra[x][ds#]['min_cutoff']; There will also be a secondary array created with the actual samples. This array will be used to calculate the standard deviation of the sample set. samples[rra_num][ds_num][]; Also track the min and max value for each ds and store it into the two arrays: ds_min[ds#], ds_max[ds#]. The we don't need to know the type of rra, only it's number for this analysis the same applies for the ds' as well. */ $rra = array(); $rra_cf = array(); $rra_pdp = array(); $rra_num = 0; $ds_num = 0; $total_kills = 0; $in_rra = false; $in_db = false; $ds_min = array(); $ds_max = array(); $ds_name = array(); /* perform a first pass on the array and do the following: 1) Get the number of good samples per ds 2) Get the sum of the samples per ds 3) Get the max and min values for all samples 4) Build both the rra and sample arrays 5) Get each ds' min and max values */ if (sizeof($output)) { foreach($output as $line) { if (substr_count($line, "")) { $linearray = explode("", $line); /* discard the row */ array_shift($linearray); $ds_num = 0; foreach($linearray as $dsvalue) { /* peel off garbage */ $dsvalue = trim(str_replace("", "", str_replace("", "", $dsvalue))); if (strtolower($dsvalue) != "nan") { if (!isset($rra[$rra_num][$ds_num]["numsamples"])) { $rra[$rra_num][$ds_num]["numsamples"] = 1; }else{ $rra[$rra_num][$ds_num]["numsamples"]++; } if (!isset($rra[$rra_num][$ds_num]["sumofsamples"])) { $rra[$rra_num][$ds_num]["sumofsamples"] = $dsvalue; }else{ $rra[$rra_num][$ds_num]["sumofsamples"] += $dsvalue; } if (!isset($rra[$rra_num][$ds_num]["max_value"])) { $rra[$rra_num][$ds_num]["max_value"] = $dsvalue; }else if ($dsvalue > $rra[$rra_num][$ds_num]["max_value"]) { $rra[$rra_num][$ds_num]["max_value"] = $dsvalue; } if (!isset($rra[$rra_num][$ds_num]["min_value"])) { $rra[$rra_num][$ds_num]["min_value"] = $dsvalue; }else if ($dsvalue < $rra[$rra_num][$ds_num]["min_value"]) { $rra[$rra_num][$ds_num]["min_value"] = $dsvalue; } /* store the sample for standard deviation calculation */ $samples[$rra_num][$ds_num][] = $dsvalue; } if (!isset($rra[$rra_num][$ds_num]["totalsamples"])) { $rra[$rra_num][$ds_num]["totalsamples"] = 1; }else{ $rra[$rra_num][$ds_num]["totalsamples"]++; } $ds_num++; } } elseif (substr_count($line, "")) { $in_rra = true; } elseif (substr_count($line, "")) { $ds_min[] = trim(str_replace("", "", str_replace("", "", trim($line)))); } elseif (substr_count($line, "")) { $ds_max[] = trim(str_replace("", "", str_replace("", "", trim($line)))); } elseif (substr_count($line, "")) { $ds_name[] = trim(str_replace("", "", str_replace("", "", trim($line)))); } elseif (substr_count($line, "")) { $rra_cf[] = trim(str_replace("", "", str_replace("", "", trim($line)))); } elseif (substr_count($line, "")) { $rra_pdp[] = trim(str_replace("", "", str_replace("", "", trim($line)))); } elseif (substr_count($line, "")) { $in_rra = false; $rra_num++; } elseif (substr_count($line, "")) { $step = trim(str_replace("", "", str_replace("", "", trim($line)))); } } } /* For all the samples determine the average with the outliers removed */ calculateVarianceAverages($rra, $samples); /* Now scan the rra array and the samples array and calculate the following 1) The standard deviation of all samples 2) The average of all samples per ds 3) The max and min cutoffs of all samples 4) The number of kills in each ds based upon the thresholds */ echo ($html ? "\n":"\n"); calculateOverallStatistics($rra, $samples); /* debugging and/or status report */ if ($debug || $dryrun) { outputStatistics($rra); } /* create an output array */ if ($method == 1) { /* standard deviation subroutine */ if ($std_kills) { if (!$dryrun) { $new_output = updateXML($output, $rra); } }else{ echo ($html ? "\n":"\n"); } }else{ /* variance subroutine */ if ($var_kills) { if (!$dryrun) { $new_output = updateXML($output, $rra); } }else{ echo ($html ? "\n":"\n"); } } /* finally update the file XML file and Reprocess the RRDfile */ if (!$dryrun) { if ($total_kills) { if (writeXMLFile($new_output, $xmlfile)) { if (backupRRDFile($rrdfile)) { createRRDFileFromXML($xmlfile, $rrdfile); }else{ echo ($html ? "\n":"\n"); } }else{ echo ($html ? "\n":"\n"); } } }else{ echo ($html ? "\n":"\n"); } if ($html) { echo "
":"") . "NOTE: Creating XML file '$xmlfile' from '$rrdfile'" . ($html ? "
":"") . "FATAL: RRDtool Command Failed. Please verify that the RRDtool path is valid in Settings->Paths!" . ($html ? "
":"") . "FATAL: RRDtool Command Failed. Please insure RRDtool is in your path!" . ($html ? "
":"") . "NOTE: Searching for Spikes in XML file '$xmlfile'" . ($html ? "
":"") . "NOTE: NO Standard Deviation Spikes found in '$rrdfile'" . ($html ? "
":"") . "NOTE: NO Variance Spikes found in '$rrdfile'" . ($html ? "
":"") . "FATAL: Unable to backup '$rrdfile'" . ($html ? "
":"") . "FATAL: Unable to write XML file '$xmlfile'" . ($html ? "
":"") . "NOTE: Dryrun requested. No updates performed" . ($html ? "
"; } /* All Functions */ function createRRDFileFromXML($xmlfile, $rrdfile) { global $using_cacti, $html; /* execute the dump command */ echo ($html ? "":"") . "NOTE: Re-Importing '$xmlfile' to '$rrdfile'" . ($html ? "\n":"\n"); if ($using_cacti) { $response = shell_exec(read_config_option("path_rrdtool") . " restore -f -r $xmlfile $rrdfile"); }else{ $response = shell_exec("rrdtool restore -f -r $xmlfile $rrdfile"); } if (strlen($response)) echo ($html ? "":"") . $response . ($html ? "\n":"\n"); } function writeXMLFile($output, $xmlfile) { return file_put_contents($xmlfile, $output); } function backupRRDFile($rrdfile) { global $using_cacti, $tempdir, $seed, $html; if ($using_cacti) { $backupdir = read_config_option("spikekill_backupdir"); if ($backupdir == "") { $backupdir = $tempdir; } }else{ $backupdir = $tempdir; } if (file_exists($backupdir . "/" . basename($rrdfile))) { $newfile = basename($rrdfile) . "." . $seed; }else{ $newfile = basename($rrdfile); } echo ($html ? "":"") . "NOTE: Backing Up '$rrdfile' to '" . $backupdir . "/" . $newfile . "'" . ($html ? "\n":"\n"); return copy($rrdfile, $backupdir . "/" . $newfile); } function calculateVarianceAverages(&$rra, &$samples) { global $outliers; if (sizeof($samples)) { foreach($samples as $rra_num => $dses) { if (sizeof($dses)) { foreach($dses as $ds_num => $ds) { if (sizeof($ds) < $outliers * 3) { $rra[$rra_num][$ds_num]["variance_avg"] = "NAN"; }else{ rsort($ds, SORT_NUMERIC); $ds = array_slice($ds, $outliers); sort($ds, SORT_NUMERIC); $ds = array_slice($ds, $outliers); $rra[$rra_num][$ds_num]["variance_avg"] = array_sum($ds) / sizeof($ds); } } } } } } function calculateOverallStatistics(&$rra, &$samples) { global $percent, $stddev, $ds_min, $ds_max, $var_kills, $std_kills; $rra_num = 0; if (sizeof($rra)) { foreach($rra as $dses) { $ds_num = 0; if (sizeof($dses)) { foreach($dses as $ds) { if (isset($samples[$rra_num][$ds_num])) { $rra[$rra_num][$ds_num]["standard_deviation"] = standard_deviation($samples[$rra_num][$ds_num]); if ($rra[$rra_num][$ds_num]["standard_deviation"] == "NAN") { $rra[$rra_num][$ds_num]["standard_deviation"] = 0; } $rra[$rra_num][$ds_num]["average"] = $rra[$rra_num][$ds_num]["sumofsamples"] / $rra[$rra_num][$ds_num]["numsamples"]; $rra[$rra_num][$ds_num]["min_cutoff"] = $rra[$rra_num][$ds_num]["average"] - ($stddev * $rra[$rra_num][$ds_num]["standard_deviation"]); if ($rra[$rra_num][$ds_num]["min_cutoff"] < $ds_min[$ds_num]) { $rra[$rra_num][$ds_num]["min_cutoff"] = $ds_min[$ds_num]; } $rra[$rra_num][$ds_num]["max_cutoff"] = $rra[$rra_num][$ds_num]["average"] + ($stddev * $rra[$rra_num][$ds_num]["standard_deviation"]); if ($rra[$rra_num][$ds_num]["max_cutoff"] > $ds_max[$ds_num]) { $rra[$rra_num][$ds_num]["max_cutoff"] = $ds_max[$ds_num]; } $rra[$rra_num][$ds_num]["numnksamples"] = 0; $rra[$rra_num][$ds_num]["sumnksamples"] = 0; $rra[$rra_num][$ds_num]["avgnksamples"] = 0; /* go through values and find cutoffs */ $rra[$rra_num][$ds_num]["stddev_killed"] = 0; $rra[$rra_num][$ds_num]["variance_killed"] = 0; if (sizeof($samples[$rra_num][$ds_num])) { foreach($samples[$rra_num][$ds_num] as $sample) { if (($sample > $rra[$rra_num][$ds_num]["max_cutoff"]) || ($sample < $rra[$rra_num][$ds_num]["min_cutoff"])) { debug(sprintf("Std Kill: Value '%.4e', StandardDev '%.4e', StdDevLimit '%.4e'", $sample, $rra[$rra_num][$ds_num]["standard_deviation"], ($rra[$rra_num][$ds_num]["max_cutoff"] * (1+$percent)))); $rra[$rra_num][$ds_num]["stddev_killed"]++; $std_kills = true; }else{ $rra[$rra_num][$ds_num]["numnksamples"]++; $rra[$rra_num][$ds_num]["sumnksamples"] += $sample; } if ($rra[$rra_num][$ds_num]["variance_avg"] == "NAN") { /* not enought samples to calculate */ }else if ($sample > ($rra[$rra_num][$ds_num]["variance_avg"] * (1+$percent))) { /* kill based upon variance */ debug(sprintf("Var Kill: Value '%.4e', VarianceDev '%.4e', VarianceLimit '%.4e'", $sample, $rra[$rra_num][$ds_num]["variance_avg"], ($rra[$rra_num][$ds_num]["variance_avg"] * (1+$percent)))); $rra[$rra_num][$ds_num]["variance_killed"]++; $var_kills = true; } } } if ($rra[$rra_num][$ds_num]["numnksamples"] > 0) { $rra[$rra_num][$ds_num]["avgnksamples"] = $rra[$rra_num][$ds_num]["sumnksamples"] / $rra[$rra_num][$ds_num]["numnksamples"]; } }else{ $rra[$rra_num][$ds_num]["standard_deviation"] = "N/A"; $rra[$rra_num][$ds_num]["average"] = "N/A"; $rra[$rra_num][$ds_num]["min_cutoff"] = "N/A"; $rra[$rra_num][$ds_num]["max_cutoff"] = "N/A"; $rra[$rra_num][$ds_num]["numnksamples"] = "N/A"; $rra[$rra_num][$ds_num]["sumnksamples"] = "N/A"; $rra[$rra_num][$ds_num]["avgnksamples"] = "N/A"; $rra[$rra_num][$ds_num]["stddev_killed"] = "N/A"; $rra[$rra_num][$ds_num]["variance_killed"] = "N/A"; $rra[$rra_num][$ds_num]["stddev_killed"] = "N/A"; $rra[$rra_num][$ds_num]["numnksamples"] = "N/A"; $rra[$rra_num][$ds_num]["sumnksamples"] = "N/A"; $rra[$rra_num][$ds_num]["variance_killed"] = "N/A"; $rra[$rra_num][$ds_num]["avgnksamples"] = "N/A"; } $ds_num++; } } $rra_num++; } } } function outputStatistics($rra) { global $rra_cf, $rra_name, $ds_name, $rra_pdp, $html; if (sizeof($rra)) { if (!$html) { echo "\n"; printf("%10s %16s %10s %7s %7s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s\n", "Size", "DataSource", "CF", "Samples", "NonNan", "Avg", "StdDev", "MaxValue", "MinValue", "MaxStdDev", "MinStdDev", "StdKilled", "VarKilled", "StdDevAvg", "VarAvg"); printf("%10s %16s %10s %7s %7s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s\n", "----------", "---------------", "----------", "-------", "-------", "----------", "----------", "----------", "----------", "----------", "----------", "----------", "----------", "----------", "----------"); foreach($rra as $rra_key => $dses) { if (sizeof($dses)) { foreach($dses as $dskey => $ds) { printf("%10s %16s %10s %7s %7s " . ($ds["average"] < 1E6 ? "%10s ":"%10.4e ") . ($ds["standard_deviation"] < 1E6 ? "%10s ":"%10.4e ") . (isset($ds["max_value"]) ? ($ds["max_value"] < 1E6 ? "%10s ":"%10.4e ") : "%10s ") . (isset($ds["min_value"]) ? ($ds["min_value"] < 1E6 ? "%10s ":"%10.4e ") : "%10s ") . (isset($ds["max_cutoff"]) ? ($ds["max_cutoff"] < 1E6 ? "%10s ":"%10.4e ") : "%10s ") . (isset($ds["min_cutoff"]) ? ($ds["min_cutoff"] < 1E6 ? "%10s ":"%10.4e ") : "%10s ") . "%10s %10s " . (isset($ds["avgnksampled"]) ? ($ds["avgnksamples"] < 1E6 ? "%10s ":"%10.4e ") : "%10s ") . (isset($ds["variance_avg"]) ? ($ds["variance_avg"] < 1E6 ? "%10s ":"%10.4e ") : "%10s ") . "\n", displayTime($rra_pdp[$rra_key]), $ds_name[$dskey], $rra_cf[$rra_key], $ds["totalsamples"], (isset($ds["numsamples"]) ? $ds["numsamples"] : "0"), ($ds["average"] != "N/A" ? round($ds["average"],2) : $ds["average"]), ($ds["standard_deviation"] != "N/A" ? round($ds["standard_deviation"],2) : $ds["standard_deviation"]), (isset($ds["max_value"]) ? round($ds["max_value"],2) : "N/A"), (isset($ds["min_value"]) ? round($ds["min_value"],2) : "N/A"), ($ds["max_cutoff"] != "N/A" ? round($ds["max_cutoff"],2) : $ds["max_cutoff"]), ($ds["min_cutoff"] != "N/A" ? round($ds["min_cutoff"],2) : $ds["min_cutoff"]), $ds["stddev_killed"], $ds["variance_killed"], ($ds["avgnksamples"] != "N/A" ? round($ds["avgnksamples"],2) : $ds["avgnksamples"]), (isset($ds["variance_avg"]) ? round($ds["variance_avg"],2) : "N/A")); } } } echo "\n"; }else{ printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", "Size", "DataSource", "CF", "Samples", "NonNan", "Avg", "StdDev", "MaxValue", "MinValue", "MaxStdDev", "MinStdDev", "StdKilled", "VarKilled", "StdDevAvg", "VarAvg"); foreach($rra as $rra_key => $dses) { if (sizeof($dses)) { foreach($dses as $dskey => $ds) { printf("%s%s%s%s%s" . ($ds["average"] < 1E6 ? "%s":"%.4e") . ($ds["standard_deviation"] < 1E6 ? "%s":"%.4e") . (isset($ds["max_value"]) ? ($ds["max_value"] < 1E6 ? "%s":"%.4e") : "%s") . (isset($ds["min_value"]) ? ($ds["min_value"] < 1E6 ? "%s":"%.4e") : "%s") . (isset($ds["max_cutoff"]) ? ($ds["max_cutoff"] < 1E6 ? "%s":"%.4e") : "%s") . (isset($ds["min_cutoff"]) ? ($ds["min_cutoff"] < 1E6 ? "%s":"%.4e") : "%s") . "%s%s" . (isset($ds["avgnksampled"]) ? ($ds["avgnksamples"] < 1E6 ? "%s":"%.4e") : "%s") . (isset($ds["variance_avg"]) ? ($ds["variance_avg"] < 1E6 ? "%s\n":"%.4e\n") : "%s\n") . "\n", displayTime($rra_pdp[$rra_key]), $ds_name[$dskey], $rra_cf[$rra_key], $ds["totalsamples"], (isset($ds["numsamples"]) ? $ds["numsamples"] : "0"), ($ds["average"] != "N/A" ? round($ds["average"],2) : $ds["average"]), ($ds["standard_deviation"] != "N/A" ? round($ds["standard_deviation"],2) : $ds["standard_deviation"]), (isset($ds["max_value"]) ? round($ds["max_value"],2) : "N/A"), (isset($ds["min_value"]) ? round($ds["min_value"],2) : "N/A"), ($ds["max_cutoff"] != "N/A" ? round($ds["max_cutoff"],2) : $ds["max_cutoff"]), ($ds["min_cutoff"] != "N/A" ? round($ds["min_cutoff"],2) : $ds["min_cutoff"]), $ds["stddev_killed"], $ds["variance_killed"], ($ds["avgnksamples"] != "N/A" ? round($ds["avgnksamples"],2) : $ds["avgnksamples"]), (isset($ds["variance_avg"]) ? round($ds["variance_avg"],2) : "N/A")); } } } } } } function updateXML(&$output, &$rra) { global $numspike, $percent, $avgnan, $method, $total_kills; $new_array = array(); /* variance subroutine */ $rra_num = 0; $ds_num = 0; $kills = 0; if (sizeof($output)) { foreach($output as $line) { if (substr_count($line, "")) { $linearray = explode("", $line); /* discard the row */ array_shift($linearray); /* initialize variables */ $ds_num = 0; $out_row = ""; foreach($linearray as $dsvalue) { /* peel off garbage */ $dsvalue = trim(str_replace("", "", str_replace("", "", $dsvalue))); if (strtolower($dsvalue) == "nan") { /* do nothing, it's a NaN */ }else{ if ($method == 2) { if ($dsvalue > (1+$percent)*$rra[$rra_num][$ds_num]["variance_avg"]) { if ($kills < $numspike) { if ($avgnan == "avg") { $dsvalue = $rra[$rra_num][$ds_num]["variance_avg"]; }else{ $dsvalue = "NaN"; } $kills++; $total_kills++; } } }else{ if (($dsvalue > $rra[$rra_num][$ds_num]["max_cutoff"]) || ($dsvalue < $rra[$rra_num][$ds_num]["min_cutoff"])) { if ($kills < $numspike) { if ($avgnan == "avg") { $dsvalue = $rra[$rra_num][$ds_num]["average"]; }else{ $dsvalue = "NaN"; } $kills++; $total_kills++; } } } } $out_row .= " " . $dsvalue . ""; $ds_num++; } $out_row .= ""; $new_array[] = $out_row; }else{ if (substr_count($line, "")) { $ds_minmax = array(); $rra_num++; $kills = 0; }else if (substr_count($line, "")) { $ds_num++; $kills = 0; } $new_array[] = $line; } } } return $new_array; } function removeComments(&$output) { if (sizeof($output)) { foreach($output as $line) { $line = trim($line); if ($line == "") { continue; }else{ /* is there a comment, remove it */ $comment_start = strpos($line, ""); if ($comment_start == 0) { $line = trim(substr($line, $comment_end+3)); }else{ $line = trim(substr($line,0,$comment_start-1) . substr($line,$comment_end+3)); } } if ($line != "") { $new_array[] = $line; } } } /* transfer the new array back to the original array */ return $new_array; } } function displayTime($pdp) { global $step; $total_time = $pdp * $step; // seconds if ($total_time < 60) { return $total_time . " secs"; }else{ $total_time = $total_time / 60; if ($total_time < 60) { return $total_time . " mins"; }else{ $total_time = $total_time / 60; if ($total_time < 24) { return $total_time . " hours"; }else{ $total_time = $total_time / 24; return $total_time . " days"; } } } } function debug($string) { global $debug; if ($debug) { echo "DEBUG: " . $string . "\n"; } } function standard_deviation($samples) { $sample_count = count($samples); $sample_square = array(); for ($current_sample = 0; $sample_count > $current_sample; ++$current_sample) { $sample_square[$current_sample] = pow($samples[$current_sample], 2); } return sqrt(array_sum($sample_square) / $sample_count - pow((array_sum($samples) / $sample_count), 2)); } /* display_help - displays the usage of the function */ function display_help () { global $using_cacti; if ($using_cacti) { $version = spikekill_version(); }else{ $version = "v1.0"; } echo "Cacti Spike Remover " . ($using_cacti ? "v" . $version["version"] : $version) . ", Copyright 2009, The Cacti Group, Inc.\n\n"; echo "Usage:\n"; echo "removespikes.php -R|--rrdfile=rrdfile [-M|--method=stddev] [-A|--avgnan] [-S|--stddev=N]\n"; echo " [-P|--percent=N] [-N|--number=N] [-D|--dryrun] [-d|--debug] [-h|--help|-v|-V|--version]\n\n"; echo "The RRDfile input parameter is mandatory. If no other input parameters are specified the defaults\n"; echo "are taken from the Spikekill Plugin settings.\n\n"; echo "-M|--method - The spike removal method to use. Options are 'stddev'|'variance'\n"; echo "-A|--avgnan - The spike replacement method to use. Options are 'avg'|'nan'\n"; echo "-S|--stddev - The number of standard deviations +/- allowed\n"; echo "-P|--percent - The sample to sample percentage variation allowed\n"; echo "-N|--number - The maximum number of spikes to remove from the RRDfile\n"; echo "-D|--dryrun - If specified, the RRDfile will not be changed. Instead a summary of\n"; echo " changes that would have been performed will be issued.\n\n"; echo "The remainder of arguments are informational\n"; echo "-d|--debug - Display verbose output during execution\n"; echo "-v -V --version - Display this help message\n"; echo "-h --help - display this help message\n"; }