perfdataValue = $value; $this->label = $label; $this->parse(); if ($this->unit === '%') { if ($this->minValue === null) { $this->minValue = 0.0; } if ($this->maxValue === null) { $this->maxValue = 100.0; } } $warn = $this->warningThreshold->getMax(); if ($warn !== null) { $crit = $this->criticalThreshold->getMax(); if ($crit !== null && $warn > $crit) { $this->warningThreshold->setInverted(); $this->criticalThreshold->setInverted(); } } } /** * Return a new Perfdata object based on the given performance data key=value pair * * @param string $perfdata The key=value pair to parse * * @return Perfdata * * @throws InvalidArgumentException In case the given performance data has no content or a invalid format */ public static function fromString($perfdata) { if (empty($perfdata)) { throw new InvalidArgumentException('Perfdata::fromString expects a string with content'); } elseif (strpos($perfdata, '=') === false) { throw new InvalidArgumentException( 'Perfdata::fromString expects a key=value formatted string. Got "' . $perfdata . '" instead' ); } list($label, $value) = explode('=', $perfdata, 2); return new static(trim($label), trim($value)); } /** * Return whether this performance data's 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's 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's value is a temperature * * @return bool True in case it's temperature, otherwise False */ public function isTemperature() { return in_array($this->unit, array('°c', '°f')); } /** * Return whether this performance data's 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's 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's value is a counter * * @return bool True in case it's a counter, otherwise False */ public function isCounter() { return $this->unit === 'c'; } /** * Returns whether it is possible to display a visual representation * * @return bool True when the perfdata is visualizable */ public function isVisualizable() { return isset($this->minValue) && isset($this->maxValue) && isset($this->value); } /** * Return this perfomance data's label */ public function getLabel() { return $this->label; } /** * Return the value or null if it is unknown (U) * * @return null|float */ public function getValue() { return $this->value; } /** * Return the unit as a string * * @return string */ public function getUnit() { return $this->unit; } /** * Return the value as percentage (0-100) * * @return null|float */ public function getPercentage() { if ($this->isPercentage()) { return $this->value; } if ($this->maxValue !== null) { $minValue = $this->minValue !== null ? $this->minValue : 0.0; if ($this->maxValue == $minValue) { return null; } if ($this->value > $minValue) { return (($this->value - $minValue) / ($this->maxValue - $minValue)) * 100; } } } /** * Return this performance data's warning treshold * * @return ThresholdRange */ public function getWarningThreshold() { return $this->warningThreshold; } /** * Return this performance data's critical treshold * * @return ThresholdRange */ public function getCriticalThreshold() { return $this->criticalThreshold; } /** * Return the minimum value or null if it is not available * * @return null|string */ 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; } /** * Return this performance data as string * * @return string */ public function __toString() { return $this->formatLabel(); } /** * 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,3})$@u', $parts[0], $matches)) { $this->unit = strtolower($matches[2]); $this->value = self::convert($matches[1], $this->unit); } else { $this->value = self::convert($parts[0]); } switch (count($parts)) { /* @noinspection PhpMissingBreakStatementInspection */ case 5: if ($parts[4] !== '') { $this->maxValue = self::convert($parts[4], $this->unit); } /* @noinspection PhpMissingBreakStatementInspection */ case 4: if ($parts[3] !== '') { $this->minValue = self::convert($parts[3], $this->unit); } /* @noinspection PhpMissingBreakStatementInspection */ case 3: $this->criticalThreshold = self::convert( ThresholdRange::fromString(trim($parts[2])), $this->unit ); // Fallthrough case 2: $this->warningThreshold = self::convert( ThresholdRange::fromString(trim($parts[1])), $this->unit ); } if ($this->warningThreshold === null) { $this->warningThreshold = new ThresholdRange(); } if ($this->criticalThreshold === null) { $this->criticalThreshold = new ThresholdRange(); } } /** * 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 ThresholdRange|null|float Null in case the value is not a number */ protected static function convert($value, $fromUnit = null) { if ($value instanceof ThresholdRange) { $value = clone $value; $min = $value->getMin(); if ($min !== null) { $value->setMin(self::convert($min, $fromUnit)); } $max = $value->getMax(); if ($max !== null) { $value->setMax(self::convert($max, $fromUnit)); } return $value; } 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; } } } protected function calculatePieChartData() { $rawValue = $this->getValue(); $minValue = $this->getMinimumValue() !== null ? $this->getMinimumValue() : 0; $usedValue = ($rawValue - $minValue); $green = $orange = $red = 0; if ($this->criticalThreshold->contains($rawValue)) { if ($this->warningThreshold->contains($rawValue)) { $green = $usedValue; } else { $orange = $usedValue; } } else { $red = $usedValue; } return array($green, $orange, $red, ($this->getMaximumValue() - $minValue) - $usedValue); } public function asInlinePie() { if (! $this->isVisualizable()) { throw new ProgrammingError('Cannot calculate piechart data for unvisualizable perfdata entry.'); } $data = $this->calculatePieChartData(); $pieChart = new InlinePie($data, $this); $pieChart->setColors(array('#44bb77', '#ffaa44', '#ff5566', '#ddccdd')); return $pieChart; } /** * Format the given value depending on the currently used unit */ protected function format($value) { if ($value === null) { return null; } if ($value instanceof ThresholdRange) { if ($value->getMin()) { return (string) $value; } $max = $value->getMax(); return $max === null ? '' : $this->format($max); } if ($this->isPercentage()) { return (string)$value . '%'; } if ($this->isBytes()) { return Format::bytes($value); } if ($this->isSeconds()) { return Format::seconds($value); } if ($this->isTemperature()) { return (string)$value . strtoupper($this->unit); } return number_format($value, 2) . ($this->unit !== null ? ' ' . $this->unit : ''); } /** * Format the title string that represents this perfdata set * * @param bool $html * * @return string */ public function formatLabel($html = false) { return sprintf( $html ? '%s %s (%s%%)' : '%s %s (%s%%)', htmlspecialchars($this->getLabel()), $this->format($this->value), number_format($this->getPercentage() ?? 0, 2) ); } public function toArray() { return array( '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) ); } /** * Return the state indicated by this perfdata * * @see Service * * @return int */ public function getState() { if ($this->value === null) { return Service::STATE_UNKNOWN; } if (! $this->criticalThreshold->contains($this->value)) { return Service::STATE_CRITICAL; } if (! $this->warningThreshold->contains($this->value)) { return Service::STATE_WARNING; } return Service::STATE_OK; } /** * Return whether the state indicated by this perfdata is worse than * the state indicated by the other perfdata * CRITICAL > UNKNOWN > WARNING > OK * * @param Perfdata $rhs the other perfdata * * @return bool */ public function worseThan(Perfdata $rhs) { if (($state = $this->getState()) === ($rhsState = $rhs->getState())) { return $this->getPercentage() > $rhs->getPercentage(); } if ($state === Service::STATE_CRITICAL) { return true; } if ($state === Service::STATE_UNKNOWN) { return $rhsState !== Service::STATE_CRITICAL; } if ($state === Service::STATE_WARNING) { return $rhsState === Service::STATE_OK; } return false; } }