diff --git a/www/api/class/centreon_customview.class.php b/www/api/class/centreon_customview.class.php deleted file mode 100644 index 2c0cb4c7717..00000000000 --- a/www/api/class/centreon_customview.class.php +++ /dev/null @@ -1,152 +0,0 @@ -. - * - * Linking this program statically or dynamically with other modules is making a - * combined work based on this program. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this program give Centreon - * permission to link this program with independent modules to produce an executable, - * regardless of the license terms of these independent modules, and to copy and - * distribute the resulting executable under terms of Centreon choice, provided that - * Centreon also meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module which is not - * derived from this program. If you modify this program, you may extend this - * exception to your version of the program, but you are not obliged to do so. If you - * do not wish to do so, delete this exception statement from your version. - * - * For more information : contact@centreon.com - * - */ - -require_once dirname(__FILE__) . "/webService.class.php"; -require_once _CENTREON_PATH_ . 'www/class/centreonCustomView.class.php'; - -class CentreonHomeCustomview extends CentreonWebService -{ - /** - * CentreonHomeCustomview constructor. - */ - public function __construct() - { - parent::__construct(); - } - - /** - * @return array - */ - public function getListSharedViews() - { - global $centreon; - - $views = array(); - - $query = 'SELECT custom_view_id, name FROM (' . - 'SELECT cv.custom_view_id, cv.name FROM custom_views cv ' . - 'INNER JOIN custom_view_user_relation cvur ON cv.custom_view_id = cvur.custom_view_id ' . - 'WHERE (cvur.user_id = ' . $centreon->user->user_id . ' ' . - 'OR cvur.usergroup_id IN ( ' . - 'SELECT contactgroup_cg_id ' . - 'FROM contactgroup_contact_relation ' . - 'WHERE contact_contact_id = ' . $centreon->user->user_id . ' ' . - ') ' . - ') ' . - 'UNION ' . - 'SELECT cv2.custom_view_id, cv2.name FROM custom_views cv2 ' . - 'WHERE cv2.public = 1 ) as d ' . - 'WHERE d.custom_view_id NOT IN (' . - 'SELECT cvur2.custom_view_id FROM custom_view_user_relation cvur2 ' . - 'WHERE cvur2.user_id = ' . $centreon->user->user_id . ' ' . - 'AND cvur2.is_consumed = 1) '; - - $dbResult = $this->pearDB->query($query); - while ($row = $dbResult->fetch()) { - $views[] = array( - 'id' => $row['custom_view_id'], - 'text' => $row['name'] - ); - } - return array( - 'items' => $views, - 'total' => count($views) - ); - } - - /** - * @return array - */ - public function getLinkedUsers() - { - // Check for select2 'q' argument - if (false === isset($this->arguments['q'])) { - $customViewId = 0; - } else { - $customViewId = $this->arguments['q']; - } - - global $centreon; - $viewObj = new CentreonCustomView($centreon, $this->pearDB); - - return $viewObj->getUsersFromViewId($customViewId); - } - - /** - * @return array - */ - public function getLinkedUsergroups() - { - // Check for select2 'q' argument - if (false === isset($this->arguments['q'])) { - $customViewId = 0; - } else { - $customViewId = $this->arguments['q']; - } - - global $centreon; - $viewObj = new CentreonCustomView($centreon, $this->pearDB); - - return $viewObj->getUsergroupsFromViewId($customViewId); - } - - /** - * Get the list of views - * - * @return array - */ - public function getListViews() - { - global $centreon; - $viewObj = new CentreonCustomView($centreon, $this->pearDB); - - $tabs = array(); - $tabsDb = $viewObj->getCustomViews(); - foreach ($tabsDb as $key => $tab) { - $tabs[] = array( - 'default' => false, - 'name' => $tab['name'], - 'custom_view_id' => $tab['custom_view_id'], - 'public' => $tab['public'], - 'nbCols' => $tab['layout'] - ); - } - - return array( - 'current' => $viewObj->getCurrentView(), - 'tabs' => $tabs - ); - } -} diff --git a/www/api/class/centreon_home_customview.class.php b/www/api/class/centreon_home_customview.class.php index 077edc93fd0..9e910509872 100644 --- a/www/api/class/centreon_home_customview.class.php +++ b/www/api/class/centreon_home_customview.class.php @@ -321,6 +321,25 @@ public function getPreferences() return $tpl->fetch("widgetParam.html"); } + /** + * Get preferences by widget id + * + * @return array The widget preferences + * @throws \Exception When missing argument + */ + public function getPreferencesByWidgetId() + { + global $centreon; + + if (!isset($this->arguments['widgetId'])) { + throw new \Exception('Missing argument : widgetId'); + } + $widgetId = $this->arguments['widgetId']; + $widgetObj = new CentreonWidget($centreon, $this->pearDB); + + return $widgetObj->getWidgetPreferences($widgetId); + } + /** * Authorize to access to the action * diff --git a/www/api/class/centreon_metric.class.php b/www/api/class/centreon_metric.class.php index af63c6d8c14..30553881ba6 100644 --- a/www/api/class/centreon_metric.class.php +++ b/www/api/class/centreon_metric.class.php @@ -38,7 +38,7 @@ require_once _CENTREON_PATH_ . "/www/class/centreonGraphService.class.php"; require_once _CENTREON_PATH_ . "/www/class/centreonGraphPoller.class.php"; require_once _CENTREON_PATH_ . "/www/class/centreonGraphStatus.class.php"; -require_once dirname(__FILE__) . "/webService.class.php"; +require_once __DIR__ . "/webService.class.php"; class CentreonMetric extends CentreonWebService { @@ -155,6 +155,40 @@ protected function getListByService() ); } + /** + * Get last metrics value by services or/and metrics + * + * @return array | null if arguments are not set + */ + public function getLastMetricsData() + { + if (!isset($this->arguments['services']) && !isset($this->arguments['metrics'])) { + self::sendResult([]); + } + + return $this->lastMetricsData( + $this->arguments['services'] ?? '', + $this->arguments['metrics'] ?? '' + ); + } + + + /** + * Get metrics data by service or/and metrics + * + * @return array | null if arguments are not set + */ + public function getMetricsData() + { + if (!isset($this->arguments['services']) && !isset($this->arguments['metrics'])) { + self::sendResult([]); + } + + return $this->metricsData( + $this->arguments['services'] ?? '', + $this->arguments['metrics'] ?? '' + ); + } /** * Get metrics datas for a service @@ -163,13 +197,13 @@ protected function getListByService() */ public function getMetricsDataByService() { - if (false === isset($this->arguments['ids'])) { - self::sendResult(array()); + if (!isset($this->arguments['ids'])) { + self::sendResult([]); } /* Get the list of service ID */ $ids = explode(',', $this->arguments['ids']); - $result = array(); + $result = []; if (isset($this->arguments['type']) && $this->arguments['type'] === 'ng') { foreach ($ids as $id) { @@ -214,6 +248,294 @@ public function getMetricsDataByMetric() return $result; } + /** + * Check acl for user + * + * @param int $hostId Host id to check + * @param int $serviceId Service id to check + * @param string $aclGroups String with user acl groups + * @param int $isAdmin User is admin or not + * + * @return bool if the user is allowed to get service information + */ + private function checkAcl($hostId, $serviceId, ?array $aclGroups, $isAdmin = true): bool + { + if (!$isAdmin) { + $query = 'SELECT service_id ' . + 'FROM centreon_acl ' . + 'WHERE host_id = :hostId ' . + 'AND service_id = :serviceId ' . + 'AND group_id IN (' . $aclGroups . ')'; + + $stmt = $this->pearDBMonitoring->prepare($query); + $stmt->bindParam(':hostId', $hostId, PDO::PARAM_INT); + $stmt->bindParam(':serviceId', $serviceId, PDO::PARAM_INT); + $dbResult = $stmt->execute(); + if (!$dbResult || $stmt->rowCount() === 0) { + return false; + } + } + + return true; + } + + /** + * Get array builded from arguments + * + * @param string $services List of services (like hostId_serviceId,hostId2_serviceId2,...) + * @param string $metrics List of metrics (like metricId,metricId2,...) + * + * @return mixed + */ + private function manageMetricsDataArguments($services, $metrics) + { + global $centreon; + + $userId = $centreon->user->user_id; + $isAdmin = $centreon->user->admin; + $aclGroups = null; + + /* Get ACL if user is not admin */ + if (!$isAdmin) { + $acl = new CentreonACL($userId, $isAdmin); + $aclGroups = $acl->getAccessGroupsString(); + } + + if (!isset($this->arguments['start']) || !is_numeric($this->arguments['start']) + || !isset($this->arguments['end']) || !is_numeric($this->arguments['end']) + ) { + throw new RestBadRequestException("Bad parameters"); + } + + /* + * Format: + * { + * "hostId_serviceId": {}, # no metricsId means: all metrics + * "hostId2_serviceId2: { "metricId": 1, "metricId2": 1 } + * } + */ + $selectedMetrics = []; + if (is_string($services) && strlen($services) > 0) { + foreach (explode(',', $services) as $service) { + list($hostId, $serviceId) = explode('_', $service); + if (!is_numeric($hostId) || !is_numeric($serviceId)) { + continue; + } + if (isset($selectedMetrics[$service])) { + continue; + } + + if (!$this->checkAcl($hostId, $serviceId, $aclGroups, $isAdmin)) { + continue; + } + $selectedMetrics[$service] = []; + } + } + + if (is_string($metrics) && strlen($metrics) > 0) { + $filter = ''; + $filterAppend = ''; + $queryValues = []; + foreach (explode(',', $metrics) as $metricId) { + if (!is_numeric($metricId)) { + continue; + } + $filter .= $filterAppend . ' :metric' . $metricId; + $queryValues[':metric' . $metricId] = $metricId; + $filterAppend = ','; + } + + if ($filter === '') { + return $selectedMetrics; + } + + + + $stmt = $this->pearDBMonitoring->prepare( + 'SELECT metric_id, host_id, service_id + FROM metrics, index_data + WHERE metrics.metric_id IN (' . $filter. ') + AND metrics.index_id = index_data.id' + ); + foreach ($queryValues as $param => $value) { + $stmt->bindValue($param, $value, PDO::PARAM_INT); + } + $stmt->execute(); + + while ($row = $stmt->fetch()) { + if (isset($selectedMetrics[$row['host_id'] . '_' . $row['service_id']]) + && count($selectedMetrics[$row['host_id'] . '_' . $row['service_id']]) <= 0 + ) { + continue; + } + if (!isset($selectedMetrics[$row['host_id'] . '_' . $row['service_id']])) { + if (!$this->checkAcl($row['host_id'], $row['service_id'], $aclGroups, $isAdmin)) { + continue; + } + $selectedMetrics[$row['host_id'] . '_' . $row['service_id']] = array(); + } + $selectedMetrics[$row['host_id'] . '_' . $row['service_id']][$row['metric_id']] = 1; + } + } + + return $selectedMetrics; + } + + /** + * Get last data for metrics (by services and/or metrics) + * + * @param string $services List of services (like hostId_serviceId,hostId2_serviceId2,...) + * @param string $metrics List of metrics (like metricId,metricId2,...) + * + * @return array + * + * @throws Exception + * @throws RestBadRequestException + * @throws RestForbiddenException + * @throws RestNotFoundException + */ + protected function lastMetricsData($services, $metrics) + { + global $centreon; + + $userId = $centreon->user->user_id; + $isAdmin = $centreon->user->admin; + $aclGroups = null; + + $query = ''; + $filterHostIds = []; + $filterServiceIds = []; + $filterMetricIds = []; + + if (is_string($services) && strlen($services) > 0) { + foreach (explode(',', $services) as $service) { + list($hostId, $serviceId) = explode('_', $service); + if (!is_numeric($hostId) || !is_numeric($serviceId)) { + continue; + } + $filterHostIds[':host' . $hostId] = $hostId; + $filterServiceIds[':service' . $serviceId] = $serviceId; + } + + if (!empty($filterHostIds) && !empty($filterServiceIds)) { + $query = ' + SELECT i.host_id, i.service_id, m.* + FROM index_data i, metrics m + WHERE i.host_id IN (' . implode(',', array_keys($filterHostIds)) . ') + AND i.service_id IN (' . implode(',', array_keys($filterServiceIds)) . ') + AND i.id = m.index_id'; + } + } + + if (is_string($metrics) && strlen($metrics) > 0) { + foreach (explode(',', $metrics) as $metricId) { + if (!is_numeric($metricId)) { + continue; + } + $filterMetricIds[':metric' . $metricId] = $metricId; + } + + if (!empty($filterMetricIds)) { + if ($query !== '') { + $query .= ' UNION '; + } + $query .= ' + SELECT i.host_id, i.service_id, m.* + FROM metrics m, index_data i + WHERE m.metric_id IN (' . implode(',', array_keys($filterMetricIds)) . ') + AND m.index_id = i.id'; + } + } + + if ($query === '') { + throw new \Exception("No metrics found"); + } + + /* Get ACL if user is not admin */ + if (!$isAdmin) { + $acl = new CentreonACL($userId, $isAdmin); + $aclGroups = $acl->getAccessGroupsString(); + $query = ' + SELECT ms.* FROM (' . $query . ') as ms, centreon_acl ca + WHERE EXISTS ( + SELECT 1 + FROM centreon_acl ca + WHERE ca.host_id = ms.host_id + AND ca.service_id = ms.service_id + AND ca.group_id IN (' . $aclGroups . '))'; + } + + $stmt = $this->pearDBMonitoring->prepare($query); + foreach ([$filterHostIds, $filterServiceIds, $filterMetricIds] as $filterParams) { + foreach ($filterParams as $param => $value) { + $stmt->bindValue($param, $value, PDO::PARAM_INT); + } + } + $stmt->execute(); + + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * Get data for metrics (by services and/or metrics) + * + * @param string $services List of services (like hostId_serviceId,hostId2_serviceId2,...) + * @param string $metrics List of metrics (like metricId,metricId2,...) + * + * @return array + * + * @throws Exception + * @throws RestBadRequestException + * @throws RestForbiddenException + * @throws RestNotFoundException + */ + protected function metricsData($services, $metrics) + { + global $centreon; + + $selectedMetrics = $this->manageMetricsDataArguments($services, $metrics); + $multipleServices = count(array_keys($selectedMetrics)) > 1 ? true : false; + + /* Prepare graph */ + try { + $graph = new CentreonGraphNg($centreon->user->user_id); + $graph->setMultipleServices($multipleServices); + foreach ($selectedMetrics as $service => $metrics) { + list($hostId, $serviceId) = explode('_', $service); + if (count(array_keys($metrics)) <= 0) { + $graph->addServiceMetrics($hostId, $serviceId); + } else { + $graph->addServiceCustomMetrics($hostId, $serviceId, $metrics); + } + } + } catch (Exception $e) { + throw new RestNotFoundException("Graph not found"); + } + + $result = $graph->getGraph($this->arguments['start'], $this->arguments['end']); + + if (!$multipleServices && count($selectedMetrics) > 0) { + /* Get extra information (downtime/acknowledgment) */ + $result['acknowledge'] = array(); + $result['downtime'] = array(); + list($hostId, $serviceId) = explode('_', array_key_first($selectedMetrics)); + $result['acknowledge'] = $this->getAcknowledgements( + (int)$hostId, + (int)$serviceId, + (int)$this->arguments['start'], + (int)$this->arguments['end'] + ); + $result['downtime'] = $this->getDowntimePeriods( + (int)$hostId, + (int)$serviceId, + (int)$this->arguments['start'], + (int)$this->arguments['end'] + ); + } + + return $result; + } + /** * Get the status for a service * @@ -237,10 +559,8 @@ public function getStatusByService() } /* Validate options */ - if (false === isset($this->arguments['start']) || - false === is_numeric($this->arguments['start']) || - false === isset($this->arguments['end']) || - false === is_numeric($this->arguments['end']) + if (!isset($this->arguments['start']) || !is_numeric($this->arguments['start']) + || !isset($this->arguments['end']) || !is_numeric($this->arguments['end']) ) { throw new RestBadRequestException("Bad parameters"); } @@ -292,7 +612,7 @@ public function getStatusByService() throw new \Exception("An error occured"); } - if (0 == $stmt->rowCount()) { + if ($stmt->rowCount() === 0) { throw new RestForbiddenException("Access denied"); } } @@ -313,7 +633,7 @@ public function getStatusByService() $query = 'SELECT `value` FROM `options` WHERE `key` = "display_comment_chart"'; $res = $this->pearDB->query($query); $row = $res->fetch(); - if (false === is_null($row) && $row['value'] === '1') { + if ($row && $row['value'] === '1') { $queryComment = 'SELECT `entry_time`, `author`, `data` ' . 'FROM comments ' . 'WHERE host_id = :hostId ' . @@ -379,10 +699,8 @@ protected function serviceDatasNg($id, $metric = null) $aclGroups = $acl->getAccessGroupsString(); } - if (false === isset($this->arguments['start']) || - false === is_numeric($this->arguments['start']) || - false === isset($this->arguments['end']) || - false === is_numeric($this->arguments['end']) + if (!isset($this->arguments['start']) || !is_numeric($this->arguments['start']) + || !isset($this->arguments['end']) || !is_numeric($this->arguments['end']) ) { throw new RestBadRequestException("Bad parameters"); } @@ -412,7 +730,7 @@ protected function serviceDatasNg($id, $metric = null) if (!$dbResult) { throw new \Exception("An error occured"); } - if (0 == $stmt->rowCount()) { + if ($stmt->rowCount() === 0) { throw new RestForbiddenException("Access denied"); } } @@ -428,7 +746,7 @@ protected function serviceDatasNg($id, $metric = null) } catch (Exception $e) { throw new RestNotFoundException("Graph not found"); } - + $result = $graph->getGraph($this->arguments['start'], $this->arguments['end']); /* Get extra information (downtime/acknowledgment) */ @@ -437,9 +755,9 @@ protected function serviceDatasNg($id, $metric = null) $query = 'SELECT `value` FROM `options` WHERE `key` = "display_downtime_chart"'; $res = $this->pearDB->query($query); - + $row = $res->fetch(); - if (false === is_null($row) && $row['value'] === '1') { + if ($row && $row['value'] === '1') { $result['acknowledge'] = $this->getAcknowlegePeriods($hostId, $serviceId, $start, $end); $result['downtime'] = $this->getDowntimePeriods($hostId, $serviceId, $start, $end); } @@ -518,7 +836,7 @@ protected function serviceDatas($id, $metric = null) if (!$dbResult) { throw new \Exception("An error occured"); } - if (0 == $stmt->rowCount()) { + if ($stmt->rowCount() === 0) { throw new RestForbiddenException("Access denied"); } } @@ -651,7 +969,7 @@ public function getMetricsDataByPoller() } catch (\Exception $e) { throw new RestNotFoundException("Graph not found"); } - + $result = $graphPollerObject->getGraph($start, $end); return array($result); @@ -673,6 +991,32 @@ protected function convertNaN($element) return $element; } + /** + * Get the list of a acknowlegments for a service during a period + * + * @param int $hostId the host id + * @param int $serviceId the service id + * @param int $start the start timestamp + * @param int $end the end timestamp + * + * @return array The list of acknowledgements + */ + protected function getAcknowledgements(int $hostId, int $serviceId, int $start, int $end): array + { + $query = 'SELECT entry_time as start, deletion_time as end, author, comment_data ' . + 'FROM acknowledgements ' . + 'WHERE host_id = :hostId ' . + 'AND service_id = :serviceId ' . + 'AND (entry_time >= :start AND entry_time <= :end)'; + $stmt = $this->pearDBMonitoring->prepare($query); + $stmt->bindValue(':hostId', $hostId, PDO::PARAM_INT); + $stmt->bindValue(':serviceId', $serviceId, PDO::PARAM_INT); + $stmt->bindValue(':start', $start, PDO::PARAM_INT); + $stmt->bindValue(':end', $end, PDO::PARAM_INT); + $stmt->execute(); + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + /** * Get the list of a acknowlegment for a service during a period * @@ -701,24 +1045,22 @@ protected function getAcknowlegePeriods($hostId, $serviceId, $start, $end) } /** - * @param int $hostId - * @param int $serviceId - * @param int $start - * @param int $end + * Get list of downtime periods by service + * + * @param int $hostId the host id + * @param int $serviceId the service id + * @param int $start the start timestamp + * @param int $end the end timestamp * * @return array */ - protected function getDowntimePeriods($hostId, $serviceId, $start, $end) + protected function getDowntimePeriods($hostId, $serviceId, $start, $end): array { $query = 'SELECT actual_start_time as start, actual_end_time as end ' . 'FROM downtimes ' . - 'WHERE type = 1 AND host_id = :hostId AND service_id = :serviceId ' . - 'AND (' . - '(actual_start_time <= :end AND :end <= actual_end_time) ' . - 'OR (actual_start_time <= :start AND :start <= actual_end_time) ' . - 'OR (actual_start_time >= :start AND :end >= actual_end_time) ' . - 'OR (actual_start_time IS NOT NULL AND actual_end_time IS NULL) ' . - ')'; + 'WHERE host_id = :hostId AND service_id = :serviceId ' . + 'AND ' . + 'actual_start_time <= :end AND (actual_end_time >= :start OR actual_end_time is NULL)'; $queryValues['hostId'] = (int)$hostId; $queryValues['serviceId'] = (int)$serviceId; $queryValues['end'] = (int)$end; @@ -739,14 +1081,14 @@ protected function executeQueryPeriods($query, $start, $end, $queryValues) $periods = array(); $stmt = $this->pearDBMonitoring->prepare($query); foreach ($queryValues as $key => $value) { - $stmt->bindParam(':' . $key, $value, PDO::PARAM_INT); + $stmt->bindValue(':' . $key, $value, PDO::PARAM_INT); } $dbResult = $stmt->execute(); if (!$dbResult) { throw new \Exception("An error occured"); } - while ($row = $stmt->fetchRow()) { + while ($row = $stmt->fetch()) { $period = array( 'start' => $row['start'], 'end' => $row['end'] diff --git a/www/class/centreonGraphNg.class.php b/www/class/centreonGraphNg.class.php index d541b4fd0aa..4a0f68809d6 100644 --- a/www/class/centreonGraphNg.class.php +++ b/www/class/centreonGraphNg.class.php @@ -48,7 +48,7 @@ class MetricUtils { private static $instance = null; - + /** * Constructor * @@ -57,7 +57,7 @@ class MetricUtils private function __construct() { } - + /** * Singleton create method * @@ -218,7 +218,9 @@ public function __construct($userId) $this->listMetricsId = array(); $this->metrics = array(); $this->vmetrics = array(); + $this->templateInformations = array(); $this->extraDatas = array(); + $this->multipleServices = false; $stmt = $this->dbCs->prepare("SELECT RRDdatabase_path, RRDdatabase_status_path FROM config"); $stmt->execute(); @@ -244,7 +246,19 @@ public function __construct($userId) $this->rrdCachedOptions[$row['config_key']] = $row['config_value']; } } - + + /** + * Set if a graph has multiple services + * + * @param int $multiple set multiple value + * + * @return void + */ + public function setMultipleServices($multiple) + { + $this->multipleServices = $multiple; + } + /** * Get graph result * @@ -475,7 +489,7 @@ private function addRealMetric($metric, $hidden = null) 'max' => $metric['max'], 'virtual' => 0, ); - + $this->cacheAllMetrics['r:' . $metric["metric_name"]] = $metric["metric_id"]; $dsData = $this->getCurveDsConfig($metric); @@ -501,6 +515,15 @@ private function addRealMetric($metric, $hidden = null) (isset($dsData["ds_order"]) && $dsData["ds_order"] ? $dsData["ds_order"] : 0); $this->metrics[$metric['metric_id']]['hidden'] = is_null($hidden) ? 0 : $hidden; + + if (isset($dsData['ds_invert']) && $dsData['ds_invert']) { + if (!is_null($this->metrics[$metric['metric_id']]['min']) && is_numeric($this->metrics[$metric['metric_id']]['min'])) { + $this->metrics[$metric['metric_id']]['min'] = $metric['min'] * -1; + } + if (!is_null($this->metrics[$metric['metric_id']]['max']) && is_numeric($this->metrics[$metric['metric_id']]['max'])) { + $this->metrics[$metric['metric_id']]['max'] = $metric['max'] * -1; + } + } } /** @@ -583,11 +606,12 @@ public function addServiceMetrics($hostId, $serviceId) $this->addRealMetric($metric); } - $stmt = $this->db->prepare("SELECT * - FROM virtual_metrics - WHERE index_id = :index_id - AND vmetric_activate = '1' - "); + $stmt = $this->db->prepare( + "SELECT * + FROM virtual_metrics + WHERE index_id = :index_id + AND vmetric_activate = '1'" + ); $stmt->bindParam(':index_id', $indexId, PDO::PARAM_INT); $stmt->execute(); $vmetrics = $stmt->fetchAll(PDO::FETCH_ASSOC); @@ -596,7 +620,59 @@ public function addServiceMetrics($hostId, $serviceId) $this->addVirtualMetric($vmetric); } } - + + /** + * Add metrics for a service + * + * @param int $hostId + * @param int $serviceId + * @param mixed $metricsSelected + * + * @return void + */ + public function addServiceCustomMetrics($hostId, $serviceId, $metricsSelected): void + { + $indexId = null; + $stmt = $this->dbCs->prepare( + "SELECT + m.index_id, host_id, service_id, metric_id, metric_name, + unit_name, min, max, warn, warn_low, crit, crit_low + FROM metrics AS m, index_data AS i + WHERE i.host_id = :host_id + AND i.service_id = :service_id + AND i.id = m.index_id + AND m.hidden = '0'" + ); + $stmt->bindParam(':host_id', $hostId, PDO::PARAM_INT); + $stmt->bindParam(':service_id', $serviceId, PDO::PARAM_INT); + $stmt->execute(); + $metrics = $stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($metrics as $metric) { + $indexId = $metric['index_id']; + $this->addIndexId($metric['index_id']); + if (isset($metricsSelected[$metric['metric_id']])) { + $this->addRealMetric($metric); + } else { + // this metric will be hidden + $this->addRealMetric($metric, 1); + } + } + + $stmt = $this->db->prepare( + "SELECT * + FROM virtual_metrics + WHERE index_id = :index_id + AND vmetric_activate = '1'" + ); + $stmt->bindParam(':index_id', $indexId, PDO::PARAM_INT); + $stmt->execute(); + $vmetrics = $stmt->fetchAll(PDO::FETCH_ASSOC); + + foreach ($vmetrics as $vmetric) { + $this->addVirtualMetric($vmetric); + } + } + /** * Add a metric * @@ -622,13 +698,13 @@ public function addMetric($metricId, $isVirtual = 0) if (is_null($metric)) { return; } - + $this->addIndexId($metric['index_id']); $this->addRealMetric($metric); - + return ; } - + $stmt = $this->db->prepare( "SELECT * FROM virtual_metrics @@ -641,10 +717,10 @@ public function addMetric($metricId, $isVirtual = 0) if (is_null($vmetric)) { return; } - + $this->addIndexId($vmetric['index_id']); $this->addVirtualMetric($vmetric); - + /** * Brutal: we get all vmetrics and metrics, with hidden */ @@ -677,9 +753,9 @@ private function initCurveList() $this->addArgument("DEF:v" . $metricId . "=" . $this->dbPath . $metricId . ".rrd:value:AVERAGE"); } } - + $this->manageMetrics(); - + foreach ($this->vmetricsOrder as $vmetricId) { $this->addArgument($this->vmetrics[$vmetricId]['def_type'] . ":vv" . $vmetricId . "=" . $this->vmetrics[$vmetricId]['rpn_function']); @@ -874,6 +950,9 @@ private function getServiceGraphID() */ private function getIndexData() { + if ($this->multipleServices) { + return ; + } /** * We take the first */ @@ -910,6 +989,10 @@ private function getIndexData() */ public function setTemplate($templateId = null) { + if ($this->multipleServices) { + return ; + } + if (!isset($templateId) || !$templateId) { if ($this->indexData["host_name"] != "_Module_Meta") { $this->getDefaultGraphTemplate(); @@ -961,13 +1044,13 @@ public function setRRDOption($name, $value = null) /** * Parse rrdtool result * - * @param mixed $rrdData + * @param array $rrdData * * @return void */ private function formatByMetrics($rrdData) { - $this->graphData['times'] = array(); + $this->graphData['times'] = []; $size = (is_array($rrdData['data']) || $rrdData['data'] instanceof \Countable) ? count($rrdData['data']) @@ -976,17 +1059,17 @@ private function formatByMetrics($rrdData) $gprintsSize = (is_array($rrdData['meta']['gprints']) || $rrdData['meta']['gprints'] instanceof \Countable) ? count($rrdData['meta']['gprints']) : 0; - + for ($i = 0; $i < $size; $i++) { $this->graphData['times'][] = $rrdData['data'][$i][0]; } - - $i = 1; + + $metricIndex = 1; $gprintsPos = 0; foreach ($this->graphData['metrics'] as &$metric) { $metric['data'] = array(); $metric['prints'] = array(); - + $insert = 0; if ($metric['virtual'] == 0) { $metricFullname = 'v' . $metric['metric_id']; @@ -1004,11 +1087,24 @@ private function formatByMetrics($rrdData) $metric['prints'][] = array_values($rrdData['meta']['gprints'][$gprintsPos]); } } - - for ($j = 0; $j < $size; $j++) { - $metric['data'][] = $rrdData['data'][$j][$i]; + + $minimumValue = null; + $maximumValue = null; + for ($dataIndex = 0; $dataIndex < $size; $dataIndex++) { + $metric['data'][] = $rrdData['data'][$dataIndex][$metricIndex]; + if (!is_null($rrdData['data'][$dataIndex][$metricIndex]) && + (is_null($minimumValue) || $rrdData['data'][$dataIndex][$metricIndex] < $minimumValue)) { + $minimumValue = $rrdData['data'][$dataIndex][$metricIndex]; + } + if (!is_null($rrdData['data'][$dataIndex][$metricIndex]) && + (is_null($maximumValue) || $rrdData['data'][$dataIndex][$metricIndex] > $maximumValue)) { + $maximumValue = $rrdData['data'][$dataIndex][$metricIndex]; + } } - $i++; + + $metric['minimum_value'] = $minimumValue; + $metric['maximum_value'] = $maximumValue; + $metricIndex++; } } @@ -1060,9 +1156,10 @@ public function getJsonStream() null, null ); + $this->extraDatas['multiple_services'] = $this->multipleServices; $this->graphData = array( 'global' => $this->extraDatas, - 'metrics' => array(), + 'metrics' => [] ); foreach ($this->metrics as $metric) { if ($metric['hidden'] == 1) { @@ -1124,20 +1221,21 @@ public function checkArgument($name, $tab, $defaultValue) public function getOVDColor($indexId, $metricId) { if (is_null($this->colorCache)) { - $this->colorCache = array(); - + $this->colorCache = []; + } + if (!isset($this->colorCache[$indexId])) { $stmt = $this->db->prepare( "SELECT metric_id, rnd_color FROM `ods_view_details` WHERE `index_id` = :index_id" ); $stmt->bindParam(':index_id', $indexId, PDO::PARAM_INT); $stmt->execute(); - $this->colorCache = $stmt->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_UNIQUE|PDO::FETCH_ASSOC); + $this->colorCache[$indexId] = $stmt->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_UNIQUE|PDO::FETCH_ASSOC); } - - if (isset($this->colorCache[$metricId]) - && preg_match("/^\#[a-f0-9]{6,6}/i", $this->colorCache[$metricId]['rnd_color']) + + if (isset($this->colorCache[$indexId][$metricId]) + && preg_match("/^\#[a-f0-9]{6,6}/i", $this->colorCache[$indexId][$metricId]['rnd_color']) ) { - return $this->colorCache[$metricId]['rnd_color']; + return $this->colorCache[$indexId][$metricId]['rnd_color']; } $lRndcolor = $this->getRandomWebColor(); $stmt = $this->db->prepare( @@ -1192,8 +1290,9 @@ public function getRandomWebColor() '#ff33ff', '#ff6600', '#ff6633', '#ff6666', '#ff6699', '#ff66cc', '#ff66ff', '#ff9900', '#ff9933', '#ff9966', '#ff9999', '#ff99cc', '#ff99ff', '#ffcc00', '#ffcc33', '#ffcc66', '#ffcc99', '#ffcccc', - '#ffccff'); - return $webSafeColors[rand(0, sizeof($webSafeColors)-1)]; + '#ffccff' + ); + return $webSafeColors[rand(0, sizeof($webSafeColors) - 1)]; } /** diff --git a/www/class/centreonMetrics.class.php b/www/class/centreonMetrics.class.php index d185b47048c..b7b8ecd90bd 100644 --- a/www/class/centreonMetrics.class.php +++ b/www/class/centreonMetrics.class.php @@ -39,34 +39,35 @@ public function __construct($db) } /** - * @param array $values + * Get metrics information from ids to populat select2 + * + * @param array $values list of metric ids * @return array */ - public function getObjectForSelect2($values = array()) + public function getObjectForSelect2($values = []) { - $metrics = array(); - $filters = ''; + $metrics = []; $listValues = ''; - $queryValues = array(); + $queryValues = []; if (!empty($values)) { - foreach ($values as $k => $v) { - $listValues .= ':metric' . $v . ','; - $queryValues['metric' . $v] = (int)$v; + foreach ($values as $v) { + $multiValues = explode(',', $v); + foreach ($multiValues as $item) { + $listValues .= ':metric' . $item . ','; + $queryValues['metric' . $item] = (int)$item; + } } $listValues = rtrim($listValues, ','); - $filters .= 'm.metric_id IN (' . $listValues . ') AND'; } else { - $filters .= '""'; + $listValues = '""'; } - $queryService = "SELECT SQL_CALC_FOUND_ROWS m.metric_id, CONCAT(h.name,' - ', s.description," - . "' - ', m.metric_name) AS fullname " - . "FROM metrics m, hosts h, services s, index_data i " - . "WHERE " - . $filters . " " - . "i.id = m.index_id AND " - . "h.host_id = i.host_id " - . "AND s.service_id = i.service_id " + + $queryService = "SELECT SQL_CALC_FOUND_ROWS m.metric_id, CONCAT(i.host_name,' - ', i.service_description," + . "' - ', m.metric_name) AS fullname " + . "FROM metrics m, index_data i " + . "WHERE m.metric_id IN (" . $listValues . ") " + . "AND i.id = m.index_id " . "ORDER BY fullname COLLATE utf8_general_ci"; $stmt = $this->dbo->prepare($queryService); @@ -78,11 +79,12 @@ public function getObjectForSelect2($values = array()) $stmt->execute(); while ($row = $stmt->fetch()) { - $metrics[] = array( + $metrics[] = [ 'id' => $row['metric_id'], 'text' => $row['fullname'] - ); + ]; } + return $metrics; } } diff --git a/www/class/centreonWidget/Params/Connector/MetricMulti.class.php b/www/class/centreonWidget/Params/Connector/MetricMulti.class.php index a782370ebbc..b62dc896be5 100644 --- a/www/class/centreonWidget/Params/Connector/MetricMulti.class.php +++ b/www/class/centreonWidget/Params/Connector/MetricMulti.class.php @@ -44,12 +44,12 @@ public function __construct($db, $quickform, $userId) public function getParameters() { - $path = './include/common/webServices/rest/internal.php?object=centreon_metric&action=listByService'; - return array( + $path = './api/internal.php?object=centreon_metric&action=listByService'; + return [ 'datasourceOrigin' => 'ajax', 'availableDatasetRoute' => $path, 'multiple' => true, - 'linkedObject' => 'centreonMetrics' - ); + 'linkedObject' => 'centreonMetrics', + ]; } } diff --git a/www/include/home/customViews/widgetParam.html b/www/include/home/customViews/widgetParam.html index 649c5bd7228..0bf8cb54354 100644 --- a/www/include/home/customViews/widgetParam.html +++ b/www/include/home/customViews/widgetParam.html @@ -1,7 +1,7 @@ {$form.javascript}{$javascript}
- +

{$form.header.title}