1<?php
2/*
3** Zabbix
4** Copyright (C) 2001-2021 Zabbix SIA
5**
6** This program is free software; you can redistribute it and/or modify
7** it under the terms of the GNU General Public License as published by
8** the Free Software Foundation; either version 2 of the License, or
9** (at your option) any later version.
10**
11** This program is distributed in the hope that it will be useful,
12** but WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14** GNU General Public License for more details.
15**
16** You should have received a copy of the GNU General Public License
17** along with this program; if not, write to the Free Software
18** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19**/
20
21
22require_once dirname(__FILE__).'/include/config.inc.php';
23require_once dirname(__FILE__).'/include/items.inc.php';
24
25$page['title'] = _('Queue');
26$page['file'] = 'queue.php';
27
28define('ZBX_PAGE_DO_REFRESH', 1);
29
30require_once dirname(__FILE__).'/include/page_header.php';
31
32$queueModes = [
33	QUEUE_OVERVIEW,
34	QUEUE_OVERVIEW_BY_PROXY,
35	QUEUE_DETAILS
36];
37
38//		VAR			TYPE	OPTIONAL FLAGS	VALIDATION	EXCEPTION
39$fields = [
40	'config' => [T_ZBX_INT, O_OPT, P_SYS, IN($queueModes), null]
41];
42
43check_fields($fields);
44
45$config = getRequest('config', CProfile::get('web.queue.config', 0));
46CProfile::update('web.queue.config', $config, PROFILE_TYPE_INT);
47
48// fetch data
49$zabbixServer = new CZabbixServer($ZBX_SERVER, $ZBX_SERVER_PORT, ZBX_SOCKET_TIMEOUT, ZBX_SOCKET_BYTES_LIMIT);
50$queueRequests = [
51	QUEUE_OVERVIEW => CZabbixServer::QUEUE_OVERVIEW,
52	QUEUE_OVERVIEW_BY_PROXY => CZabbixServer::QUEUE_OVERVIEW_BY_PROXY,
53	QUEUE_DETAILS => CZabbixServer::QUEUE_DETAILS
54];
55$queueData = $zabbixServer->getQueue($queueRequests[$config], get_cookie(ZBX_SESSION_NAME), QUEUE_DETAIL_ITEM_COUNT);
56
57// check for errors error
58if ($zabbixServer->getError()) {
59	error($zabbixServer->getError());
60	show_error_message(_('Cannot display item queue.'));
61
62	require_once dirname(__FILE__).'/include/page_footer.php';
63}
64
65$widget = (new CWidget())
66	->setTitle(_('Queue of items to be updated'))
67	->setControls((new CTag('nav', true, [
68		(new CForm('get'))
69			->cleanItems()
70			->addItem((new CList())
71				->addItem(
72					(new CComboBox('config', $config, 'submit();', [
73						QUEUE_OVERVIEW => _('Overview'),
74						QUEUE_OVERVIEW_BY_PROXY => _('Overview by proxy'),
75						QUEUE_DETAILS => _('Details')
76					]))->removeId()
77				)
78			)
79		]))
80			->setAttribute('aria-label', _('Content controls'))
81	);
82
83$table = new CTableInfo();
84
85$severityConfig = select_config();
86
87// overview
88if ($config == QUEUE_OVERVIEW) {
89	$itemTypes = [
90		ITEM_TYPE_ZABBIX,
91		ITEM_TYPE_ZABBIX_ACTIVE,
92		ITEM_TYPE_SIMPLE,
93		ITEM_TYPE_SNMPV1,
94		ITEM_TYPE_SNMPV2C,
95		ITEM_TYPE_SNMPV3,
96		ITEM_TYPE_INTERNAL,
97		ITEM_TYPE_AGGREGATE,
98		ITEM_TYPE_EXTERNAL,
99		ITEM_TYPE_DB_MONITOR,
100		ITEM_TYPE_HTTPAGENT,
101		ITEM_TYPE_IPMI,
102		ITEM_TYPE_SSH,
103		ITEM_TYPE_TELNET,
104		ITEM_TYPE_JMX,
105		ITEM_TYPE_CALCULATED
106	];
107
108	$table->setHeader([
109		_('Items'),
110		_('5 seconds'),
111		_('10 seconds'),
112		_('30 seconds'),
113		_('1 minute'),
114		_('5 minutes'),
115		_('More than 10 minutes')
116	]);
117
118	$queueData = zbx_toHash($queueData, 'itemtype');
119
120	foreach ($itemTypes as $type) {
121		if (isset($queueData[$type])) {
122			$itemTypeData = $queueData[$type];
123		}
124		else {
125			$itemTypeData = [
126				'delay5' => 0,
127				'delay10' => 0,
128				'delay30' => 0,
129				'delay60' => 0,
130				'delay300' => 0,
131				'delay600' => 0
132			];
133		}
134
135		$table->addRow([
136			item_type2str($type),
137			getSeverityCell(TRIGGER_SEVERITY_NOT_CLASSIFIED, $severityConfig, $itemTypeData['delay5'],
138				!$itemTypeData['delay5']
139			),
140			getSeverityCell(TRIGGER_SEVERITY_INFORMATION, $severityConfig, $itemTypeData['delay10'],
141				!$itemTypeData['delay10']
142			),
143			getSeverityCell(TRIGGER_SEVERITY_WARNING, $severityConfig, $itemTypeData['delay30'],
144				!$itemTypeData['delay30']
145			),
146			getSeverityCell(TRIGGER_SEVERITY_AVERAGE, $severityConfig, $itemTypeData['delay60'],
147				!$itemTypeData['delay60']
148			),
149			getSeverityCell(TRIGGER_SEVERITY_HIGH, $severityConfig, $itemTypeData['delay300'],
150				!$itemTypeData['delay300']
151			),
152			getSeverityCell(TRIGGER_SEVERITY_DISASTER, $severityConfig, $itemTypeData['delay600'],
153				!$itemTypeData['delay600']
154			)
155		]);
156	}
157}
158
159// overview by proxy
160elseif ($config == QUEUE_OVERVIEW_BY_PROXY) {
161	$proxies = API::proxy()->get([
162		'output' => ['hostid', 'host'],
163		'preservekeys' => true
164	]);
165	order_result($proxies, 'host');
166
167	$proxies[0] = ['host' => _('Server')];
168
169	$table->setHeader([
170		_('Proxy'),
171		_('5 seconds'),
172		_('10 seconds'),
173		_('30 seconds'),
174		_('1 minute'),
175		_('5 minutes'),
176		_('More than 10 minutes')
177	]);
178
179	$queueData = zbx_toHash($queueData, 'proxyid');
180	foreach ($proxies as $proxyId => $proxy) {
181		if (isset($queueData[$proxyId])) {
182			$proxyData = $queueData[$proxyId];
183		}
184		else {
185			$proxyData = [
186				'delay5' => 0,
187				'delay10' => 0,
188				'delay30' => 0,
189				'delay60' => 0,
190				'delay300' => 0,
191				'delay600' => 0
192			];
193		}
194
195		$table->addRow([
196			$proxy['host'],
197			getSeverityCell(TRIGGER_SEVERITY_NOT_CLASSIFIED, $severityConfig, $proxyData['delay5'],
198				!$proxyData['delay5']
199			),
200			getSeverityCell(TRIGGER_SEVERITY_INFORMATION, $severityConfig, $proxyData['delay10'],
201				!$proxyData['delay10']
202			),
203			getSeverityCell(TRIGGER_SEVERITY_WARNING, $severityConfig, $proxyData['delay30'], !$proxyData['delay30']),
204			getSeverityCell(TRIGGER_SEVERITY_AVERAGE, $severityConfig, $proxyData['delay60'], !$proxyData['delay60']),
205			getSeverityCell(TRIGGER_SEVERITY_HIGH, $severityConfig, $proxyData['delay300'], !$proxyData['delay300']),
206			getSeverityCell(TRIGGER_SEVERITY_DISASTER, $severityConfig, $proxyData['delay600'], !$proxyData['delay600'])
207		]);
208	}
209}
210
211// details
212elseif ($config == QUEUE_DETAILS) {
213	$queueData = zbx_toHash($queueData, 'itemid');
214
215	$items = API::Item()->get([
216		'output' => ['itemid', 'hostid', 'name', 'key_'],
217		'selectHosts' => ['name'],
218		'itemids' => array_keys($queueData),
219		'webitems' => true,
220		'preservekeys' => true
221	]);
222
223	if (count($queueData) != count($items)) {
224		$items += API::DiscoveryRule()->get([
225			'output' => ['itemid', 'hostid', 'name', 'key_'],
226			'selectHosts' => ['name'],
227			'itemids' => array_diff(array_keys($queueData), array_keys($items)),
228			'preservekeys' => true
229		]);
230	}
231
232	$items = CMacrosResolverHelper::resolveItemNames($items);
233
234	// get hosts for queue items
235	$hostIds = zbx_objectValues($items, 'hostid');
236	$hostIds = array_keys(array_flip($hostIds));
237
238	$hosts = API::Host()->get([
239		'output' => ['hostid', 'proxy_hostid'],
240		'hostids' => $hostIds,
241		'preservekeys' => true
242	]);
243
244	// get proxies for those hosts
245	$proxyHostIds = [];
246	foreach ($hosts as $host) {
247		if ($host['proxy_hostid']) {
248			$proxyHostIds[$host['proxy_hostid']] = $host['proxy_hostid'];
249		}
250	}
251
252	if ($proxyHostIds) {
253		$proxies = API::Proxy()->get([
254			'proxyids' => $proxyHostIds,
255			'output' => ['proxyid', 'host'],
256			'preservekeys' => true
257		]);
258	}
259
260	$table->setHeader([
261		_('Scheduled check'),
262		_('Delayed by'),
263		_('Host'),
264		_('Name')
265	]);
266
267	$i = 0;
268	foreach ($queueData as $itemData) {
269		if (!isset($items[$itemData['itemid']])) {
270			continue;
271		}
272
273		// display only the first QUEUE_DETAIL_ITEM_COUNT items (can only occur when using old server versions)
274		$i++;
275		if ($i > QUEUE_DETAIL_ITEM_COUNT) {
276			break;
277		}
278
279		$item = $items[$itemData['itemid']];
280		$host = reset($item['hosts']);
281
282		$table->addRow([
283			zbx_date2str(DATE_TIME_FORMAT_SECONDS, $itemData['nextcheck']),
284			zbx_date2age($itemData['nextcheck']),
285			isset($proxies[$hosts[$item['hostid']]['proxy_hostid']])
286				? $proxies[$hosts[$item['hostid']]['proxy_hostid']]['host'].NAME_DELIMITER.$host['name']
287				: $host['name'],
288			$item['name_expanded']
289		]);
290	}
291}
292
293// display the table footer
294if ($config == QUEUE_OVERVIEW_BY_PROXY) {
295	$total = _('Total').': '.$table->getNumRows();
296}
297elseif ($config == QUEUE_DETAILS) {
298	$total = _s('Displaying %1$s of %2$s found', $table->getNumRows(), $zabbixServer->getTotalCount());
299}
300else {
301	$total = null;
302}
303
304if ($total !== null) {
305	$total = (new CDiv())
306		->addClass(ZBX_STYLE_TABLE_PAGING)
307		->addItem((new CDiv())
308			->addClass(ZBX_STYLE_PAGING_BTN_CONTAINER)
309			->addItem((new CDiv())
310				->addClass(ZBX_STYLE_TABLE_STATS)
311				->addItem($total)
312			)
313		);
314}
315
316$widget
317	->addItem($table)
318	->addItem($total)
319	->show();
320
321require_once dirname(__FILE__).'/include/page_footer.php';
322