diff options
Diffstat (limited to 'library/Icinga/Application/Hook/HealthHook.php')
-rw-r--r-- | library/Icinga/Application/Hook/HealthHook.php | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/library/Icinga/Application/Hook/HealthHook.php b/library/Icinga/Application/Hook/HealthHook.php new file mode 100644 index 0000000..f6420b5 --- /dev/null +++ b/library/Icinga/Application/Hook/HealthHook.php @@ -0,0 +1,222 @@ +<?php +/* Icinga Web 2 | (c) 2021 Icinga GmbH | GPLv2+ */ + +namespace Icinga\Application\Hook; + +use Exception; +use Icinga\Application\Hook; +use Icinga\Application\Logger; +use Icinga\Data\DataArray\ArrayDatasource; +use Icinga\Exception\IcingaException; +use ipl\Web\Url; +use LogicException; + +abstract class HealthHook +{ + /** @var int */ + const STATE_OK = 0; + + /** @var int */ + const STATE_WARNING = 1; + + /** @var int */ + const STATE_CRITICAL = 2; + + /** @var int */ + const STATE_UNKNOWN = 3; + + /** @var int The overall state */ + protected $state; + + /** @var string Message describing the overall state */ + protected $message; + + /** @var array Available metrics */ + protected $metrics; + + /** @var Url Url to a graphical representation of the available metrics */ + protected $url; + + /** + * Get overall state + * + * @return int + */ + public function getState() + { + return $this->state; + } + + /** + * Set overall state + * + * @param int $state + * + * @return $this + */ + public function setState($state) + { + $this->state = $state; + + return $this; + } + + /** + * Get the message describing the overall state + * + * @return string + */ + public function getMessage() + { + return $this->message; + } + + /** + * Set the message describing the overall state + * + * @param string $message + * + * @return $this + */ + public function setMessage($message) + { + $this->message = $message; + + return $this; + } + + /** + * Get available metrics + * + * @return array + */ + public function getMetrics() + { + return $this->metrics; + } + + /** + * Set available metrics + * + * @param array $metrics + * + * @return $this + */ + public function setMetrics(array $metrics) + { + $this->metrics = $metrics; + + return $this; + } + + /** + * Get the url to a graphical representation of the available metrics + * + * @return Url + */ + public function getUrl() + { + return $this->url; + } + + /** + * Set the url to a graphical representation of the available metrics + * + * @param Url $url + * + * @return $this + */ + public function setUrl(Url $url) + { + $this->url = $url; + + return $this; + } + + /** + * Collect available health data from hooks + * + * @return ArrayDatasource + */ + final public static function collectHealthData() + { + $checks = []; + foreach (Hook::all('health') as $hook) { + /** @var self $hook */ + + try { + $hook->checkHealth(); + $url = $hook->getUrl(); + $state = $hook->getState(); + $message = $hook->getMessage(); + $metrics = $hook->getMetrics(); + } catch (Exception $e) { + Logger::error('Failed to check health: %s', $e); + + $state = self::STATE_UNKNOWN; + $message = IcingaException::describe($e); + $metrics = null; + $url = null; + } + + $checks[] = (object) [ + 'module' => $hook->getModuleName(), + 'name' => $hook->getName(), + 'url' => $url ? $url->getAbsoluteUrl() : null, + 'state' => $state, + 'message' => $message, + 'metrics' => (object) $metrics + ]; + } + + return (new ArrayDatasource($checks)) + ->setKeyColumn('name'); + } + + /** + * Get the name of the hook + * + * Only used in API responses to differentiate it from other hooks of the same module. + * + * @return string + */ + public function getName() + { + $classPath = get_class($this); + $parts = explode('\\', $classPath); + $className = array_pop($parts); + + if (substr($className, -4) === 'Hook') { + $className = substr($className, 1, -4); + } + + return strtolower($className[0]) . substr($className, 1); + } + + /** + * Get the name of the module providing this hook + * + * @return string + * + * @throws LogicException + */ + public function getModuleName() + { + $classPath = get_class($this); + if (substr($classPath, 0, 14) !== 'Icinga\\Module\\') { + throw new LogicException('Not a module hook'); + } + + $withoutPrefix = substr($classPath, 14); + return strtolower(substr($withoutPrefix, 0, strpos($withoutPrefix, '\\'))); + } + + /** + * Check health + * + * Implement this method and set the overall state, message, url and metrics. + * + * @return void + */ + abstract public function checkHealth(); +} |