From 9229e460d19bcbc19a1ebe07784760344a553889 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 8 Jun 2015 17:09:24 +0200 Subject: [PATCH] NotificationQuery: Use subqueries to fetch host- and service-notifications refs #9009 --- .../Backend/Ido/Query/NotificationQuery.php | 195 +++++++++--------- .../Monitoring/DataView/Notification.php | 55 ++++- 2 files changed, 143 insertions(+), 107 deletions(-) diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php index 0133dc637..ed8a1a911 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php @@ -3,136 +3,127 @@ namespace Icinga\Module\Monitoring\Backend\Ido\Query; +use Zend_Db_Expr; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for host and service notifications + */ class NotificationQuery extends IdoQuery { + /** + * {@inheritdoc} + */ protected $columnMap = array( - 'notification' => array( - 'notification_output' => 'n.output', - 'notification_start_time' => 'UNIX_TIMESTAMP(n.start_time)', - 'notification_state' => 'n.state', - 'notification_object_id' => 'n.object_id' - ), - 'objects' => array( - 'host' => 'o.name1 COLLATE latin1_general_ci', - 'host_name' => 'o.name1', - 'service' => 'o.name2 COLLATE latin1_general_ci', - 'service_description' => 'o.name2' - ), - 'contact' => array( - 'contact' => 'c_o.name1 COLLATE latin1_general_ci', - 'notification_contact_name' => 'c_o.name1', - 'contact_object_id' => 'c_o.object_id' - ), - 'command' => array( - 'notification_command' => 'cmd_o.name1' - ), - 'acknowledgement' => array( - 'acknowledgement_entry_time' => 'UNIX_TIMESTAMP(a.entry_time)', - 'acknowledgement_author_name' => 'a.author_name', - 'acknowledgement_comment_data' => 'a.comment_data' + 'notifications' => array( + 'notification_state' => 'n.notification_state', + 'notification_start_time' => 'n.notification_start_time', + 'notification_contact_name' => 'n.notification_contact_name', + 'notification_output' => 'n.notification_output', + 'notification_object_id' => 'n.notification_object_id', + 'contact_object_id' => 'n.contact_object_id', + 'acknowledgement_entry_time' => 'n.acknowledgement_entry_time', + 'acknowledgement_author_name' => 'n.acknowledgement_author_name', + 'acknowledgement_comment_data' => 'n.acknowledgement_comment_data', + 'object_type' => 'n.object_type' ), 'hosts' => array( - 'host_display_name' => 'CASE WHEN sh.display_name IS NOT NULL THEN sh.display_name ELSE h.display_name END' + 'host_display_name' => 'n.host_display_name', + 'host_name' => 'n.host_name' ), 'services' => array( - 'service_display_name' => 's.display_name' + 'service_description' => 'n.service_description', + 'service_display_name' => 'n.service_display_name', + 'service_host_name' => 'n.service_host_name' ) ); /** - * Fetch basic information about notifications + * The union + * + * @var Zend_Db_Select + */ + protected $notificationQuery; + + /** + * Subqueries used for the notification query + * + * @var IdoQuery[] + */ + protected $subQueries = array(); + + /** + * {@inheritdoc} */ protected function joinBaseTables() { + $this->notificationQuery = $this->db->select(); $this->select->from( - array('n' => $this->prefix . 'notifications'), + array('n' => $this->notificationQuery), array() ); - $this->joinedVirtualTables = array('notification' => true); + $this->joinedVirtualTables['notifications'] = true; } /** - * Fetch description of each affected host/service + * Join hosts */ - protected function joinObjects() - { - $this->select->join( - array('o' => $this->prefix . 'objects'), - 'n.object_id = o.object_id AND o.is_active = 1 AND o.objecttype_id IN (1, 2)', - array() - ); - } - - /** - * Fetch name of involved contacts and/or contact groups - */ - protected function joinContact() - { - $this->select->join( - array('c' => $this->prefix . 'contactnotifications'), - 'n.notification_id = c.notification_id', - array() - ); - $this->select->join( - array('c_o' => $this->prefix . 'objects'), - 'c.contact_object_id = c_o.object_id', - array() - ); - } - - /** - * Fetch name of the command which was used to send out a notification - */ - protected function joinCommand() - { - $this->select->join( - array('cmd_c' => $this->prefix . 'contactnotifications'), - 'n.notification_id = cmd_c.notification_id', - array() - ); - $this->select->joinLeft( - array('cmd_m' => $this->prefix . 'contactnotificationmethods'), - 'cmd_c.contactnotification_id = cmd_m.contactnotification_id', - array() - ); - $this->select->joinLeft( - array('cmd_o' => $this->prefix . 'objects'), - 'cmd_m.command_object_id = cmd_o.object_id', - array() - ); - } - - protected function joinAcknowledgement() - { - $this->select->joinLeft( - array('a' => $this->prefix . 'acknowledgements'), - 'n.object_id = a.object_id', - array() - ); - } - protected function joinHosts() { - $this->select->joinLeft( - array('h' => $this->prefix . 'hosts'), - 'h.host_object_id = o.object_id', - array() + $columns = array_keys($this->columnMap['notifications'] + $this->columnMap['hosts']); + foreach (array_keys($this->columnMap['services']) as $column) { + $columns[$column] = new Zend_Db_Expr('NULL'); + } + $hosts = $this->createSubQuery('hostnotification', $columns); + $this->subQueries[] = $hosts; + $this->notificationQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * Join services + */ + protected function joinServices() + { + $columns = array_keys( + $this->columnMap['notifications'] + $this->columnMap['hosts'] + $this->columnMap['services'] ); + $services = $this->createSubQuery('servicenotification', $columns); + $this->subQueries[] = $services; + $this->notificationQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + return parent::order($columnOrAlias, $dir); + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } return $this; } - protected function joinServices() + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) { - $this->select->joinLeft( - array('s' => $this->prefix . 'services'), - 's.service_object_id = o.object_id', - array() - ); - $this->select->joinLeft( - array('sh' => $this->prefix . 'hosts'), - 'sh.host_object_id = s.host_object_id', - array() - ); + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } return $this; } } diff --git a/modules/monitoring/library/Monitoring/DataView/Notification.php b/modules/monitoring/library/Monitoring/DataView/Notification.php index 48d8fd058..9c06fc2ef 100644 --- a/modules/monitoring/library/Monitoring/DataView/Notification.php +++ b/modules/monitoring/library/Monitoring/DataView/Notification.php @@ -5,6 +5,19 @@ namespace Icinga\Module\Monitoring\DataView; class Notification extends DataView { + /** + * {@inheritdoc} + */ + public function isValidFilterTarget($column) + { + if ($column[0] === '_' + && preg_match('/^_(?:host|service)_/', $column) + ) { + return true; + } + return parent::isValidFilterTarget($column); + } + /** * Retrieve columns provided by this view * @@ -13,30 +26,62 @@ class Notification extends DataView public function getColumns() { return array( - 'host_name', - 'service_description', 'notification_state', 'notification_start_time', 'notification_contact_name', 'notification_output', - 'notification_command', + 'notification_object_id', + 'contact_object_id', + 'acknowledgement_entry_time', + 'acknowledgement_author_name', + 'acknowledgement_comment_data', 'host_display_name', - 'service_display_name' + 'host_name', + 'object_type', + 'service_description', + 'service_display_name', + 'service_host_name' ); } + /** + * {@inheritdoc} + */ public function getSortRules() { return array( 'notification_start_time' => array( 'order' => self::SORT_DESC, 'title' => 'Notification Start' + ), + 'host_display_name' => array( + 'columns' => array( + 'host_display_name', + 'service_display_name' + ), + 'order' => self::SORT_ASC + ), + 'service_display_name' => array( + 'columns' => array( + 'service_display_name', + 'host_display_name' + ), + 'order' => self::SORT_ASC ) ); } + /** + * {@inheritdoc} + */ public function getFilterColumns() { - return array('host', 'service', 'contact'); + return array( + 'contact', + 'host', 'host_alias', + 'hostgroup', 'hostgroup_alias', 'hostgroup_name', + 'service', + 'servicegroup', 'servicegroup_alias', 'servicegroup_name' + ); } }