Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'ui/widgets/tophosts/actions/WidgetView.php')
-rw-r--r--ui/widgets/tophosts/actions/WidgetView.php458
1 files changed, 458 insertions, 0 deletions
diff --git a/ui/widgets/tophosts/actions/WidgetView.php b/ui/widgets/tophosts/actions/WidgetView.php
new file mode 100644
index 00000000000..8c9596ba6ef
--- /dev/null
+++ b/ui/widgets/tophosts/actions/WidgetView.php
@@ -0,0 +1,458 @@
+<?php declare(strict_types = 0);
+/*
+** Zabbix
+** Copyright (C) 2001-2021 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+
+namespace Widgets\TopHosts\Actions;
+
+use API,
+ CControllerDashboardWidgetView,
+ CControllerResponseData,
+ CHousekeepingHelper,
+ CMacrosResolverHelper,
+ CNumberParser,
+ CParser,
+ CSettingsHelper,
+ Manager;
+
+use Widgets\TopHosts\Widget;
+
+use Zabbix\Widgets\Fields\CWidgetFieldColumnsList;
+
+class WidgetView extends CControllerDashboardWidgetView {
+
+ protected function doAction(): void {
+ $data = [
+ 'name' => $this->getInput('name', $this->widget->getDefaultName()),
+ 'user' => [
+ 'debug_mode' => $this->getDebugMode()
+ ]
+ ];
+
+ $data += $this->getData();
+
+ $this->setResponse(new CControllerResponseData($data));
+ }
+
+ private function getData(): array {
+ $configuration = $this->fields_values['columns'];
+
+ $groupids = $this->fields_values['groupids'] ? getSubGroups($this->fields_values['groupids']) : null;
+ $hostids = $this->fields_values['hostids'] ?: null;
+
+ if (array_key_exists('tags', $this->fields_values)) {
+ $hosts = API::Host()->get([
+ 'output' => ['name'],
+ 'groupids' => $groupids,
+ 'hostids' => $hostids,
+ 'evaltype' => $this->fields_values['evaltype'],
+ 'tags' => $this->fields_values['tags'],
+ 'monitored_hosts' => true,
+ 'preservekeys' => true
+ ]);
+
+ $hostids = array_keys($hosts);
+ }
+ else {
+ $hosts = null;
+ }
+
+ $time_now = time();
+
+ $master_column = $configuration[$this->fields_values['column']];
+ $master_items_only_numeric_allowed = self::isNumericOnlyColumn($master_column);
+
+ $master_items = self::getItems($master_column['item'], $master_items_only_numeric_allowed, $groupids, $hostids);
+ $master_item_values = self::getItemValues($master_items, $master_column, $time_now);
+
+ if (!$master_item_values) {
+ return [
+ 'configuration' => $configuration,
+ 'rows' => []
+ ];
+ }
+
+ $master_items_only_numeric_present = $master_items_only_numeric_allowed && !array_filter($master_items,
+ static function(array $item): bool {
+ return !in_array($item['value_type'], [ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64]);
+ }
+ );
+
+ if ($this->fields_values['order'] == Widget::ORDER_TOP_N) {
+ if ($master_items_only_numeric_present) {
+ arsort($master_item_values, SORT_NUMERIC);
+
+ $master_items_min = end($master_item_values);
+ $master_items_max = reset($master_item_values);
+ }
+ else {
+ asort($master_item_values, SORT_NATURAL);
+ }
+ }
+ else {
+ if ($master_items_only_numeric_present) {
+ asort($master_item_values, SORT_NUMERIC);
+
+ $master_items_min = reset($master_item_values);
+ $master_items_max = end($master_item_values);
+ }
+ else {
+ arsort($master_item_values, SORT_NATURAL);
+ }
+ }
+
+ $master_item_values = array_slice($master_item_values, 0, $this->fields_values['count'], true);
+ $master_items = array_intersect_key($master_items, $master_item_values);
+
+ $master_hostids = [];
+
+ foreach (array_keys($master_item_values) as $itemid) {
+ $master_hostids[$master_items[$itemid]['hostid']] = true;
+ }
+
+ $number_parser = new CNumberParser(['with_size_suffix' => true, 'with_time_suffix' => true]);
+
+ $item_values = [];
+
+ foreach ($configuration as $column_index => &$column) {
+ if ($column['data'] != CWidgetFieldColumnsList::DATA_ITEM_VALUE) {
+ continue;
+ }
+
+ $calc_extremes = $column['display'] == CWidgetFieldColumnsList::DISPLAY_BAR
+ || $column['display'] == CWidgetFieldColumnsList::DISPLAY_INDICATORS;
+
+ if ($calc_extremes) {
+ if ($column['min'] !== '' && $number_parser->parse($column['min']) == CParser::PARSE_SUCCESS) {
+ $column['min'] = $number_parser->calcValue();
+ }
+
+ if ($column['max'] !== '' && $number_parser->parse($column['max']) == CParser::PARSE_SUCCESS) {
+ $column['max'] = $number_parser->calcValue();
+ }
+ }
+
+ if (array_key_exists('thresholds', $column)) {
+ foreach ($column['thresholds'] as &$threshold) {
+ if ($number_parser->parse($threshold['threshold']) == CParser::PARSE_SUCCESS) {
+ $threshold['threshold'] = $number_parser->calcValue();
+ }
+ }
+ unset($threshold);
+ }
+
+ if ($column_index == $this->fields_values['column']) {
+ $column_items = $master_items;
+ $column_item_values = $master_item_values;
+
+ if ($calc_extremes) {
+ if ($column['min'] === '') {
+ $column['min'] = $master_items_min;
+ }
+
+ if ($column['max'] === '') {
+ $column['max'] = $master_items_max;
+ }
+ }
+ }
+ else {
+ $numeric_only = self::isNumericOnlyColumn($column);
+ $column_items = !$calc_extremes || ($column['min'] !== '' && $column['max'] !== '')
+ ? self::getItems($column['item'], $numeric_only, $groupids, array_keys($master_hostids))
+ : self::getItems($column['item'], $numeric_only, $groupids, $hostids);
+
+ $column_item_values = self::getItemValues($column_items, $column, $time_now);
+
+ if ($calc_extremes && $column_item_values) {
+ if ($column['min'] === '') {
+ $column['min'] = min($column_item_values);
+ }
+
+ if ($column['max'] === '') {
+ $column['max'] = max($column_item_values);
+ }
+ }
+ }
+
+ $item_values[$column_index] = [];
+
+ foreach ($column_item_values as $itemid => $column_item_value) {
+ if (array_key_exists($column_items[$itemid]['hostid'], $master_hostids)) {
+ $item_values[$column_index][$column_items[$itemid]['hostid']] = [
+ 'value' => $column_item_value,
+ 'item' => $column_items[$itemid]
+ ];
+ }
+ }
+ }
+ unset($column);
+
+ $text_columns = [];
+
+ foreach ($configuration as $column_index => $column) {
+ if ($column['data'] == CWidgetFieldColumnsList::DATA_TEXT) {
+ $text_columns[$column_index] = $column['text'];
+ }
+ }
+
+ $text_columns = CMacrosResolverHelper::resolveWidgetTopHostsTextColumns($text_columns, $master_items);
+
+ $hostid_to_itemid = array_column($master_items, 'itemid', 'hostid');
+
+ $rows = [];
+
+ foreach (array_keys($master_hostids) as $hostid) {
+ $row = [];
+
+ foreach ($configuration as $column_index => $column) {
+ switch ($column['data']) {
+ case CWidgetFieldColumnsList::DATA_HOST_NAME:
+ if ($hosts === null) {
+ $hosts = API::Host()->get([
+ 'output' => ['name'],
+ 'groupids' => $groupids,
+ 'hostids' => array_keys($master_hostids),
+ 'monitored_hosts' => true,
+ 'preservekeys' => true
+ ]);
+ }
+
+ $row[] = [
+ 'value' => $hosts[$hostid]['name'],
+ 'hostid' => $hostid
+ ];
+
+ break;
+
+ case CWidgetFieldColumnsList::DATA_TEXT:
+ $row[] = [
+ 'value' => $text_columns[$column_index][$hostid_to_itemid[$hostid]]
+ ];
+
+ break;
+
+ case CWidgetFieldColumnsList::DATA_ITEM_VALUE:
+ $row[] = array_key_exists($hostid, $item_values[$column_index])
+ ? [
+ 'value' => $item_values[$column_index][$hostid]['value'],
+ 'item' => $item_values[$column_index][$hostid]['item']
+ ]
+ : null;
+
+ break;
+ }
+ }
+
+ $rows[] = $row;
+ }
+
+ return [
+ 'configuration' => $configuration,
+ 'rows' => $rows
+ ];
+ }
+
+ private static function isNumericOnlyColumn(array $column): bool {
+ return $column['aggregate_function'] != AGGREGATE_NONE
+ || $column['display'] != CWidgetFieldColumnsList::DISPLAY_AS_IS
+ || array_key_exists('thresholds', $column);
+ }
+
+ private static function getItems(string $name, bool $numeric_only, ?array $groupids, ?array $hostids): array {
+ $items = API::Item()->get([
+ 'output' => ['itemid', 'hostid', 'key_', 'history', 'trends', 'value_type', 'units'],
+ 'selectValueMap' => ['mappings'],
+ 'groupids' => $groupids,
+ 'hostids' => $hostids,
+ 'monitored' => true,
+ 'webitems' => true,
+ 'filter' => [
+ 'name' => $name,
+ 'status' => ITEM_STATUS_ACTIVE,
+ 'value_type' => $numeric_only ? [ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64] : null
+ ],
+ 'sortfield' => 'key_',
+ 'preservekeys' => true
+ ]);
+
+ if ($items) {
+ $single_key = reset($items)['key_'];
+
+ $items = array_filter($items,
+ static function ($item) use ($single_key): bool {
+ return $item['key_'] === $single_key;
+ }
+ );
+ }
+
+ return $items;
+ }
+
+ private static function getItemValues(array $items, array $column, int $time_now): array {
+ static $history_period;
+
+ if ($history_period === null) {
+ $history_period = timeUnitToSeconds(CSettingsHelper::get(CSettingsHelper::HISTORY_PERIOD));
+ }
+
+ $timeshift = $column['timeshift'] !== '' ? timeUnitToSeconds($column['timeshift']) : 0;
+
+ $time_to = $time_now + $timeshift;
+
+ $time_from = $column['aggregate_function'] != AGGREGATE_NONE
+ ? $time_to - timeUnitToSeconds($column['aggregate_interval'])
+ : $time_to - $history_period;
+
+ $function = $column['aggregate_function'] != AGGREGATE_NONE
+ ? $column['aggregate_function']
+ : AGGREGATE_LAST;
+
+ $interval = $time_to;
+
+ self::addDataSource($items, $time_from, $time_now, $column['history']);
+
+ $result = [];
+
+ if ($column['aggregate_function'] == AGGREGATE_NONE) {
+ $items_by_source = ['history' => [], 'trends' => []];
+
+ foreach ($items as $itemid => $item) {
+ $items_by_source[$item['source']][$itemid] = $item;
+ }
+
+ if ($timeshift != 0) {
+ $values = [];
+
+ foreach ($items_by_source['history'] as $itemid => $item) {
+ $history = Manager::History()->getValueAt($item, $time_to, 0);
+
+ if (is_array($history)) {
+ $values[$itemid] = $history['value'];
+ }
+ }
+ }
+ else {
+ $values = Manager::History()->getLastValues($items_by_source['history'], 1, $history_period);
+ $values = array_column(array_column($values, 0), 'value', 'itemid');
+ }
+
+ $result += $values;
+ $items = $items_by_source['trends'];
+ }
+
+ $values = Manager::History()->getAggregationByInterval($items, $time_from, $time_to, $function, $interval);
+ $values = array_column(array_column(array_column($values, 'data'), 0),
+ $function == AGGREGATE_COUNT ? 'count' : 'value', 'itemid'
+ );
+
+ $result += $values;
+
+ return $result;
+ }
+
+ private static function addDataSource(array &$items, int $time_from, int $time_now, int $data_source): void {
+ if ($data_source == CWidgetFieldColumnsList::HISTORY_DATA_HISTORY
+ || $data_source == CWidgetFieldColumnsList::HISTORY_DATA_TRENDS) {
+ foreach ($items as &$item) {
+ $item['source'] = $data_source == CWidgetFieldColumnsList::HISTORY_DATA_TRENDS
+ && ($item['value_type'] == ITEM_VALUE_TYPE_FLOAT || $item['value_type'] == ITEM_VALUE_TYPE_UINT64)
+ ? 'trends'
+ : 'history';
+ }
+ unset($item);
+
+ return;
+ }
+
+ static $hk_history_global, $global_history_time, $hk_trends_global, $global_trends_time;
+
+ if ($hk_history_global === null) {
+ $hk_history_global = CHousekeepingHelper::get(CHousekeepingHelper::HK_HISTORY_GLOBAL);
+
+ if ($hk_history_global) {
+ $global_history_time = timeUnitToSeconds(CHousekeepingHelper::get(CHousekeepingHelper::HK_HISTORY));
+ }
+ }
+
+ if ($hk_trends_global === null) {
+ $hk_trends_global = CHousekeepingHelper::get(CHousekeepingHelper::HK_TRENDS_GLOBAL);
+
+ if ($hk_history_global) {
+ $global_trends_time = timeUnitToSeconds(CHousekeepingHelper::get(CHousekeepingHelper::HK_TRENDS));
+ }
+ }
+
+ if ($hk_history_global) {
+ foreach ($items as &$item) {
+ $item['history'] = $global_history_time;
+ }
+ unset($item);
+ }
+
+ if ($hk_trends_global) {
+ foreach ($items as &$item) {
+ $item['trends'] = $global_trends_time;
+ }
+ unset($item);
+ }
+
+ if (!$hk_history_global || !$hk_trends_global) {
+ $items = CMacrosResolverHelper::resolveTimeUnitMacros($items,
+ array_merge($hk_history_global ? [] : ['history'], $hk_trends_global ? [] : ['trends'])
+ );
+
+ $processed_items = [];
+
+ foreach ($items as $itemid => $item) {
+ if (!$global_trends_time) {
+ $item['history'] = timeUnitToSeconds($item['history']);
+
+ if ($item['history'] === null) {
+ error(_s('Incorrect value for field "%1$s": %2$s.', 'history',
+ _('invalid history storage period')
+ ));
+
+ continue;
+ }
+ }
+
+ if (!$hk_trends_global) {
+ $item['trends'] = timeUnitToSeconds($item['trends']);
+
+ if ($item['trends'] === null) {
+ error(_s('Incorrect value for field "%1$s": %2$s.', 'trends',
+ _('invalid trend storage period')
+ ));
+
+ continue;
+ }
+ }
+
+ $processed_items[$itemid] = $item;
+ }
+
+ $items = $processed_items;
+ }
+
+ foreach ($items as &$item) {
+ $item['source'] = $item['trends'] == 0 || $time_now - $item['history'] <= $time_from ? 'history' : 'trends';
+ }
+ unset($item);
+ }
+}