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(string $perfdata): self { 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(): bool { 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(): bool { return $this->unit === 's'; } /** * Return whether this performance data's value is a temperature * * @return bool True in case it's temperature, otherwise False */ public function isTemperature(): bool { return in_array($this->unit, array('C', 'F', 'K')); } /** * Return whether this performance data's value is in percentage * * @return bool True in case it's in percentage, otherwise False */ public function isPercentage(): bool { return $this->unit === '%'; } /** * Get whether this perf data's value is in packets * * @return bool True in case it's in packets */ public function isPackets(): bool { return $this->unit === 'packets'; } /** * Get whether this perf data's value is in lumen * * @return bool */ public function isLumens(): bool { return $this->unit === 'lm'; } /** * Get whether this perf data's value is in decibel-milliwatts * * @return bool */ public function isDecibelMilliWatts(): bool { return $this->unit === 'dBm'; } /** * Get whether this data's value is in bits * * @return bool */ public function isBits(): bool { return $this->unit === 'b'; } /** * Return whether this performance data's value is in bytes * * @return bool True in case it's in bytes, otherwise False */ public function isBytes(): bool { return $this->unit === 'B'; } /** * Get whether this data's value is in watt hours * * @return bool */ public function isWattHours(): bool { return $this->unit === 'Wh'; } /** * Get whether this data's value is in watt * * @return bool */ public function isWatts(): bool { return $this->unit === 'W'; } /** * Get whether this data's value is in ampere * * @return bool */ public function isAmperes(): bool { return $this->unit === 'A'; } /** * Get whether this data's value is in ampere seconds * * @return bool */ public function isAmpSeconds(): bool { return $this->unit === 'As'; } /** * Get whether this data's value is in volts * * @return bool */ public function isVolts(): bool { return $this->unit === 'V'; } /** * Get whether this data's value is in ohm * * @return bool */ public function isOhms(): bool { return $this->unit === 'O'; } /** * Get whether this data's value is in grams * * @return bool */ public function isGrams(): bool { return $this->unit === 'g'; } /** * Get whether this data's value is in Litters * * @return bool */ public function isLiters(): bool { return $this->unit === 'l'; } /** * Return whether this performance data's value is a counter * * @return bool True in case it's a counter, otherwise False */ public function isCounter(): bool { 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(): bool { return isset($this->minValue, $this->maxValue, $this->value) && $this->isValid(); } /** * Return this perfomance data's label */ public function getLabel(): string { 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(): ThresholdRange { return $this->warningThreshold; } /** * Return this performance data's critical treshold * * @return ThresholdRange */ public function getCriticalThreshold(): ThresholdRange { return $this->criticalThreshold; } /** * Return the minimum value or null if it is not available * * @return ?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; } /** * 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('@^(U|-?(?:\d+)?(?:\.\d+)?)([a-zA-TV-Z%°]{1,3})$@u', $parts[0], $matches)) { $this->unit = $matches[2]; $value = $matches[1]; } else { $value = $parts[0]; } 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] !== '') { if (is_numeric($parts[4])) { $this->maxValue = floatval($parts[4]); } else { $this->rawMaxValue = $parts[4]; } } /* @noinspection PhpMissingBreakStatementInspection */ case 4: if ($parts[3] !== '') { if (is_numeric($parts[3])) { $this->minValue = floatval($parts[3]); } else { $this->rawMinValue = $parts[3]; } } /* @noinspection PhpMissingBreakStatementInspection */ case 3: $this->criticalThreshold = ThresholdRange::fromString(trim($parts[2])); // Fallthrough case 2: $this->warningThreshold = ThresholdRange::fromString(trim($parts[1])); } if ($this->warningThreshold === null) { $this->warningThreshold = new ThresholdRange(); } if ($this->criticalThreshold === null) { $this->criticalThreshold = new ThresholdRange(); } } protected function calculatePieChartData(): array { $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(): InlinePie { if (! $this->isVisualizable()) { throw new LogicException('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->isValid()) { return (string) $value; } if ($value->getMin()) { return (string) $value; } $max = $value->getMax(); return $max === null ? '' : $this->format($max); } switch (true) { case $this->isPercentage(): return (string) $value . '%'; case $this->isPackets(): return (string) $value . 'packets'; case $this->isLumens(): return (string) $value . 'lm'; case $this->isDecibelMilliWatts(): return (string) $value . 'dBm'; case $this->isCounter(): return (string) $value . 'c'; case $this->isTemperature(): return (string) $value . $this->unit; case $this->isBits(): return PerfDataFormat::bits($value); case $this->isBytes(): return PerfDataFormat::bytes($value); case $this->isSeconds(): return PerfDataFormat::seconds($value); case $this->isWatts(): return PerfDataFormat::watts($value); case $this->isWattHours(): return PerfDataFormat::wattHours($value); case $this->isAmperes(): return PerfDataFormat::amperes($value); case $this->isAmpSeconds(): return PerfDataFormat::ampereSeconds($value); case $this->isVolts(): return PerfDataFormat::volts($value); case $this->isOhms(): return PerfDataFormat::ohms($value); case $this->isGrams(): return PerfDataFormat::grams($value); case $this->isLiters(): return PerfDataFormat::liters($value); case ! is_numeric($value): return $value; default: 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(bool $html = false): string { 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(): array { return [ 'label' => $this->getLabel(), '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) ]; } /** * Return the state indicated by this perfdata * * @return int */ public function getState(): int { if (! is_numeric($this->value)) { return ServiceStates::UNKNOWN; } if (! $this->criticalThreshold->contains($this->value)) { return ServiceStates::CRITICAL; } if (! $this->warningThreshold->contains($this->value)) { return ServiceStates::WARNING; } return ServiceStates::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): bool { if (($state = $this->getState()) === ($rhsState = $rhs->getState())) { return $this->getPercentage() > $rhs->getPercentage(); } if ($state === ServiceStates::CRITICAL) { return true; } if ($state === ServiceStates::UNKNOWN) { return $rhsState !== ServiceStates::CRITICAL; } if ($state === ServiceStates::WARNING) { return $rhsState === ServiceStates::OK; } 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(); } }