Do not evaluate invalid performance data

This commit is contained in:
raviks789 2023-08-23 14:54:15 +02:00
parent 808a275b21
commit 172e75102f
5 changed files with 134 additions and 23 deletions

View file

@ -39,21 +39,21 @@ class PerfData
/**
* The value
*
* @var float
* @var ?float
*/
protected $value;
/**
* The minimum value
*
* @var float
* @var ?float
*/
protected $minValue;
/**
* The maximum value
*
* @var float
* @var ?float
*/
protected $maxValue;
@ -71,6 +71,27 @@ class PerfData
*/
protected $criticalThreshold;
/**
* The raw value
*
* @var ?string
*/
protected $rawValue;
/**
* The raw minimum value
*
* @var ?string
*/
protected $rawMinValue;
/**
* The raw maximum value
*
* @var ?string
*/
protected $rawMaxValue;
/**
* Create a new PerfData object based on the given performance data label and value
*
@ -312,7 +333,7 @@ class PerfData
*/
public function isVisualizable(): bool
{
return isset($this->minValue) && isset($this->maxValue) && isset($this->value);
return isset($this->minValue, $this->maxValue, $this->value) && $this->isValid();
}
/**
@ -428,25 +449,39 @@ class PerfData
$matches = array();
if (preg_match('@^(U|-?(?:\d+)?(?:\.\d+)?)([a-zA-TV-Z%°]{1,3})$@u', $parts[0], $matches)) {
$this->unit = $matches[2];
$this->value = $matches[1];
$value = $matches[1];
} else {
$this->value = $parts[0];
$value = $parts[0];
}
if (! is_numeric($this->value)) {
if (! is_numeric($value)) {
if ($value !== 'U') {
$this->rawValue = $parts[0];
}
$this->value = null;
} else {
$this->value = floatval($value);
}
switch (count($parts)) {
/* @noinspection PhpMissingBreakStatementInspection */
case 5:
if ($parts[4] !== '') {
$this->maxValue = $parts[4];
if (is_numeric($parts[4])) {
$this->maxValue = floatval($parts[4]);
} else {
$this->rawMaxValue = $parts[4];
}
}
/* @noinspection PhpMissingBreakStatementInspection */
case 4:
if ($parts[3] !== '') {
$this->minValue = $parts[3];
if (is_numeric($parts[3])) {
$this->minValue = floatval($parts[3]);
} else {
$this->rawMinValue = $parts[3];
}
}
/* @noinspection PhpMissingBreakStatementInspection */
case 3:
@ -509,6 +544,10 @@ class PerfData
}
if ($value instanceof ThresholdRange) {
if (! $value->isValid()) {
return (string) $value;
}
if ($value->getMin()) {
return (string) $value;
}
@ -578,18 +617,22 @@ class PerfData
public function toArray(): array
{
return array(
return [
'label' => $this->getLabel(),
'value' => $this->format($this->getValue()),
'min' => isset($this->minValue) && !$this->isPercentage()
? $this->format($this->minValue)
: '',
'max' => isset($this->maxValue) && !$this->isPercentage()
? $this->format($this->maxValue)
: '',
'warn' => $this->format($this->warningThreshold),
'crit' => $this->format($this->criticalThreshold)
);
'value' => isset($this->value) ? $this->format($this->value) : $this->rawValue,
'min' => (string) (
! $this->isPercentage()
? (isset($this->minValue) ? $this->format($this->minValue) : $this->rawMinValue)
: null
),
'max' => (string) (
! $this->isPercentage()
? (isset($this->maxValue) ? $this->format($this->maxValue) : $this->rawMaxValue)
: null
),
'warn' => $this->format($this->warningThreshold),
'crit' => $this->format($this->criticalThreshold)
];
}
/**
@ -643,4 +686,18 @@ class PerfData
return false;
}
/**
* Returns whether the performance data can be evaluated
*
* @return bool
*/
public function isValid(): bool
{
return ! isset($this->rawValue)
&& ! isset($this->rawMinValue)
&& ! isset($this->rawMaxValue)
&& $this->criticalThreshold->isValid()
&& $this->warningThreshold->isValid();
}
}

View file

@ -131,10 +131,9 @@ class PerfDataFormat
return sprintf('%0.2f d', $value / 86400);
}
protected static function formatForUnits($value, array &$units, int $base): string
protected static function formatForUnits(float $value, array &$units, int $base): string
{
$sign = '';
$value = (float) $value;
if ($value < 0) {
$value = abs($value);
$sign = '-';

View file

@ -37,6 +37,13 @@ class ThresholdRange
*/
protected $raw;
/**
* Whether the threshold range is valid
*
* @var bool
*/
protected $isValid = true;
/**
* Create a new instance based on a threshold range conforming to <https://nagios-plugins.org/doc/guidelines.html>
*
@ -61,6 +68,12 @@ class ThresholdRange
if (strpos($rawRange, ':') === false) {
$min = 0.0;
$max = trim($rawRange);
if (! is_numeric($max)) {
$range->isValid = false;
return $range;
}
$max = floatval(trim($rawRange));
} else {
list($min, $max) = explode(':', $rawRange, 2);
@ -75,9 +88,19 @@ class ThresholdRange
$min = null;
break;
default:
if (! is_numeric($min)) {
$range->isValid = false;
return $range;
}
$min = floatval($min);
}
if (! empty($max) && ! is_numeric($max)) {
$range->isValid = false;
return $range;
}
$max = empty($max) ? null : floatval($max);
}
@ -168,6 +191,16 @@ class ThresholdRange
));
}
/**
* Return whether the threshold range is valid
*
* @return bool
*/
public function isValid()
{
return $this->isValid;
}
/**
* Return the textual representation of $this, suitable for fromString()
*

View file

@ -12,9 +12,13 @@ use ipl\Html\HtmlElement;
use ipl\Html\HtmlString;
use ipl\Html\Table;
use ipl\Html\Text;
use ipl\I18n\Translation;
use ipl\Web\Widget\Icon;
class PerfDataTable extends Table
{
use Translation;
protected $defaultAttributes = [
'class' => 'performance-data-table collapsible',
'data-visible-rows' => 6
@ -58,7 +62,7 @@ class PerfDataTable extends Table
$containsSparkline = false;
foreach ($pieChartData as $perfdata) {
if ($perfdata->isVisualizable()) {
if ($perfdata->isVisualizable() || ! $perfdata->isValid()) {
$containsSparkline = true;
break;
}
@ -91,6 +95,19 @@ class PerfDataTable extends Table
HtmlString::create($perfdata->asInlinePie($this->color)->render()),
['class' => 'sparkline-col']
);
} elseif (! $perfdata->isValid()) {
$cols[] = Table::td(
new Icon(
'triangle-exclamation',
[
'title' => $this->translate(
'Evaluation failed. Performance data is invalid.'
),
'class' => ['invalid-perfdata']
]
),
['class' => 'sparkline-col']
);
} else {
$cols[] = Table::td('');
}

View file

@ -43,6 +43,11 @@
min-width: 1.75em;
width: 1.75em;
padding: 2/12em 0;
.invalid-perfdata {
font-size: 1.25em;
vertical-align: text-bottom;
color: @color-warning;
}
}
.inline-pie > svg {