You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
761 lines
24 KiB
761 lines
24 KiB
1 year ago
|
<?php
|
||
|
/*
|
||
|
** Zabbix
|
||
|
** Copyright (C) 2001-2023 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.
|
||
|
**/
|
||
|
|
||
|
|
||
|
require_once dirname(__FILE__).'/graphs.inc.php';
|
||
|
require_once dirname(__FILE__).'/maps.inc.php';
|
||
|
require_once dirname(__FILE__).'/users.inc.php';
|
||
|
|
||
|
/**
|
||
|
* @param array $filter
|
||
|
* @param array $filter['groupids'] (optional)
|
||
|
* @param array $filter['exclude_groupids'] (optional)
|
||
|
* @param array $filter['hostids'] (optional)
|
||
|
* @param string $filter['problem'] (optional)
|
||
|
* @param array $filter['severities'] (optional)
|
||
|
* @param int $filter['show_suppressed'] (optional)
|
||
|
* @param int $filter['hide_empty_groups'] (optional)
|
||
|
* @param int $filter['ext_ack'] (optional)
|
||
|
* @param int $filter['show_opdata'] (optional)
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function getSystemStatusData(array $filter) {
|
||
|
$filter_groupids = (array_key_exists('groupids', $filter) && $filter['groupids']) ? $filter['groupids'] : null;
|
||
|
$filter_hostids = (array_key_exists('hostids', $filter) && $filter['hostids']) ? $filter['hostids'] : null;
|
||
|
$filter_severities = (array_key_exists('severities', $filter) && $filter['severities'])
|
||
|
? $filter['severities']
|
||
|
: range(TRIGGER_SEVERITY_NOT_CLASSIFIED, TRIGGER_SEVERITY_COUNT - 1);
|
||
|
$filter_ext_ack = array_key_exists('ext_ack', $filter)
|
||
|
? $filter['ext_ack']
|
||
|
: EXTACK_OPTION_ALL;
|
||
|
$filter_evaltype = array_key_exists('evaltype', $filter) ? $filter['evaltype'] : TAG_EVAL_TYPE_AND_OR;
|
||
|
$filter_tags = array_key_exists('tags', $filter) && $filter['tags'] ? $filter['tags'] : null;
|
||
|
$show_opdata = array_key_exists('show_opdata', $filter) && $filter['show_opdata'] != OPERATIONAL_DATA_SHOW_NONE;
|
||
|
|
||
|
if (array_key_exists('exclude_groupids', $filter) && $filter['exclude_groupids']) {
|
||
|
if ($filter_hostids === null) {
|
||
|
// Get all groups if no selected groups defined.
|
||
|
if ($filter_groupids === null) {
|
||
|
$filter_groupids = array_keys(API::HostGroup()->get([
|
||
|
'output' => [],
|
||
|
'with_hosts' => true,
|
||
|
'preservekeys' => true
|
||
|
]));
|
||
|
}
|
||
|
|
||
|
$filter_groupids = array_diff($filter_groupids, $filter['exclude_groupids']);
|
||
|
|
||
|
// Get available hosts.
|
||
|
$filter_hostids = array_keys(API::Host()->get([
|
||
|
'output' => [],
|
||
|
'groupids' => $filter_groupids,
|
||
|
'preservekeys' => true
|
||
|
]));
|
||
|
}
|
||
|
|
||
|
$exclude_hostids = array_keys(API::Host()->get([
|
||
|
'output' => [],
|
||
|
'groupids' => $filter['exclude_groupids'],
|
||
|
'preservekeys' => true
|
||
|
]));
|
||
|
|
||
|
$filter_hostids = array_diff($filter_hostids, $exclude_hostids);
|
||
|
}
|
||
|
|
||
|
$data = [
|
||
|
'groups' => API::HostGroup()->get([
|
||
|
'output' => ['groupid', 'name'],
|
||
|
'groupids' => $filter_groupids,
|
||
|
'hostids' => $filter_hostids,
|
||
|
'with_monitored_hosts' => true,
|
||
|
'preservekeys' => true
|
||
|
]),
|
||
|
'triggers' => [],
|
||
|
'actions' => [],
|
||
|
'stats' => [],
|
||
|
'allowed' => [
|
||
|
'ui_problems' => CWebUser::checkAccess(CRoleHelper::UI_MONITORING_PROBLEMS),
|
||
|
'add_comments' => CWebUser::checkAccess(CRoleHelper::ACTIONS_ADD_PROBLEM_COMMENTS),
|
||
|
'change_severity' => CWebUser::checkAccess(CRoleHelper::ACTIONS_CHANGE_SEVERITY),
|
||
|
'acknowledge' => CWebUser::checkAccess(CRoleHelper::ACTIONS_ACKNOWLEDGE_PROBLEMS),
|
||
|
'close' => CWebUser::checkAccess(CRoleHelper::ACTIONS_CLOSE_PROBLEMS),
|
||
|
'suppress' => CWebUser::checkAccess(CRoleHelper::ACTIONS_SUPPRESS_PROBLEMS)
|
||
|
]
|
||
|
];
|
||
|
|
||
|
CArrayHelper::sort($data['groups'], [['field' => 'name', 'order' => ZBX_SORT_UP]]);
|
||
|
|
||
|
$default_stats = [];
|
||
|
|
||
|
for ($severity = TRIGGER_SEVERITY_COUNT - 1; $severity >= TRIGGER_SEVERITY_NOT_CLASSIFIED; $severity--) {
|
||
|
if (in_array($severity, $filter_severities)) {
|
||
|
$default_stats[$severity] = ['count' => 0, 'problems' => [], 'count_unack' => 0, 'problems_unack' => []];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$data['stats'] = $default_stats;
|
||
|
|
||
|
foreach ($data['groups'] as &$group) {
|
||
|
$group['stats'] = $default_stats;
|
||
|
$group['has_problems'] = false;
|
||
|
}
|
||
|
unset($group);
|
||
|
|
||
|
$options = [
|
||
|
'output' => ['eventid', 'r_eventid', 'objectid', 'clock', 'ns', 'name', 'acknowledged', 'severity'],
|
||
|
'selectAcknowledges' => ['action', 'clock', 'userid'],
|
||
|
'groupids' => array_keys($data['groups']),
|
||
|
'hostids' => $filter_hostids,
|
||
|
'evaltype' => $filter_evaltype,
|
||
|
'tags' => $filter_tags,
|
||
|
'source' => EVENT_SOURCE_TRIGGERS,
|
||
|
'object' => EVENT_OBJECT_TRIGGER,
|
||
|
'suppressed' => false,
|
||
|
'symptom' => false,
|
||
|
'sortfield' => ['eventid'],
|
||
|
'sortorder' => ZBX_SORT_DOWN,
|
||
|
'preservekeys' => true
|
||
|
];
|
||
|
|
||
|
if (array_key_exists('severities', $filter) && $filter['severities']) {
|
||
|
$options['severities'] = $filter['severities'];
|
||
|
}
|
||
|
|
||
|
if (array_key_exists('show_suppressed', $filter) && $filter['show_suppressed']) {
|
||
|
unset($options['suppressed']);
|
||
|
$options['selectSuppressionData'] = ['maintenanceid', 'suppress_until', 'userid'];
|
||
|
}
|
||
|
|
||
|
if ($filter_ext_ack == EXTACK_OPTION_UNACK) {
|
||
|
$options['acknowledged'] = false;
|
||
|
}
|
||
|
|
||
|
if (array_key_exists('problem', $filter) && $filter['problem'] !== '') {
|
||
|
$options['search'] = ['name' => $filter['problem']];
|
||
|
}
|
||
|
|
||
|
$problems = API::Problem()->get($options);
|
||
|
if ($problems) {
|
||
|
$triggerids = [];
|
||
|
|
||
|
foreach ($problems as $problem) {
|
||
|
$triggerids[$problem['objectid']] = true;
|
||
|
}
|
||
|
|
||
|
$options = [
|
||
|
'output' => ['priority', 'manual_close'],
|
||
|
'selectHostGroups' => ['groupid'],
|
||
|
'selectHosts' => ['name'],
|
||
|
'triggerids' => array_keys($triggerids),
|
||
|
'monitored' => true,
|
||
|
'skipDependent' => true,
|
||
|
'preservekeys' => true
|
||
|
];
|
||
|
|
||
|
if ($show_opdata) {
|
||
|
$options['selectFunctions'] = ['itemid'];
|
||
|
$options['output'] = array_merge($options['output'],
|
||
|
['expression', 'recovery_mode', 'recovery_expression', 'opdata']
|
||
|
);
|
||
|
}
|
||
|
|
||
|
$data['triggers'] = API::Trigger()->get($options);
|
||
|
|
||
|
if ($show_opdata && $data['triggers']) {
|
||
|
$items = API::Item()->get([
|
||
|
'output' => ['itemid', 'hostid', 'name', 'key_', 'value_type', 'units'],
|
||
|
'selectValueMap' => ['mappings'],
|
||
|
'triggerids' => array_keys($data['triggers']),
|
||
|
'webitems' => true,
|
||
|
'preservekeys' => true
|
||
|
]);
|
||
|
|
||
|
foreach ($data['triggers'] as &$trigger) {
|
||
|
foreach ($trigger['functions'] as $function) {
|
||
|
$trigger['items'][] = $items[$function['itemid']];
|
||
|
}
|
||
|
unset($trigger['functions']);
|
||
|
}
|
||
|
unset($trigger);
|
||
|
}
|
||
|
|
||
|
foreach ($data['triggers'] as &$trigger) {
|
||
|
CArrayHelper::sort($trigger['hosts'], [['field' => 'name', 'order' => ZBX_SORT_UP]]);
|
||
|
}
|
||
|
unset($trigger);
|
||
|
|
||
|
foreach ($problems as $eventid => $problem) {
|
||
|
if (!array_key_exists($problem['objectid'], $data['triggers'])) {
|
||
|
unset($problems[$eventid]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$visible_problems = [];
|
||
|
|
||
|
foreach ($problems as $eventid => $problem) {
|
||
|
$trigger = $data['triggers'][$problem['objectid']];
|
||
|
|
||
|
$data['stats'][$problem['severity']]['count']++;
|
||
|
if ($problem['acknowledged'] == EVENT_NOT_ACKNOWLEDGED) {
|
||
|
$data['stats'][$problem['severity']]['count_unack']++;
|
||
|
}
|
||
|
|
||
|
// groups
|
||
|
foreach ($trigger['hostgroups'] as $trigger_group) {
|
||
|
if (!array_key_exists($trigger_group['groupid'], $data['groups'])) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$group = &$data['groups'][$trigger_group['groupid']];
|
||
|
|
||
|
if (in_array($filter_ext_ack, [EXTACK_OPTION_ALL, EXTACK_OPTION_BOTH])) {
|
||
|
if ($group['stats'][$problem['severity']]['count'] < ZBX_WIDGET_ROWS) {
|
||
|
$group['stats'][$problem['severity']]['problems'][] = $problem;
|
||
|
$visible_problems[$eventid] = ['eventid' => $eventid];
|
||
|
}
|
||
|
|
||
|
$group['stats'][$problem['severity']]['count']++;
|
||
|
}
|
||
|
|
||
|
if (in_array($filter_ext_ack, [EXTACK_OPTION_UNACK, EXTACK_OPTION_BOTH])
|
||
|
&& $problem['acknowledged'] == EVENT_NOT_ACKNOWLEDGED) {
|
||
|
if ($group['stats'][$problem['severity']]['count_unack'] < ZBX_WIDGET_ROWS) {
|
||
|
$group['stats'][$problem['severity']]['problems_unack'][] = $problem;
|
||
|
$visible_problems[$eventid] = ['eventid' => $eventid];
|
||
|
}
|
||
|
|
||
|
$group['stats'][$problem['severity']]['count_unack']++;
|
||
|
}
|
||
|
|
||
|
$group['has_problems'] = true;
|
||
|
}
|
||
|
unset($group);
|
||
|
}
|
||
|
|
||
|
// actions & tags
|
||
|
$problems_data = API::Problem()->get([
|
||
|
'output' => ['eventid', 'r_eventid', 'clock', 'objectid', 'severity'],
|
||
|
'selectAcknowledges' => ['userid', 'clock', 'message', 'action', 'old_severity', 'new_severity',
|
||
|
'suppress_until'
|
||
|
],
|
||
|
'selectTags' => ['tag', 'value'],
|
||
|
'eventids' => array_keys($visible_problems),
|
||
|
'preservekeys' => true
|
||
|
]);
|
||
|
|
||
|
// Remove problems that were resolved between requests or set tags.
|
||
|
foreach ($data['groups'] as $groupid => &$group) {
|
||
|
foreach ($group['stats'] as $severity => &$stat) {
|
||
|
foreach (['problems', 'problems_unack'] as $key) {
|
||
|
foreach ($stat[$key] as $event_no => &$problem) {
|
||
|
if (array_key_exists($problem['eventid'], $problems_data)) {
|
||
|
$problem['tags'] = $problems_data[$problem['eventid']]['tags'];
|
||
|
}
|
||
|
else {
|
||
|
if ($key === 'problems') {
|
||
|
$data['groups'][$groupid]['stats'][$severity]['count']--;
|
||
|
}
|
||
|
else {
|
||
|
$data['groups'][$groupid]['stats'][$severity]['count_unack']--;
|
||
|
}
|
||
|
unset($data['groups'][$groupid]['stats'][$severity][$key][$event_no]);
|
||
|
}
|
||
|
}
|
||
|
unset($problem);
|
||
|
}
|
||
|
}
|
||
|
unset($stat);
|
||
|
}
|
||
|
unset($group);
|
||
|
|
||
|
// actions
|
||
|
// Possible performance improvement: one API call may be saved, if r_clock for problem will be used.
|
||
|
$actions = getEventsActionsIconsData($problems_data, $data['triggers']);
|
||
|
$data['actions'] = [
|
||
|
'all_actions' => $actions['data'],
|
||
|
'users' => API::User()->get([
|
||
|
'output' => ['username', 'name', 'surname'],
|
||
|
'userids' => array_keys($actions['userids']),
|
||
|
'preservekeys' => true
|
||
|
])
|
||
|
];
|
||
|
|
||
|
if (array_key_exists('show_opdata', $filter) && $filter['show_opdata'] != OPERATIONAL_DATA_SHOW_NONE) {
|
||
|
$maked_data = CScreenProblem::makeData(
|
||
|
['problems' => $problems_data, 'triggers' => $data['triggers']],
|
||
|
['show' => 0, 'details' => 0, 'show_opdata' => $filter['show_opdata']]
|
||
|
);
|
||
|
$data['triggers'] = $maked_data['triggers'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param array $data
|
||
|
* @param array $data['groups']
|
||
|
* @param string $data['groups'][]['groupid']
|
||
|
* @param string $data['groups'][]['name']
|
||
|
* @param bool $data['groups'][]['has_problems']
|
||
|
* @param array $data['groups'][]['stats']
|
||
|
* @param int $data['groups'][]['stats'][]['count']
|
||
|
* @param array $data['groups'][]['stats'][]['problems']
|
||
|
* @param int $data['groups'][]['stats'][]['count_unack']
|
||
|
* @param array $data['groups'][]['stats'][]['problems_unack']
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function getSystemStatusTotals(array $data) {
|
||
|
$groups_totals = [
|
||
|
0 => [
|
||
|
'groupid' => 0,
|
||
|
'stats' => []
|
||
|
]
|
||
|
];
|
||
|
|
||
|
foreach ($data['stats'] as $severity => $value) {
|
||
|
$groups_totals[0]['stats'][$severity] = [
|
||
|
'count' => $value['count'],
|
||
|
'problems' => [],
|
||
|
'count_unack' => $value['count_unack'],
|
||
|
'problems_unack' => []
|
||
|
];
|
||
|
}
|
||
|
|
||
|
foreach ($data['groups'] as $group) {
|
||
|
foreach ($group['stats'] as $severity => $stat) {
|
||
|
foreach ($stat['problems'] as $problem) {
|
||
|
$groups_totals[0]['stats'][$severity]['problems'][$problem['eventid']] = $problem;
|
||
|
}
|
||
|
foreach ($stat['problems_unack'] as $problem) {
|
||
|
$groups_totals[0]['stats'][$severity]['problems_unack'][$problem['eventid']] = $problem;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $groups_totals;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param array $data
|
||
|
* @param array $data['data']
|
||
|
* @param array $data['data']['groups']
|
||
|
* @param array $data['data']['groups'][]['stats']
|
||
|
* @param array $data['filter']
|
||
|
* @param array $data['filter']['severities']
|
||
|
* @param array $data['allowed']
|
||
|
* @param bool $data['allowed']['ui_problems']
|
||
|
* @param bool $data['allowed']['add_comments']
|
||
|
* @param bool $data['allowed']['change_severity']
|
||
|
* @param bool $data['allowed']['acknowledge']
|
||
|
* @param bool $data['allowed']['close']
|
||
|
* @param bool $data['allowed']['suppress']
|
||
|
* @param bool $hide_empty_groups
|
||
|
* @param CUrl $groupurl
|
||
|
*
|
||
|
* @return CTableInfo
|
||
|
*/
|
||
|
function makeSeverityTable(array $data, $hide_empty_groups = false, CUrl $groupurl = null) {
|
||
|
$table = new CTableInfo();
|
||
|
|
||
|
foreach ($data['data']['groups'] as $group) {
|
||
|
if ($hide_empty_groups && !$group['has_problems']) {
|
||
|
// Skip row.
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ($data['allowed']['ui_problems']) {
|
||
|
$groupurl->setArgument('groupids', [$group['groupid']]);
|
||
|
$row = [new CLink($group['name'], $groupurl->getUrl())];
|
||
|
}
|
||
|
else {
|
||
|
$row = [$group['name']];
|
||
|
}
|
||
|
|
||
|
foreach ($group['stats'] as $severity => $stat) {
|
||
|
if ($data['filter']['severities'] && !in_array($severity, $data['filter']['severities'])) {
|
||
|
// Skip cell.
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$row[] = getSeverityTableCell($severity, $data, $stat);
|
||
|
}
|
||
|
|
||
|
$table->addRow($row);
|
||
|
}
|
||
|
|
||
|
return $table;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param array $data
|
||
|
* @param array $data['data']
|
||
|
* @param array $data['data']['groups']
|
||
|
* @param array $data['data']['groups'][]['stats']
|
||
|
* @param array $data['filter']
|
||
|
* @param array $data['filter']['severities']
|
||
|
* @param array $data['allowed']
|
||
|
* @param bool $data['allowed']['ui_problems']
|
||
|
* @param bool $data['allowed']['add_comments']
|
||
|
* @param bool $data['allowed']['change_severity']
|
||
|
* @param bool $data['allowed']['acknowledge']
|
||
|
* @param bool $data['allowed']['close']
|
||
|
* @param bool $data['allowed']['suppress']
|
||
|
*
|
||
|
* @return CDiv
|
||
|
*/
|
||
|
function makeSeverityTotals(array $data) {
|
||
|
$table = new CDiv();
|
||
|
|
||
|
foreach ($data['data']['groups'] as $group) {
|
||
|
foreach ($group['stats'] as $severity => $stat) {
|
||
|
if ($data['filter']['severities'] && !in_array($severity, $data['filter']['severities'])) {
|
||
|
// Skip cell.
|
||
|
continue;
|
||
|
}
|
||
|
$table->addItem(getSeverityTableCell($severity, $data, $stat, true));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $table;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param int $severity
|
||
|
* @param array $data
|
||
|
* @param array $data['data']
|
||
|
* @param array $data['data']['triggers']
|
||
|
* @param array $data['data']['actions']
|
||
|
* @param array $data['filter']
|
||
|
* @param array $data['filter']['ext_ack']
|
||
|
* @param array $data['severity_names']
|
||
|
* @param array $data['allowed']
|
||
|
* @param bool $data['allowed']['ui_problems']
|
||
|
* @param bool $data['allowed']['add_comments']
|
||
|
* @param bool $data['allowed']['change_severity']
|
||
|
* @param bool $data['allowed']['acknowledge']
|
||
|
* @param bool $data['allowed']['close']
|
||
|
* @param bool $data['allowed']['suppress']
|
||
|
* @param array $stat
|
||
|
* @param int $stat['count']
|
||
|
* @param array $stat['problems']
|
||
|
* @param int $stat['count_unack']
|
||
|
* @param array $stat['problems_unack']
|
||
|
* @param bool $is_total
|
||
|
*
|
||
|
* @return CCol|string
|
||
|
*/
|
||
|
function getSeverityTableCell($severity, array $data, array $stat, $is_total = false) {
|
||
|
if (!$is_total && $stat['count'] == 0 && $stat['count_unack'] == 0) {
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
$severity_name = $is_total ? ' '.CSeverityHelper::getName($severity) : '';
|
||
|
$ext_ack = array_key_exists('ext_ack', $data['filter']) ? $data['filter']['ext_ack'] : EXTACK_OPTION_ALL;
|
||
|
|
||
|
$allTriggersNum = $stat['count'];
|
||
|
if ($allTriggersNum) {
|
||
|
$allTriggersNum = (new CLinkAction($allTriggersNum))
|
||
|
->setHint(makeProblemsPopup($stat['problems'], $data['data']['triggers'], $data['data']['actions'],
|
||
|
$data['filter'], $data['allowed']
|
||
|
));
|
||
|
}
|
||
|
|
||
|
$unackTriggersNum = $stat['count_unack'];
|
||
|
if ($unackTriggersNum) {
|
||
|
$unackTriggersNum = (new CLinkAction($unackTriggersNum))
|
||
|
->setHint(makeProblemsPopup($stat['problems_unack'], $data['data']['triggers'], $data['data']['actions'],
|
||
|
$data['filter'], $data['allowed']
|
||
|
));
|
||
|
}
|
||
|
|
||
|
switch ($ext_ack) {
|
||
|
case EXTACK_OPTION_ALL:
|
||
|
return CSeverityHelper::makeSeverityCell($severity, [
|
||
|
(new CSpan($allTriggersNum))->addClass(ZBX_STYLE_TOTALS_LIST_COUNT),
|
||
|
$severity_name
|
||
|
], false, $is_total);
|
||
|
|
||
|
case EXTACK_OPTION_UNACK:
|
||
|
return CSeverityHelper::makeSeverityCell($severity, [
|
||
|
(new CSpan($unackTriggersNum))->addClass(ZBX_STYLE_TOTALS_LIST_COUNT),
|
||
|
$severity_name
|
||
|
], false, $is_total);
|
||
|
|
||
|
case EXTACK_OPTION_BOTH:
|
||
|
return CSeverityHelper::makeSeverityCell($severity, [
|
||
|
(new CSpan([$unackTriggersNum, ' '._('of').' ', $allTriggersNum]))
|
||
|
->addClass(ZBX_STYLE_TOTALS_LIST_COUNT),
|
||
|
$severity_name
|
||
|
], false, $is_total);
|
||
|
|
||
|
default:
|
||
|
return '';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generate table for dashboard triggers popup.
|
||
|
*
|
||
|
* @param array $problems
|
||
|
* @param string $problems[]['objectid']
|
||
|
* @param int $problems[]['clock']
|
||
|
* @param int $problems[]['ns']
|
||
|
* @param string $problems[]['r_eventid']
|
||
|
* @param string $problems[]['acknowledged']
|
||
|
* @param array $problems[]['acknowledges']
|
||
|
* @param string $problems[]['acknowledges'][]['action']
|
||
|
* @param array $problems[]['severity']
|
||
|
* @param array $problems[]['suppression_data']
|
||
|
* @param array $problems[]['tags']
|
||
|
* @param string $problems[]['tags'][]['tag']
|
||
|
* @param string $problems[]['tags'][]['value']
|
||
|
* @param array $triggers
|
||
|
* @param string $triggers[<triggerid>]['expression']
|
||
|
* @param string $triggers[<triggerid>]['description']
|
||
|
* @param string $triggers[<triggerid>]['manual_close']
|
||
|
* @param array $triggers[<triggerid>]['hosts']
|
||
|
* @param string $triggers[<triggerid>]['hosts'][]['name']
|
||
|
* @param string $triggers[<triggerid>]['opdata']
|
||
|
* @param array $actions
|
||
|
* @param array $filter
|
||
|
* @param array $filter['show_suppressed'] (optional)
|
||
|
* @param array $filter['show_timeline'] (optional)
|
||
|
* @param array $filter['show_opdata'] (optional)
|
||
|
* @param array $allowed
|
||
|
* @param bool $allowed['ui_problems']
|
||
|
* @param bool $allowed['add_comments']
|
||
|
* @param bool $allowed['change_severity']
|
||
|
* @param bool $allowed['acknowledge']
|
||
|
* @param bool $allowed['close']
|
||
|
* @param bool $allowed['suppress']
|
||
|
*
|
||
|
* @return CTableInfo
|
||
|
*/
|
||
|
function makeProblemsPopup(array $problems, array $triggers, array $actions, array $filter, array $allowed) {
|
||
|
$url_details = $allowed['ui_problems']
|
||
|
? (new CUrl('tr_events.php'))
|
||
|
->setArgument('triggerid', '')
|
||
|
->setArgument('eventid', '')
|
||
|
: null;
|
||
|
|
||
|
$header_time = new CColHeader([_('Time'), (new CSpan())->addClass(ZBX_STYLE_ARROW_DOWN)]);
|
||
|
|
||
|
$show_timeline = (array_key_exists('show_timeline', $filter) && $filter['show_timeline']);
|
||
|
$show_opdata = (array_key_exists('show_opdata', $filter)) ? $filter['show_opdata'] : OPERATIONAL_DATA_SHOW_NONE;
|
||
|
|
||
|
if ($show_timeline) {
|
||
|
$header = [
|
||
|
$header_time->addClass(ZBX_STYLE_RIGHT),
|
||
|
(new CColHeader())->addClass(ZBX_STYLE_TIMELINE_TH),
|
||
|
(new CColHeader())->addClass(ZBX_STYLE_TIMELINE_TH)
|
||
|
];
|
||
|
}
|
||
|
else {
|
||
|
$header = [$header_time];
|
||
|
}
|
||
|
|
||
|
$table = (new CTableInfo())
|
||
|
->setHeader(array_merge($header, [
|
||
|
_('Info'),
|
||
|
_('Host'),
|
||
|
_('Problem'),
|
||
|
($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY) ? _('Operational data') : null,
|
||
|
_('Duration'),
|
||
|
_('Update'),
|
||
|
_('Actions'),
|
||
|
_('Tags')
|
||
|
]));
|
||
|
|
||
|
$data = [
|
||
|
'last_clock' => 0,
|
||
|
'sortorder' => ZBX_SORT_DOWN,
|
||
|
'show_three_columns' => false,
|
||
|
'show_two_columns' => false
|
||
|
];
|
||
|
|
||
|
$today = strtotime('today');
|
||
|
|
||
|
// Unset triggers, which missing in problems array.
|
||
|
if ($problems) {
|
||
|
$objectids = [];
|
||
|
|
||
|
foreach ($problems as $problem) {
|
||
|
$objectids[$problem['objectid']] = true;
|
||
|
}
|
||
|
|
||
|
$triggers = array_intersect_key($triggers, $objectids);
|
||
|
}
|
||
|
|
||
|
$triggers_hosts = getTriggersHostsList($triggers);
|
||
|
$triggers_hosts = makeTriggersHostsList($triggers_hosts);
|
||
|
|
||
|
$tags = makeTags($problems);
|
||
|
|
||
|
if (array_key_exists('show_suppressed', $filter) && $filter['show_suppressed']) {
|
||
|
CScreenProblem::addSuppressionNames($problems);
|
||
|
}
|
||
|
|
||
|
foreach ($problems as $problem) {
|
||
|
$trigger = $triggers[$problem['objectid']];
|
||
|
|
||
|
$cell_clock = ($problem['clock'] >= $today)
|
||
|
? zbx_date2str(TIME_FORMAT_SECONDS, $problem['clock'])
|
||
|
: zbx_date2str(DATE_TIME_FORMAT_SECONDS, $problem['clock']);
|
||
|
|
||
|
if ($url_details !== null) {
|
||
|
$url_details
|
||
|
->setArgument('triggerid', $problem['objectid'])
|
||
|
->setArgument('eventid', $problem['eventid']);
|
||
|
$cell_clock = new CCol(new CLink($cell_clock, $url_details));
|
||
|
}
|
||
|
else {
|
||
|
$cell_clock = new CCol($cell_clock);
|
||
|
}
|
||
|
|
||
|
if ($show_timeline) {
|
||
|
if ($data['last_clock'] != 0) {
|
||
|
CScreenProblem::addTimelineBreakpoint($table, $data, $problem, false, false);
|
||
|
}
|
||
|
$data['last_clock'] = $problem['clock'];
|
||
|
|
||
|
$row = [
|
||
|
$cell_clock->addClass(ZBX_STYLE_TIMELINE_DATE),
|
||
|
(new CCol())
|
||
|
->addClass(ZBX_STYLE_TIMELINE_AXIS)
|
||
|
->addClass(ZBX_STYLE_TIMELINE_DOT),
|
||
|
(new CCol())->addClass(ZBX_STYLE_TIMELINE_TD)
|
||
|
];
|
||
|
}
|
||
|
else {
|
||
|
$row = [
|
||
|
$cell_clock
|
||
|
->addClass(ZBX_STYLE_NOWRAP)
|
||
|
->addClass(ZBX_STYLE_RIGHT)
|
||
|
];
|
||
|
}
|
||
|
|
||
|
$info_icons = [];
|
||
|
if (array_key_exists('suppression_data', $problem)) {
|
||
|
if (count($problem['suppression_data']) == 1
|
||
|
&& $problem['suppression_data'][0]['maintenanceid'] == 0
|
||
|
&& isEventRecentlyUnsuppressed($problem['acknowledges'], $unsuppression_action)) {
|
||
|
// Show blinking button if the last manual suppression was recently revoked.
|
||
|
$user_unsuppressed = array_key_exists($unsuppression_action['userid'], $actions['users'])
|
||
|
? getUserFullname($actions['users'][$unsuppression_action['userid']])
|
||
|
: _('Inaccessible user');
|
||
|
|
||
|
$info_icons[] = (new CButtonIcon(ZBX_ICON_EYE))
|
||
|
->addClass(ZBX_STYLE_COLOR_ICON)
|
||
|
->addClass('js-blink')
|
||
|
->setHint(_s('Unsuppressed by: %1$s', $user_unsuppressed));
|
||
|
}
|
||
|
elseif ($problem['suppression_data']) {
|
||
|
$info_icons[] = makeSuppressedProblemIcon($problem['suppression_data'], false);
|
||
|
}
|
||
|
elseif (isEventRecentlySuppressed($problem['acknowledges'], $suppression_action)) {
|
||
|
// Show blinking button if suppression was made but is not yet processed by server.
|
||
|
$info_icons[] = makeSuppressedProblemIcon([[
|
||
|
'suppress_until' => $suppression_action['suppress_until'],
|
||
|
'username' => array_key_exists($suppression_action['userid'], $actions['users'])
|
||
|
? getUserFullname($actions['users'][$suppression_action['userid']])
|
||
|
: _('Inaccessible user')
|
||
|
]], true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// operational data
|
||
|
$opdata = null;
|
||
|
if ($show_opdata != OPERATIONAL_DATA_SHOW_NONE) {
|
||
|
|
||
|
if ($trigger['opdata'] === '') {
|
||
|
if ($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY) {
|
||
|
$opdata = (new CCol(CScreenProblem::getLatestValues($trigger['items'])))->addClass('latest-values');
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
$opdata = CMacrosResolverHelper::resolveTriggerOpdata(
|
||
|
[
|
||
|
'triggerid' => $trigger['triggerid'],
|
||
|
'expression' => $trigger['expression'],
|
||
|
'opdata' => $trigger['opdata'],
|
||
|
'clock' => $problem['clock'],
|
||
|
'ns' => $problem['ns']
|
||
|
],
|
||
|
[
|
||
|
'events' => true,
|
||
|
'html' => true
|
||
|
]
|
||
|
);
|
||
|
|
||
|
if ($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY) {
|
||
|
$opdata = (new CCol($opdata))
|
||
|
->addClass('opdata')
|
||
|
->addClass(ZBX_STYLE_WORDWRAP);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$can_be_closed = ($trigger['manual_close'] == ZBX_TRIGGER_MANUAL_CLOSE_ALLOWED && $allowed['close']);
|
||
|
|
||
|
if ($problem['r_eventid'] != 0) {
|
||
|
$can_be_closed = false;
|
||
|
}
|
||
|
else {
|
||
|
foreach ($problem['acknowledges'] as $acknowledge) {
|
||
|
if (($acknowledge['action'] & ZBX_PROBLEM_UPDATE_CLOSE) == ZBX_PROBLEM_UPDATE_CLOSE) {
|
||
|
$can_be_closed = false;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Create acknowledge link.
|
||
|
$is_acknowledged = ($problem['acknowledged'] == EVENT_ACKNOWLEDGED);
|
||
|
$problem_update_link = ($allowed['add_comments'] || $allowed['change_severity'] || $allowed['acknowledge']
|
||
|
|| $can_be_closed || $allowed['suppress'])
|
||
|
? (new CLink(_('Update')))
|
||
|
->addClass(ZBX_STYLE_LINK_ALT)
|
||
|
->setAttribute('data-eventid', $problem['eventid'])
|
||
|
->onClick('acknowledgePopUp({eventids: [this.dataset.eventid]}, this);')
|
||
|
: new CSpan(_('Update'));
|
||
|
|
||
|
$table->addRow(array_merge($row, [
|
||
|
makeInformationList($info_icons),
|
||
|
$triggers_hosts[$trigger['triggerid']],
|
||
|
CSeverityHelper::makeSeverityCell((int) $problem['severity'],
|
||
|
(($show_opdata == OPERATIONAL_DATA_SHOW_WITH_PROBLEM && $opdata)
|
||
|
? [$problem['name'], ' (', $opdata, ')']
|
||
|
: $problem['name']
|
||
|
)
|
||
|
)->addClass(ZBX_STYLE_WORDBREAK),
|
||
|
($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY) ? $opdata : null,
|
||
|
zbx_date2age($problem['clock']),
|
||
|
$problem_update_link,
|
||
|
makeEventActionsIcons($problem['eventid'], $actions['all_actions'], $actions['users'], $is_acknowledged),
|
||
|
$tags[$problem['eventid']]
|
||
|
]));
|
||
|
}
|
||
|
|
||
|
return $table;
|
||
|
}
|