From becd7d0504c09307ba7f0e6eae792c25742d2ce9 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 3 Jul 2018 14:41:55 +0200 Subject: [PATCH] Introduce monitoring/PluginOutputHook refs #3257 --- .../controllers/HostController.php | 3 +- .../controllers/ListController.php | 6 +- .../views/helpers/PluginOutput.php | 14 ++- .../views/scripts/list/hosts.phtml | 2 +- .../views/scripts/list/services.phtml | 2 +- .../scripts/show/components/output.phtml | 4 +- modules/monitoring/doc/20-Hooks.md | 85 ++++++++++++++ .../Monitoring/Hook/PluginOutputHook.php | 46 ++++++++ .../Web/Helper/PluginOutputHookRenderer.php | 105 ++++++++++++++++++ 9 files changed, 259 insertions(+), 8 deletions(-) create mode 100644 modules/monitoring/library/Monitoring/Hook/PluginOutputHook.php create mode 100644 modules/monitoring/library/Monitoring/Web/Helper/PluginOutputHookRenderer.php diff --git a/modules/monitoring/application/controllers/HostController.php b/modules/monitoring/application/controllers/HostController.php index bb98b2a8f..b0cda11dd 100644 --- a/modules/monitoring/application/controllers/HostController.php +++ b/modules/monitoring/application/controllers/HostController.php @@ -100,7 +100,8 @@ class HostController extends MonitoredObjectController 'service_active_checks_enabled', 'service_passive_checks_enabled', 'current_check_attempt' => 'service_current_check_attempt', - 'max_check_attempts' => 'service_max_check_attempts' + 'max_check_attempts' => 'service_max_check_attempts', + 'service_check_command' )); $this->applyRestriction('monitoring/filter/objects', $query); $this->view->services = $query->where('host_name', $this->object->getName()); diff --git a/modules/monitoring/application/controllers/ListController.php b/modules/monitoring/application/controllers/ListController.php index ccdb149d4..4bbb39fb5 100644 --- a/modules/monitoring/application/controllers/ListController.php +++ b/modules/monitoring/application/controllers/ListController.php @@ -76,7 +76,8 @@ class ListController extends Controller 'host_last_state_change' => $stateChangeColumn, 'host_notifications_enabled', 'host_active_checks_enabled', - 'host_passive_checks_enabled' + 'host_passive_checks_enabled', + 'host_check_command' ), $this->addColumns())); $this->applyRestriction('monitoring/filter/objects', $hosts); @@ -156,7 +157,8 @@ class ListController extends Controller 'service_severity', 'service_notifications_enabled', 'service_active_checks_enabled', - 'service_passive_checks_enabled' + 'service_passive_checks_enabled', + 'service_check_command' ), $this->addColumns())); $this->applyRestriction('monitoring/filter/objects', $services); diff --git a/modules/monitoring/application/views/helpers/PluginOutput.php b/modules/monitoring/application/views/helpers/PluginOutput.php index 1c77b578d..f10e516ff 100644 --- a/modules/monitoring/application/views/helpers/PluginOutput.php +++ b/modules/monitoring/application/views/helpers/PluginOutput.php @@ -76,19 +76,31 @@ class Zend_View_Helper_PluginOutput extends Zend_View_Helper_Abstract 'hookRenderer = (new \Icinga\Module\Monitoring\Web\Helper\PluginOutputHookRenderer())->registerHooks(); + } + /** * Render plugin output * * @param string $output * @param bool $raw + * @param string $command Check command * * @return string */ - public function pluginOutput($output, $raw = false) + public function pluginOutput($output, $raw = false, $command = null) { if (empty($output)) { return ''; } + if ($command !== null) { + $output = $this->hookRenderer->render($command, $output, ! $raw); + } $output = preg_replace('~]*>~', "\n", $output); if (preg_match('~<[^>]*["/\'][^>]*>~', $output)) { // HTML diff --git a/modules/monitoring/application/views/scripts/list/hosts.phtml b/modules/monitoring/application/views/scripts/list/hosts.phtml index da00fccc6..e00038bf6 100644 --- a/modules/monitoring/application/views/scripts/list/hosts.phtml +++ b/modules/monitoring/application/views/scripts/list/hosts.phtml @@ -82,7 +82,7 @@ if (! $this->compact): ?> hostFlags($host) ?> -

pluginOutput($this->ellipsis($host->host_output, 10000), true) ?>

+

pluginOutput($this->ellipsis($host->host_output, 10000), true, $host->host_check_command) ?>

addColumns as $col): ?>
diff --git a/modules/monitoring/application/views/scripts/list/services.phtml b/modules/monitoring/application/views/scripts/list/services.phtml index c9f1e855b..25a18781a 100644 --- a/modules/monitoring/application/views/scripts/list/services.phtml +++ b/modules/monitoring/application/views/scripts/list/services.phtml @@ -86,7 +86,7 @@ if (! $this->compact): ?>
perfdata($service->service_perfdata, true, 5) ?>
-

pluginOutput($this->ellipsis($service->service_output, 10000), true) ?>

+

pluginOutput($this->ellipsis($service->service_output, 10000), true, $service->service_check_command) ?>

addColumns as $col): ?> diff --git a/modules/monitoring/application/views/scripts/show/components/output.phtml b/modules/monitoring/application/views/scripts/show/components/output.phtml index e4c0fd0a8..c450319a1 100644 --- a/modules/monitoring/application/views/scripts/show/components/output.phtml +++ b/modules/monitoring/application/views/scripts/show/components/output.phtml @@ -1,3 +1,3 @@

translate('Plugin Output') ?>

-pluginOutput($object->output) ?> -pluginOutput($object->long_output) ?> +pluginOutput($object->output, false, $object->check_command) ?> +pluginOutput($object->long_output, false, $object->check_command) ?> diff --git a/modules/monitoring/doc/20-Hooks.md b/modules/monitoring/doc/20-Hooks.md index 373f7ebea..5d38843d6 100644 --- a/modules/monitoring/doc/20-Hooks.md +++ b/modules/monitoring/doc/20-Hooks.md @@ -74,3 +74,88 @@ class Simple extends DetailviewExtensionHook ### How it looks ![Screenshot](img/hooks-detailviewextension-01.png) + +## Plugin Output Hook + +The Plugin Output Hook allows you to rewrite the plugin output based on check commands. You have to implement the +following methods: + +* `getCommands()` +* and `render()` + +With `getCommands()` you specify for which commands the provided hook is responsible for. You may return a single +command as string or a list of commands as array. If you want your hook to be responsible for every command, you have to +specify the `*`. + +In `render()` you rewrite the plugin output based on check commands. The parameter `$command` specifies the check +command of the host or service and `$output` specifies the plugin output. The parameter `$detail` tells you +whether the output is requested from the detail area of the host or service. + +Do not use complex logic for rewriting plugin output in list views because of the performance impact! + +You have to return the rewritten plugin output as string. It is also possible to return a HTML string here. +Please refer to `\Icinga\Module\Monitoring\Web\Helper\PluginOutputPurifier` for a list of allowed tags. + +Please also have a look at the following examples. + +**Example hook which is responsible for disk checks:** + +```php +', explode(';', $output)); + } +} +``` + +**Example hook which is responsible for disk and procs checks:** + +```php +', explode(';', $output)); + } + break; + case 'procs': + $output = preg_replace('/(\d)+/', '$1', $output); + break; + } + + return $output; + } +} +``` diff --git a/modules/monitoring/library/Monitoring/Hook/PluginOutputHook.php b/modules/monitoring/library/Monitoring/Hook/PluginOutputHook.php new file mode 100644 index 000000000..52ecd0963 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Hook/PluginOutputHook.php @@ -0,0 +1,46 @@ +getCommands(); + } catch (\Exception $e) { + Logger::error( + 'Failed to get applicable commands from hook "%s". An error occurred: %s', + get_class($hook), + $e + ); + + continue; + } + + if (! is_array($commands)) { + $commands = [$commands]; + } + + foreach ($commands as $command) { + if (! isset($this->commandMap[$command])) { + $this->commandMap[$command] = []; + } + + $this->commandMap[$command][] = $hook; + } + } + + return $this; + } + + protected function renderCommand($command, $output, $detail) + { + if (isset($this->commandMap[$command])) { + foreach ($this->commandMap[$command] as $hook) { + /** @var \Icinga\Module\Monitoring\Hook\PluginOutputHook $hook */ + + try { + $output = $hook->render($command, $output, $detail); + } catch (\Exception $e) { + Logger::error( + 'Failed to render plugin output from hook "%s". An error occurred: %s', + get_class($hook), + $e + ); + + continue; + } + } + } + + return $output; + } + + /** + * Render the given plugin output based on the specified check command + * + * Traverse all hooks which are responsible for the specified check command and call their `render()` methods. + * + * @param string $command Check command + * @param string $output Plugin output + * @param bool $detail Whether the output is requested from the detail area + * + * @return string + */ + public function render($command, $output, $detail) + { + if (empty($this->commandMap)) { + return $output; + } + + $output = $this->renderCommand('*', $output, $detail); + $output = $this->renderCommand($command, $output, $detail); + + return $output; + } +}
escape($host->$col) ?>