Created
May 14, 2023 18:38
-
-
Save miken32/832d8bfb8aad7391b08d28e7440c96b9 to your computer and use it in GitHub Desktop.
PHP parsing for Nagios/Icinga threshold values
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Return a normalized threshold value (floats are converted to ints) | |
* | |
* @param string $thresh The threshold specification | |
* @return string The normalized threshold | |
* @throws Exception In case of invalid format | |
*/ | |
function parse_threshold(string $thresh): string | |
{ | |
if (preg_match("/^[0-9]+$/", $thresh)) { | |
verbose("Threshold $thresh is an integer", 3); | |
return $thresh; | |
} | |
if (preg_match("/^([0-9]+)\.[0-9]+$/", $thresh, $matches)) { | |
verbose("Threshold $thresh is a float, returning integer", 3); | |
return $matches[1]; | |
} | |
if (preg_match("/^(@?(?:[0-9]+|~))(?:\\.[0-9]+)?(?::(?:([0-9]+)(?:\\.[0-9]+)?)?)?$/", $thresh, $matches)) { | |
verbose("Threshold $thresh is a range '$matches[1]' to '$matches[2]'", 3); | |
if (count($matches) !== 3) { | |
return $matches[1]; | |
} | |
if ($matches[1] === "~" || $matches[1] < $matches[2]) { | |
return "$matches[1]:$matches[2]"; | |
} | |
} | |
throw new Exception("Invalid threshold format $thresh"); | |
} | |
/** | |
* Checks to see if a value should trigger an alert based on a given threshold | |
* The threshold specification looks like [@][start:][end] | |
* 'start:end' means to alert if value is *outside* of the range | |
* 'start:' means end is infinity, effectively alert if below start | |
* 'end' means start is negative infinity, effectively alert if value is above end | |
* '~:end' is the same as omitting start | |
* a leading '@' means to invert the above definitions | |
* | |
* @see https://nagios-plugins.org/doc/guidelines.html#THRESHOLDFORMAT | |
* @see https://icinga.com/docs/icinga-2/2.11/doc/05-service-monitoring/#threshold-ranges | |
* @param string $thresh The threshold specification | |
* @param string|int $val The numeric value to compare against | |
* @return bool Whether or not an alert should be raised | |
*/ | |
function compare_threshold(string $thresh, string|int $val): bool | |
{ | |
verbose("Evaluating '$thresh' with '$val'", 2); | |
$inverse = false; | |
$start = null; | |
$end = null; | |
if (str_starts_with($thresh, "@")) { | |
$inverse = true; | |
$thresh = trim($thresh, "@"); | |
} | |
if (!str_contains($thresh, ":")) { | |
$end = (int)$thresh; | |
} else { | |
$vals = explode(":", $thresh); | |
$start = $vals[0] === "~" ? -INF : (int)$vals[0]; | |
$end = $vals[1] === "" ? INF : (int)$vals[1]; | |
} | |
return $inverse | |
? $val <= $end && (is_null($start) || $val >= $start) | |
: $val > $end || (!is_null($start) && $val < $start); | |
} | |
/** | |
* Output debug data | |
* @param string $message The message to output to stderr | |
* @param int $level The verbosity level | |
*/ | |
function verbose(string $message, int $level = 1): void | |
{ | |
global $verbose; | |
if ($verbose >= $level) { | |
file_put_contents("php://stderr", "$message\n"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment