223 lines
4.7 KiB
PHP
223 lines
4.7 KiB
PHP
<?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();
|
|
}
|