diff --git a/library/Icinga/Application/Cli.php b/library/Icinga/Application/Cli.php
index 5ccd2ed1e..72b2b43f8 100644
--- a/library/Icinga/Application/Cli.php
+++ b/library/Icinga/Application/Cli.php
@@ -79,7 +79,7 @@ class Cli extends ApplicationBootstrap
array(
'enable' => true,
'level' => Logger::$INFO,
- 'type' => 'stream',
+ 'type' => 'file',
'target' => 'php://stderr'
)
)
diff --git a/library/Icinga/Util/Format.php b/library/Icinga/Util/Format.php
index 8c55cbafa..a7c0ee0e3 100644
--- a/library/Icinga/Util/Format.php
+++ b/library/Icinga/Util/Format.php
@@ -50,6 +50,9 @@ class Format
);
protected static $byteBase = array(1024, 1000);
+ protected static $secondPrefix = array('s', 'ms', 'µs', 'ns', 'ps', 'fs', 'as');
+ protected static $secondBase = 1000;
+
public static function getInstance()
{
if (self::$instance === null) {
@@ -76,6 +79,20 @@ class Format
);
}
+ public static function seconds($value)
+ {
+ if ($value < 60) {
+ return self::formatForUnits($value, self::$secondPrefix, self::$secondBase);
+ } elseif ($value < 3600) {
+ return sprintf('0.2f m', $value / 60);
+ } elseif ($value < 86400) {
+ return sprintf('0.2f h', $value / 3600);
+ }
+
+ // TODO: Do we need weeks, months and years?
+ return sprintf('0.2f d', $value / 86400);
+ }
+
public static function duration($duration)
{
if ($duration === null || $duration === false) {
@@ -148,7 +165,7 @@ class Format
'%s%0.2f %s',
$sign,
$result,
- $units[$pow]
+ $units[abs($pow)]
);
}
diff --git a/modules/monitoring/application/clicommands/ListCommand.php b/modules/monitoring/application/clicommands/ListCommand.php
index a07601871..4ddf2e781 100644
--- a/modules/monitoring/application/clicommands/ListCommand.php
+++ b/modules/monitoring/application/clicommands/ListCommand.php
@@ -263,9 +263,9 @@ class ListCommand extends Command
try {
$pset = PerfdataSet::fromString($row->service_perfdata);
$perfs = array();
- foreach ($pset->getAll() as $perfName => $p) {
+ foreach ($pset as $perfName => $p) {
if ($percent = $p->getPercentage()) {
- if ($percent < 0 || $percent > 300) {
+ if ($percent < 0 || $percent > 100) {
continue;
}
$perfs[] = ' '
diff --git a/modules/monitoring/application/views/helpers/Perfdata.php b/modules/monitoring/application/views/helpers/Perfdata.php
index 13997de18..49e88cae6 100644
--- a/modules/monitoring/application/views/helpers/Perfdata.php
+++ b/modules/monitoring/application/views/helpers/Perfdata.php
@@ -1,90 +1,82 @@
getAll();
- $perfdata = preg_replace_callback('~\'([^\']+)\'~', function($match) { return str_replace(' ', '\'', $match[1]); }, $perfdata);
- $parts = preg_split('~\s+~', $perfdata, -1, PREG_SPLIT_NO_EMPTY);
-
- $table = array();
$result = '';
- if ($compact === true) {
- $compact = 5;
- }
- if ($compact && count($parts) > $compact) {
- $parts = array_slice($parts, 0, $compact);
- }
- foreach ($parts as $part) {
- if (strpos($part, '=') === false) continue;
- list($name, $vals) = preg_split('~=~', $part, 2);
- $name = str_replace("'", ' ', $name);
- $parts = preg_split('~;~', $vals, 5);
- while (count($parts) < 5) $parts[] = null;
- list($val, $warn, $crit, $min, $max) = $parts;
-
- $unit = '';
- if (preg_match('~^([\d+\.]+)([^\d]+)$~', $val, $m)) {
- $unit = $m[2];
- $val = $m[1];
- } else {
+ $table = array();
+ $pset = array_slice(PerfdataSet::fromString($perfdataStr)->asArray(), 0, ($compact ? 5 : null));
+ foreach ($pset as $label => $perfdata) {
+ if (!$perfdata->isPercentage() && $perfdata->getMaximumValue() === null) {
continue;
}
- if ($unit == 'c') continue; // Counter pie graphs are not useful
- if ($compact && $val < 0.0001) continue;
- if ($unit == '%') {
- if (! $min ) $min = 0;
- if (! $max) $max = 100;
- } else {
- if (! $max && $crit > 0) $max = $crit;
- //return '';
- }
- if (! $max) continue;
- $green = 0;
- $orange = 0;
- $red = 0;
- $gray = $max - $val;
- if ($val < $warn) $green = $val;
- elseif ($val < $crit) $orange = $val;
- else $red = $val;
- $inlinePie = new InlinePie(array($green, $orange, $red, $gray));
+
+ $pieChart = new InlinePie($this->calculatePieChartData($perfdata));
if ($compact) {
- $inlinePie->setTitle(htmlspecialchars($name) . ': ' . htmlspecialchars($ps[$name]->getFormattedValue()));
- $inlinePie->setStyle('float: right;');
- $result .= $inlinePie->render();
+ $pieChart->setTitle(
+ htmlspecialchars($label) . ': ' . htmlspecialchars($this->formatPerfdataValue($perfdata))
+ );
+ $pieChart->setStyle('float: right;');
+ $result .= $pieChart->render();
} else {
- $inlinePie->setTitle(htmlspecialchars($name));
- $inlinePie->setStyle('float: left; margin: 0.2em 0.5em 0.2em 0;');
- $table[] = '
' . $inlinePie->render()
- . htmlspecialchars($name)
+ $pieChart->setTitle(htmlspecialchars($label));
+ $pieChart->setStyle('float: left; margin: 0.2em 0.5em 0.2em 0;');
+ $table[] = ' |
---|
' . $pieChart->render()
+ . htmlspecialchars($label)
. ' | '
- . htmlspecialchars($ps[$name]->getFormattedValue()) .
+ . htmlspecialchars($this->formatPerfdataValue($perfdata)) .
' |
';
}
}
- if ($result == '' && ! $compact) {
- $result = $perfdata;
+
+ // TODO: What if we have both? And should we trust sprintf-style placeholders in perfdata titles?
+ if (empty($table)) {
+ return $compact ? $result : $perfdataStr;
+ } else {
+ return '' . implode("\n", $table) . '
';
}
- if (! empty($table)) {
- // TODO: What if we have both? And should we trust sprintf-style placeholders in perfdata titles?
- $result = '' . implode("\n", $table) . '
';
+ }
+
+ protected function calculatePieChartData(Perfdata $perfdata)
+ {
+ $rawValue = $perfdata->getValue();
+ $minValue = $perfdata->getMinimumValue() !== null ? $perfdata->getMinimumValue() : 0;
+ $maxValue = $perfdata->getMaximumValue();
+ $usedValue = ($rawValue - $minValue);
+ $unusedValue = ($maxValue - $minValue) - $usedValue;
+
+ $gray = $unusedValue;
+ $green = $orange = $red = 0;
+ // TODO(#6122): Add proper treshold parsing.
+ if ($perfdata->getCriticalTreshold() && $perfdata->getValue() > $perfdata->getCriticalTreshold()) {
+ $red = $usedValue;
+ } elseif ($perfdata->getWarningTreshold() && $perfdata->getValue() > $perfdata->getWarningTreshold()) {
+ $orange = $usedValue;
+ } else {
+ $green = $usedValue;
}
- return $result;
+ return array($green, $orange, $red, $gray);
+ }
+
+ protected function formatPerfdataValue(Perfdata $perfdata)
+ {
+ if ($perfdata->isBytes()) {
+ return Format::bytes($perfdata->getValue());
+ } elseif ($perfdata->isSeconds()) {
+ return Format::seconds($perfdata->getValue());
+ } elseif ($perfdata->isPercentage()) {
+ return $perfdata->getValue() . '%';
+ }
+
+ return $perfdata->getValue();
}
}
diff --git a/modules/monitoring/library/Monitoring/Plugin/Perfdata.php b/modules/monitoring/library/Monitoring/Plugin/Perfdata.php
index 4d7cb13db..f01880885 100644
--- a/modules/monitoring/library/Monitoring/Plugin/Perfdata.php
+++ b/modules/monitoring/library/Monitoring/Plugin/Perfdata.php
@@ -1,223 +1,280 @@
unit) {
- case self::BYTES:
- return $this->formatBytes() . ' von ' . $this->formatBytes($this->max);
- break;
- case self::SECONDS:
- return $this->formatSeconds();
- break;
- case self::PERCENT:
- return number_format($this->val, 2, ',', '.') . '%';
- break;
- default:
- return $this->val;
- }
- }
+ /**
+ * The value
+ *
+ * @var float
+ */
+ protected $value;
- public function hasMax()
- {
- return $this->max !== null && $this->max > 0;
- }
+ /**
+ * The minimum value
+ *
+ * @var float
+ */
+ protected $minValue;
- public function getPercentage()
- {
- if ($this->unit === self::PERCENT) {
- return $this->val;
- }
- if ($this->hasMax()) {
- return $this->val / $this->max * 100;
- }
- return false;
- }
+ /**
+ * The maximum value
+ *
+ * @var float
+ */
+ protected $maxValue;
- public function getValue()
- {
- return $this->val;
- }
+ /**
+ * The WARNING treshold
+ *
+ * @var string
+ */
+ protected $warningTreshold;
- protected function formatBytes($val = null)
- {
- $steps = array(
- 1 => 'Byte',
- 1024 => 'KByte',
- 1024 * 1024 => 'MByte',
- 1024 * 1024 * 1024 => 'GByte',
- 1024 * 1024 * 1024 * 1024 => 'TByte'
- );
- return $this->formatSpecial($steps, 1, $val);
- }
+ /**
+ * The CRITICAL treshold
+ *
+ * @var string
+ */
+ protected $criticalTreshold;
- protected function formatSeconds()
+ /**
+ * Create a new Perfdata object based on the given performance data value
+ *
+ * @param string $perfdataValue The value to parse
+ */
+ protected function __construct($perfdataValue)
{
- $steps = array(
- 1 => 'us',
- 1000 => 'ms',
- 10000000 => 's',
- );
- return $this->formatSpecial($steps, 1000000, $this->val);
- }
+ $this->perfdataValue = $perfdataValue;
+ $this->parse();
- protected function formatSpecial($steps, $multi = 1, $val = null)
- {
- if ($val === null) {
- $val = abs($this->val);
- } else {
- $val = abs($val);
- }
- // TODO: Check this, prefix fails if $val is given
- if ($this->val < 0) {
- $prefix = '-';
- } else {
- $prefix = '';
- }
- $val *= $multi;
- $step = 1;
- foreach (array_keys($steps) as $key) {
- if ($key > $val * 1) {
- break;
+ if ($this->unit === '%') {
+ if ($this->minValue === null) {
+ $this->minValue = 0.0;
}
- $step = $key;
- }
- if ($step <= 0) $step = 1;
- return $prefix
- . number_format($val / $step, 1, ',', '.')
- . ' '
- . $steps[$step];
- }
-
- protected function __construct(& $perfdata)
- {
- $this->byte_map = array(
- 'b' => 1,
- 'kb' => 1024,
- 'mb' => 1024 * 1024,
- 'gb' => 1024 * 1024 * 1024,
- 'tb' => 1024 * 1024 * 1024 * 1024
- );
-
- // UGLY, fixes floats using comma:
- $perfdata = preg_replace('~\,~', '.', $perfdata);
-
- $parts = preg_split('~;~', $perfdata, 5);
- while (count($parts) < 5) {
- $parts[] = null;
- }
- list(
- $this->val,
- $this->warn,
- $this->crit,
- $this->min,
- $this->max
- ) = $parts;
- // TODO: check numbers!
-
- $unit = null;
- if (! preg_match('~^(\-?[\d+\.]+(?:E\-?\d+)?)([^\d]+)?$~', $this->val, $m)) {
- return $perfdata;
- // Numbers with an exponential base will be rendered invalid using the regex above
-// throw new \Exception('Got invalid perfdata: ' . $perfdata);
- }
- $this->val = $m[1];
- if (isset($m[2])) {
- $unit = strtolower($m[2]);
- }
- if ($unit === 'c') {
- $this->unit = self::COUNTER;
- }
-
- if ($unit === '%') {
- if (! is_numeric($this->min)) {
- $this->min = 0;
- }
- if (! is_numeric($this->max)) {
- $this->max = 100;
- }
- $this->unit = self::PERCENT;
- } else {
- if (! is_numeric($this->max) && $this->crit > 0) {
- $this->max = $this->crit;
- }
- }
-
- if (array_key_exists($unit, $this->byte_map)) {
- $this->unit = self::BYTES;
- $this->val = $this->val * $this->byte_map[$unit];
- $this->min = $this->min * $this->byte_map[$unit];
- $this->max = $this->max * $this->byte_map[$unit];
- }
- if ($unit === 's') {
- $this->unit = self::SECONDS;
- }
- if ($unit === 'ms') {
- $this->unit = self::SECONDS;
- $this->val = $this->val / 1000;
- }
- if ($unit === '%') {
- if (! is_numeric($this->min)) {
- $this->min = 0;
- }
- if (! is_numeric($this->max)) {
- $this->max = 100;
- }
- } else {
- if (! is_numeric($this->max) && $this->crit > 0) {
- $this->max = $this->crit;
+ if ($this->maxValue === null) {
+ $this->maxValue = 100.0;
}
}
}
+ /**
+ * Return a new Perfdata object based on the given performance data value
+ *
+ * @param string $perfdataValue The value to parse
+ *
+ * @return Perfdata
+ *
+ * @throws ProgrammingError In case the given performance data value has no content
+ */
+ public static function fromString($perfdataValue)
+ {
+ if (empty($perfdataValue)) {
+ throw new ProgrammingError('Perfdata::fromString expects a string with content');
+ }
+
+ return new static($perfdataValue);
+ }
+
+ /**
+ * Return whether this performance data value is a number
+ *
+ * @return bool True in case it's a number, otherwise False
+ */
+ public function isNumber()
+ {
+ return $this->unit === null;
+ }
+
+ /**
+ * Return whether this performance data value are seconds
+ *
+ * @return bool True in case it's seconds, otherwise False
+ */
+ public function isSeconds()
+ {
+ return in_array($this->unit, array('s', 'ms', 'us'));
+ }
+
+ /**
+ * Return whether this performance data value is in percentage
+ *
+ * @return bool True in case it's in percentage, otherwise False
+ */
+ public function isPercentage()
+ {
+ return $this->unit === '%';
+ }
+
+ /**
+ * Return whether this performance data value is in bytes
+ *
+ * @return bool True in case it's in bytes, otherwise False
+ */
+ public function isBytes()
+ {
+ return in_array($this->unit, array('b', 'kb', 'mb', 'gb', 'tb'));
+ }
+
+ /**
+ * Return whether this performance data value is a counter
+ *
+ * @return bool True in case it's a counter, otherwise False
+ */
public function isCounter()
{
- return $this->unit === self::COUNTER;
+ return $this->unit === 'c';
}
- public static function fromString(& $perfdata)
+ /**
+ * Return the value or null if it is unknown (U)
+ *
+ * @return null|float
+ */
+ public function getValue()
{
- $pdat = new Perfdata($perfdata);
- return $pdat;
+ return $this->value;
}
- protected function normalizeNumber($num)
+ /**
+ * Return the value as percentage (0-100)
+ *
+ * @return null|float
+ */
+ public function getPercentage()
{
- return $num;
- // Bullshit, still TODO
- /*
- $dot = strpos($num, '.');
- $comma = strpos($num, ',');
-
- if ($dot === false) {
- // No dot...
- if ($comma === false) {
- // ...and no comma, it's an integer:
- return (int) $num;
- } else {
- // just a comma
- }
- } else {
- if ($comma === false) {
+ if ($this->isPercentage()) {
+ return $this->value;
+ }
+
+ if ($this->maxValue !== null) {
+ $minValue = $this->minValue !== null ? $this->minValue : 0;
+
+ if ($this->value > $minValue) {
+ return (($this->value - $minValue) / ($this->maxValue - $minValue)) * 100;
+ }
+ }
+ }
+
+ /**
+ * Return this value's warning treshold or null if it is not available
+ *
+ * @return null|string
+ */
+ public function getWarningTreshold()
+ {
+ return $this->warningTreshold;
+ }
+
+ /**
+ * Return this value's critical treshold or null if it is not available
+ *
+ * @return null|string
+ */
+ public function getCriticalTreshold()
+ {
+ return $this->criticalTreshold;
+ }
+
+ /**
+ * Return the minimum value or null if it is not available
+ *
+ * @return null|float
+ */
+ public function getMinimumValue()
+ {
+ return $this->minValue;
+ }
+
+ /**
+ * Return the maximum value or null if it is not available
+ *
+ * @return null|float
+ */
+ public function getMaximumValue()
+ {
+ return $this->maxValue;
+ }
+
+ /**
+ * Parse the current performance data value
+ *
+ * @todo Handle optional min/max if UOM == %
+ */
+ protected function parse()
+ {
+ $parts = explode(';', $this->perfdataValue);
+
+ $matches = array();
+ if (preg_match('@^(\d+(\.\d+)?)([a-zA-Z%]{1,2})$@', $parts[0], $matches)) {
+ $this->unit = strtolower($matches[3]);
+ $this->value = self::convert($matches[1], $this->unit);
+ } else {
+ $this->value = self::convert($parts[0]);
+ }
+
+ switch (count($parts))
+ {
+ case 5:
+ $this->maxValue = self::convert($parts[4], $this->unit);
+ case 4:
+ $this->minValue = self::convert($parts[3], $this->unit);
+ case 3:
+ // TODO(#6123): Tresholds have the same UOM and need to be converted as well!
+ $this->criticalTreshold = trim($parts[2]) ? trim($parts[2]) : null;
+ case 2:
+ // TODO(#6123): Tresholds have the same UOM and need to be converted as well!
+ $this->warningTreshold = trim($parts[1]) ? trim($parts[1]) : null;
+ }
+ }
+
+ /**
+ * Return the given value converted to its smallest supported representation
+ *
+ * @param string $value The value to convert
+ * @param string $fromUnit The unit the value currently represents
+ *
+ * @return null|float Null in case the value is not a number
+ */
+ protected static function convert($value, $fromUnit = null)
+ {
+ if (is_numeric($value)) {
+ switch ($fromUnit)
+ {
+ case 'us':
+ return $value / pow(10, 6);
+ case 'ms':
+ return $value / pow(10, 3);
+ case 'tb':
+ return floatval($value) * pow(2, 40);
+ case 'gb':
+ return floatval($value) * pow(2, 30);
+ case 'mb':
+ return floatval($value) * pow(2, 20);
+ case 'kb':
+ return floatval($value) * pow(2, 10);
+ default:
+ return (float) $value;
+ }
}
- */
}
}
diff --git a/modules/monitoring/library/Monitoring/Plugin/PerfdataSet.php b/modules/monitoring/library/Monitoring/Plugin/PerfdataSet.php
index 7f6876f1a..8038354a4 100644
--- a/modules/monitoring/library/Monitoring/Plugin/PerfdataSet.php
+++ b/modules/monitoring/library/Monitoring/Plugin/PerfdataSet.php
@@ -1,68 +1,144 @@
ptr = & $perfdata;
- $this->len = strlen($this->ptr);
- while ($this->pos < $this->len) {
- $label = $this->readLabel();
- $perf = $this->readUntil(' ');
- if (empty($perf)) continue;
- $this->perfdata[$label] = Perfdata::fromString($perf);
+ if (($perfdataStr = trim($perfdataStr)) !== '') {
+ $this->perfdataStr = $perfdataStr;
+ $this->parse();
}
}
- public static function fromString(& $perfdata)
+ /**
+ * Return a iterator for this set of performance data
+ *
+ * @return ArrayIterator
+ */
+ public function getIterator()
{
- $pset = new PerfdataSet($perfdata);
- return $pset;
+ return new ArrayIterator($this->asArray());
}
- public function getAll()
+ /**
+ * Return a new set of performance data
+ *
+ * @param string $perfdataStr A space separated list of label/value pairs
+ *
+ * @return PerfdataSet
+ */
+ public static function fromString($perfdataStr)
{
- return $this->perfdata === null ? array() : $this->perfdata;
+ return new static($perfdataStr);
}
+ /**
+ * Return this set of performance data as array
+ *
+ * @return array
+ */
+ public function asArray()
+ {
+ return $this->perfdata;
+ }
+
+ /**
+ * Parse the current performance data
+ */
+ protected function parse()
+ {
+ while ($this->parserPos < strlen($this->perfdataStr)) {
+ $label = trim($this->readLabel());
+ $value = trim($this->readUntil(' '));
+
+ if ($label && $value) {
+ $this->perfdata[$label] = Perfdata::fromString($value);
+ }
+ }
+ }
+
+ /**
+ * Return the next label found in the performance data
+ *
+ * @return string The label found
+ */
protected function readLabel()
{
$this->skipSpaces();
- if (in_array($this->ptr[$this->pos], array('"', "'"))) {
- $this->pos++;
- $label = $this->readUntil($this->ptr[$this->pos - 1]);
- $this->pos++; // Skip ' or "
- $skip = $this->readUntil('=');
- $this->pos++;
+ if (in_array($this->perfdataStr[$this->parserPos], array('"', "'"))) {
+ $quoteChar = $this->perfdataStr[$this->parserPos++];
+ $label = $this->readUntil('=');
+ $this->parserPos++;
+
+ if (($closingPos = strpos($label, $quoteChar)) > 0) {
+ $label = substr($label, 0, $closingPos);
+ }
} else {
$label = $this->readUntil('=');
- $this->pos++;
+ $this->parserPos++;
}
+
$this->skipSpaces();
- return trim($label);
+ return $label;
}
- protected function readUntil($stop_char)
+ /**
+ * Return all characters between the current parser position and the given character
+ *
+ * @param string $stopChar The character on which to stop
+ *
+ * @return string
+ */
+ protected function readUntil($stopChar)
{
- $start = $this->pos;
- while ($this->pos < $this->len && $this->ptr[$this->pos] !== $stop_char) {
- $this->pos++;
+ $start = $this->parserPos;
+ while ($this->parserPos < strlen($this->perfdataStr) && $this->perfdataStr[$this->parserPos] !== $stopChar) {
+ $this->parserPos++;
}
- return substr($this->ptr, $start, $this->pos - $start);
+
+ return substr($this->perfdataStr, $start, $this->parserPos - $start);
}
+ /**
+ * Advance the parser position to the next non-whitespace character
+ */
protected function skipSpaces()
{
- while ($this->pos < $this->len && $this->ptr[$this->pos] === ' ') {
- $this->pos++;
+ while ($this->parserPos < strlen($this->perfdataStr) && $this->perfdataStr[$this->parserPos] === ' ') {
+ $this->parserPos++;
}
}
}
diff --git a/modules/monitoring/test/php/library/Filter/Type/StatusFilterTest.php b/modules/monitoring/test/php/library/Monitoring/Filter/Type/StatusFilterTest.php
similarity index 98%
rename from modules/monitoring/test/php/library/Filter/Type/StatusFilterTest.php
rename to modules/monitoring/test/php/library/Monitoring/Filter/Type/StatusFilterTest.php
index 994987717..84f76d135 100644
--- a/modules/monitoring/test/php/library/Filter/Type/StatusFilterTest.php
+++ b/modules/monitoring/test/php/library/Monitoring/Filter/Type/StatusFilterTest.php
@@ -2,7 +2,7 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
-namespace Tests\Icinga\Module\Monitoring\Library\Filter\Type;
+namespace Tests\Icinga\Module\Monitoring\Filter\Type;
use Icinga\Module\Monitoring\Filter\Type\StatusFilter;
use Icinga\Filter\Type\TimeRangeSpecifier;
diff --git a/modules/monitoring/test/php/library/Filter/UrlViewFilterTest.php b/modules/monitoring/test/php/library/Monitoring/Filter/UrlViewFilterTest.php
similarity index 99%
rename from modules/monitoring/test/php/library/Filter/UrlViewFilterTest.php
rename to modules/monitoring/test/php/library/Monitoring/Filter/UrlViewFilterTest.php
index 278211405..e7afd3911 100644
--- a/modules/monitoring/test/php/library/Filter/UrlViewFilterTest.php
+++ b/modules/monitoring/test/php/library/Monitoring/Filter/UrlViewFilterTest.php
@@ -2,7 +2,7 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
-namespace Tests\Icinga\Module\Monitoring\Library\Filter;
+namespace Tests\Icinga\Module\Monitoring\Filter;
use \Mockery;
use Icinga\Module\Monitoring\Filter\Type\StatusFilter;
diff --git a/modules/monitoring/test/php/library/Monitoring/Plugin/PerfdataSetTest.php b/modules/monitoring/test/php/library/Monitoring/Plugin/PerfdataSetTest.php
new file mode 100644
index 000000000..86c0f71a7
--- /dev/null
+++ b/modules/monitoring/test/php/library/Monitoring/Plugin/PerfdataSetTest.php
@@ -0,0 +1,101 @@
+assertArrayHasKey(
+ 'key1',
+ $pset->perfdata,
+ 'PerfdataSet does not correctly parse valid simple labels'
+ );
+ $this->assertArrayHasKey(
+ 'key2',
+ $pset->perfdata,
+ 'PerfdataSet does not correctly parse valid simple labels'
+ );
+ $this->assertArrayHasKey(
+ 'key3',
+ $pset->perfdata,
+ 'PerfdataSet does not correctly parse valid simple labels'
+ );
+ }
+
+ public function testWhetherNonQuotedPerfdataLablesWithSpacesAreProperlyParsed()
+ {
+ $pset = PerfdataSetWithPublicData::fromString('key 1=val1 key 1 + 1=val2');
+ $this->assertArrayHasKey(
+ 'key 1',
+ $pset->perfdata,
+ 'PerfdataSet does not correctly parse non quoted labels with spaces'
+ );
+ $this->assertArrayHasKey(
+ 'key 1 + 1',
+ $pset->perfdata,
+ 'PerfdataSet does not correctly parse non quoted labels with spaces'
+ );
+ }
+
+ public function testWhetherValidQuotedPerfdataLabelsAreProperlyParsed()
+ {
+ $pset = PerfdataSetWithPublicData::fromString('\'key 1\'=val1 "key 2"=val2');
+ $this->assertArrayHasKey(
+ 'key 1',
+ $pset->perfdata,
+ 'PerfdataSet does not correctly parse valid quoted labels'
+ );
+ $this->assertArrayHasKey(
+ 'key 2',
+ $pset->perfdata,
+ 'PerfdataSet does not correctly parse valid quoted labels'
+ );
+ }
+
+ public function testWhetherInvalidQuotedPerfdataLabelsAreProperlyParsed()
+ {
+ $pset = PerfdataSetWithPublicData::fromString('\'key 1=val1 key 2"=val2');
+ $this->assertArrayHasKey(
+ 'key 1',
+ $pset->perfdata,
+ 'PerfdataSet does not correctly parse invalid quoted labels'
+ );
+ $this->assertArrayHasKey(
+ 'key 2"',
+ $pset->perfdata,
+ 'PerfdataSet does not correctly parse invalid quoted labels'
+ );
+ }
+
+ /**
+ * @depends testWhetherValidSimplePerfdataLabelsAreProperlyParsed
+ */
+ public function testWhetherAPerfdataSetIsIterable()
+ {
+ $pset = PerfdataSet::fromString('key=value');
+ foreach ($pset as $label => $value) {
+ $this->assertEquals('key', $label);
+ return;
+ }
+
+ $this->fail('PerfdataSet objects cannot be iterated');
+ }
+
+ public function testWhetherPerfdataSetsCanBeInitializedWithEmptyStrings()
+ {
+ $pset = PerfdataSetWithPublicData::fromString('');
+ $this->assertEmpty($pset->perfdata, 'PerfdataSet::fromString does not accept emtpy strings');
+ }
+}
diff --git a/modules/monitoring/test/php/library/Monitoring/Plugin/PerfdataTest.php b/modules/monitoring/test/php/library/Monitoring/Plugin/PerfdataTest.php
new file mode 100644
index 000000000..9bb32ffd8
--- /dev/null
+++ b/modules/monitoring/test/php/library/Monitoring/Plugin/PerfdataTest.php
@@ -0,0 +1,352 @@
+assertEquals(
+ 1337.0,
+ Perfdata::fromString('1337')->getValue(),
+ 'Perfdata::getValue does not return correct values'
+ );
+ $this->assertEquals(
+ 1337.0,
+ Perfdata::fromString('1337;;;;')->getValue(),
+ 'Perfdata::getValue does not return correct values'
+ );
+ }
+
+ public function testWhetherDecimalValuesAreCorrectlyParsed()
+ {
+ $this->assertEquals(
+ 1337.5,
+ Perfdata::fromString('1337.5')->getValue(),
+ 'Perfdata objects do not parse decimal values correctly'
+ );
+ $this->assertEquals(
+ 1337.5,
+ Perfdata::fromString('1337.5B')->getValue(),
+ 'Perfdata objects do not parse decimal values correctly'
+ );
+ }
+
+ public function testWhetherGetValueReturnsNullForInvalidOrUnknownValues()
+ {
+ $this->assertNull(
+ Perfdata::fromString('U')->getValue(),
+ 'Perfdata::getValue does not return null for unknown values'
+ );
+ $this->assertNull(
+ Perfdata::fromString('i am not a value')->getValue(),
+ 'Perfdata::getValue does not return null for invalid values'
+ );
+ }
+
+ public function testWhetherGetWarningTresholdReturnsCorrectValues()
+ {
+ $this->assertEquals(
+ '10',
+ Perfdata::fromString('1;10')->getWarningTreshold(),
+ 'Perfdata::getWarningTreshold does not return correct values'
+ );
+ $this->assertEquals(
+ '10:',
+ Perfdata::fromString('1;10:')->getWarningTreshold(),
+ 'Perfdata::getWarningTreshold does not return correct values'
+ );
+ $this->assertEquals(
+ '~:10',
+ Perfdata::fromString('1;~:10')->getWarningTreshold(),
+ 'Perfdata::getWarningTreshold does not return correct values'
+ );
+ $this->assertEquals(
+ '10:20',
+ Perfdata::fromString('1;10:20')->getWarningTreshold(),
+ 'Perfdata::getWarningTreshold does not return correct values'
+ );
+ $this->assertEquals(
+ '@10:20',
+ Perfdata::fromString('1;@10:20')->getWarningTreshold(),
+ 'Perfdata::getWarningTreshold does not return correct values'
+ );
+ }
+
+ public function testWhetherGetCriticalTresholdReturnsCorrectValues()
+ {
+ $this->assertEquals(
+ '10',
+ Perfdata::fromString('1;;10')->getCriticalTreshold(),
+ 'Perfdata::getCriticalTreshold does not return correct values'
+ );
+ $this->assertEquals(
+ '10:',
+ Perfdata::fromString('1;;10:')->getCriticalTreshold(),
+ 'Perfdata::getCriticalTreshold does not return correct values'
+ );
+ $this->assertEquals(
+ '~:10',
+ Perfdata::fromString('1;;~:10')->getCriticalTreshold(),
+ 'Perfdata::getCriticalTreshold does not return correct values'
+ );
+ $this->assertEquals(
+ '10:20',
+ Perfdata::fromString('1;;10:20')->getCriticalTreshold(),
+ 'Perfdata::getCriticalTreshold does not return correct values'
+ );
+ $this->assertEquals(
+ '@10:20',
+ Perfdata::fromString('1;;@10:20')->getCriticalTreshold(),
+ 'Perfdata::getCriticalTreshold does not return correct values'
+ );
+ }
+
+ public function testWhetherGetMinimumValueReturnsCorrectValues()
+ {
+ $this->assertEquals(
+ 1337.0,
+ Perfdata::fromString('1;;;1337')->getMinimumValue(),
+ 'Perfdata::getMinimumValue does not return correct values'
+ );
+ $this->assertEquals(
+ 1337.5,
+ Perfdata::fromString('1;;;1337.5')->getMinimumValue(),
+ 'Perfdata::getMinimumValue does not return correct values'
+ );
+ }
+
+ public function testWhetherGetMaximumValueReturnsCorrectValues()
+ {
+ $this->assertEquals(
+ 1337.0,
+ Perfdata::fromString('1;;;;1337')->getMaximumValue(),
+ 'Perfdata::getMaximumValue does not return correct values'
+ );
+ $this->assertEquals(
+ 1337.5,
+ Perfdata::fromString('1;;;;1337.5')->getMaximumValue(),
+ 'Perfdata::getMaximumValue does not return correct values'
+ );
+ }
+
+ public function testWhetherMissingValuesAreReturnedAsNull()
+ {
+ $perfdata = Perfdata::fromString('1;;3;5');
+ $this->assertNull(
+ $perfdata->getWarningTreshold(),
+ 'Perfdata objects do not return null for missing warning tresholds'
+ );
+ $this->assertNull(
+ $perfdata->getMaximumValue(),
+ 'Perfdata objects do not return null for missing maximum values'
+ );
+ }
+
+ /**
+ * @depends testWhetherGetValueReturnsValidValues
+ */
+ public function testWhetherValuesAreIdentifiedAsNumber()
+ {
+ $this->assertTrue(
+ Perfdata::fromString('666')->isNumber(),
+ 'Perfdata objects do not identify ordinary digits as number'
+ );
+ }
+
+ /**
+ * @depends testWhetherGetValueReturnsValidValues
+ */
+ public function testWhetherValuesAreIdentifiedAsSeconds()
+ {
+ $this->assertTrue(
+ Perfdata::fromString('666s')->isSeconds(),
+ 'Perfdata objects do not identify seconds as seconds'
+ );
+ $this->assertTrue(
+ Perfdata::fromString('666us')->isSeconds(),
+ 'Perfdata objects do not identify microseconds as seconds'
+ );
+ $this->assertTrue(
+ Perfdata::fromString('666ms')->isSeconds(),
+ 'Perfdata objects do not identify milliseconds as seconds'
+ );
+ }
+
+ /**
+ * @depends testWhetherGetValueReturnsValidValues
+ */
+ public function testWhetherValuesAreIdentifiedAsPercentage()
+ {
+ $this->assertTrue(
+ Perfdata::fromString('66%')->isPercentage(),
+ 'Perfdata objects do not identify percentages as percentages'
+ );
+ }
+
+ /**
+ * @depends testWhetherValuesAreIdentifiedAsPercentage
+ */
+ public function testWhetherMinAndMaxAreNotRequiredIfUnitIsInPercent()
+ {
+ $perfdata = Perfdata::fromString('1%');
+ $this->assertEquals(
+ 0.0,
+ $perfdata->getMinimumValue(),
+ 'Perfdata objects do not set minimum value to 0 if UOM is %'
+ );
+ $this->assertEquals(
+ 100.0,
+ $perfdata->getMaximumValue(),
+ 'Perfdata objects do not set maximum value to 100 if UOM is %'
+ );
+ }
+
+ /**
+ * @depends testWhetherGetValueReturnsValidValues
+ */
+ public function testWhetherValuesAreIdentifiedAsBytes()
+ {
+ $this->assertTrue(
+ Perfdata::fromString('66666B')->isBytes(),
+ 'Perfdata objects do not identify bytes as bytes'
+ );
+ $this->assertTrue(
+ Perfdata::fromString('6666KB')->isBytes(),
+ 'Perfdata objects do not identify kilobytes as bytes'
+ );
+ $this->assertTrue(
+ Perfdata::fromString('666MB')->isBytes(),
+ 'Perfdata objects do not identify megabytes as bytes'
+ );
+ $this->assertTrue(
+ Perfdata::fromString('66GB')->isBytes(),
+ 'Perfdata objects do not identify gigabytes as bytes'
+ );
+ $this->assertTrue(
+ Perfdata::fromString('6TB')->isBytes(),
+ 'Perfdata objects do not identify terabytes as bytes'
+ );
+ }
+
+ /**
+ * @depends testWhetherGetValueReturnsValidValues
+ */
+ public function testWhetherValuesAreIdentifiedAsCounter()
+ {
+ $this->assertTrue(
+ Perfdata::fromString('123c')->isCounter(),
+ 'Perfdata objects do not identify counters as counters'
+ );
+ }
+
+ /**
+ * @depends testWhetherValuesAreIdentifiedAsSeconds
+ */
+ public function testWhetherMicroSecondsAreCorrectlyConvertedToSeconds()
+ {
+ $this->assertEquals(
+ 666 / pow(10, 6),
+ Perfdata::fromString('666us')->getValue(),
+ 'Perfdata objects do not correctly convert microseconds to seconds'
+ );
+ }
+
+ /**
+ * @depends testWhetherValuesAreIdentifiedAsSeconds
+ */
+ public function testWhetherMilliSecondsAreCorrectlyConvertedToSeconds()
+ {
+ $this->assertEquals(
+ 666 / pow(10, 3),
+ Perfdata::fromString('666ms')->getValue(),
+ 'Perfdata objects do not correctly convert microseconds to seconds'
+ );
+ }
+
+ /**
+ * @depends testWhetherValuesAreIdentifiedAsPercentage
+ */
+ public function testWhetherPercentagesAreHandledCorrectly()
+ {
+ $this->assertEquals(
+ 66.0,
+ Perfdata::fromString('66%')->getPercentage(),
+ 'Perfdata objects do not correctly handle native percentages'
+ );
+ $this->assertEquals(
+ 50.0,
+ Perfdata::fromString('0;;;-250;250')->getPercentage(),
+ 'Perfdata objects do not correctly convert suitable values to percentages'
+ );
+ $this->assertNull(
+ Perfdata::fromString('50')->getPercentage(),
+ 'Perfdata objects do return a percentage though their unit is not % and no maximum is given'
+ );
+ $this->assertNull(
+ Perfdata::fromString('25;;;50;100')->getPercentage(),
+ 'Perfdata objects do return a percentage though their value is lower than it\'s allowed minimum'
+ );
+ }
+
+ /**
+ * @depends testWhetherValuesAreIdentifiedAsBytes
+ */
+ public function testWhetherKiloBytesAreCorrectlyConvertedToBytes()
+ {
+ $this->assertEquals(
+ 6666.0 * pow(2, 10),
+ Perfdata::fromString('6666KB')->getValue(),
+ 'Perfdata objects do not corretly convert kilobytes to bytes'
+ );
+ }
+
+ /**
+ * @depends testWhetherValuesAreIdentifiedAsBytes
+ */
+ public function testWhetherMegaBytesAreCorrectlyConvertedToBytes()
+ {
+ $this->assertEquals(
+ 666.0 * pow(2, 20),
+ Perfdata::fromString('666MB')->getValue(),
+ 'Perfdata objects do not corretly convert megabytes to bytes'
+ );
+ }
+
+ /**
+ * @depends testWhetherValuesAreIdentifiedAsBytes
+ */
+ public function testWhetherGigaBytesAreCorrectlyConvertedToBytes()
+ {
+ $this->assertEquals(
+ 66.0 * pow(2, 30),
+ Perfdata::fromString('66GB')->getValue(),
+ 'Perfdata objects do not corretly convert gigabytes to bytes'
+ );
+ }
+
+ /**
+ * @depends testWhetherValuesAreIdentifiedAsBytes
+ */
+ public function testWhetherTeraBytesAreCorrectlyConvertedToBytes()
+ {
+ $this->assertEquals(
+ 6.0 * pow(2, 40),
+ Perfdata::fromString('6TB')->getValue(),
+ 'Perfdata objects do not corretly convert terabytes to bytes'
+ );
+ }
+}
diff --git a/public/js/icinga/loader.js b/public/js/icinga/loader.js
index f525c2437..5d2679d55 100644
--- a/public/js/icinga/loader.js
+++ b/public/js/icinga/loader.js
@@ -508,7 +508,7 @@
// Icinga.debug(req.getResponseHeader('X-Icinga-Redirect'));
} else {
if (errorThrown === 'abort') {
- this.icinga.logger.info(
+ this.icinga.logger.debug(
'Request to ' + url + ' has been aborted for ',
req.$target
);