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
63$submenu_source = [
64	QUEUE_OVERVIEW => _('Queue overview'),
65	QUEUE_OVERVIEW_BY_PROXY => _('Queue overview by proxy'),
66	QUEUE_DETAILS => _('Queue details')
67];
68
69$submenu = [];
70foreach ($submenu_source as $value => $label) {
71	$url = (new CUrl('queue.php'))
72		->setArgument('config', $value)
73		->getUrl();
74
75	$submenu[$url] = $label;
76}
77
78$widget = (new CWidget())
79	->setTitle(array_key_exists($config, $submenu_source) ? $submenu_source[$config] : null)
80	->setTitleSubmenu([
81		'main_section' => [
82			'items' => $submenu
83		]
84	]);
85
86$table = new CTableInfo();
87
88$severityConfig = select_config();
89
90// overview
91if ($config == QUEUE_OVERVIEW) {
92	$itemTypes = [
93		ITEM_TYPE_ZABBIX,
94		ITEM_TYPE_ZABBIX_ACTIVE,
95		ITEM_TYPE_SIMPLE,
96		ITEM_TYPE_SNMP,
97		ITEM_TYPE_INTERNAL,
98		ITEM_TYPE_AGGREGATE,
99		ITEM_TYPE_EXTERNAL,
100		ITEM_TYPE_DB_MONITOR,
101		ITEM_TYPE_HTTPAGENT,
102		ITEM_TYPE_IPMI,
103		ITEM_TYPE_SSH,
104		ITEM_TYPE_TELNET,
105		ITEM_TYPE_JMX,
106		ITEM_TYPE_CALCULATED
107	];
108
109	$table->setHeader([
110		_('Items'),
111		_('5 seconds'),
112		_('10 seconds'),
113		_('30 seconds'),
114		_('1 minute'),
115		_('5 minutes'),
116		_('More than 10 minutes')
117	]);
118
119	if (!$zabbixServer->getError()) {
120		$queueData = zbx_toHash($queueData, 'itemtype');
121
122		foreach ($itemTypes as $type) {
123			if (isset($queueData[$type])) {
124				$itemTypeData = $queueData[$type];
125			}
126			else {
127				$itemTypeData = [
128					'delay5' => 0,
129					'delay10' => 0,
130					'delay30' => 0,
131					'delay60' => 0,
132					'delay300' => 0,
133					'delay600' => 0
134				];
135			}
136
137			$table->addRow([
138				item_type2str($type),
139				getSeverityCell(TRIGGER_SEVERITY_NOT_CLASSIFIED, $severityConfig, $itemTypeData['delay5'],
140					!$itemTypeData['delay5']
141				),
142				getSeverityCell(TRIGGER_SEVERITY_INFORMATION, $severityConfig, $itemTypeData['delay10'],
143					!$itemTypeData['delay10']
144				),
145				getSeverityCell(TRIGGER_SEVERITY_WARNING, $severityConfig, $itemTypeData['delay30'],
146					!$itemTypeData['delay30']
147				),
148				getSeverityCell(TRIGGER_SEVERITY_AVERAGE, $severityConfig, $itemTypeData['delay60'],
149					!$itemTypeData['delay60']
150				),
151				getSeverityCell(TRIGGER_SEVERITY_HIGH, $severityConfig, $itemTypeData['delay300'],
152					!$itemTypeData['delay300']
153				),
154				getSeverityCell(TRIGGER_SEVERITY_DISASTER, $severityConfig, $itemTypeData['delay600'],
155					!$itemTypeData['delay600']
156				)
157			]);
158		}
159	}
160}
161
162// overview by proxy
163elseif ($config == QUEUE_OVERVIEW_BY_PROXY) {
164	$table->setHeader([
165		_('Proxy'),
166		_('5 seconds'),
167		_('10 seconds'),
168		_('30 seconds'),
169		_('1 minute'),
170		_('5 minutes'),
171		_('More than 10 minutes')
172	]);
173
174	if (!$zabbixServer->getError()) {
175		$proxies = API::proxy()->get([
176			'output' => ['hostid', 'host'],
177			'preservekeys' => true
178		]);
179		order_result($proxies, 'host');
180
181		$proxies[0] = ['host' => _('Server')];
182
183		$queueData = zbx_toHash($queueData, 'proxyid');
184		foreach ($proxies as $proxyId => $proxy) {
185			if (isset($queueData[$proxyId])) {
186				$proxyData = $queueData[$proxyId];
187			}
188			else {
189				$proxyData = [
190					'delay5' => 0,
191					'delay10' => 0,
192					'delay30' => 0,
193					'delay60' => 0,
194					'delay300' => 0,
195					'delay600' => 0
196				];
197			}
198
199			$table->addRow([
200				$proxy['host'],
201				getSeverityCell(TRIGGER_SEVERITY_NOT_CLASSIFIED, $severityConfig, $proxyData['delay5'],
202					!$proxyData['delay5']
203				),
204				getSeverityCell(TRIGGER_SEVERITY_INFORMATION, $severityConfig, $proxyData['delay10'],
205					!$proxyData['delay10']
206				),
207				getSeverityCell(TRIGGER_SEVERITY_WARNING, $severityConfig, $proxyData['delay30'], !$proxyData['delay30']),
208				getSeverityCell(TRIGGER_SEVERITY_AVERAGE, $severityConfig, $proxyData['delay60'], !$proxyData['delay60']),
209				getSeverityCell(TRIGGER_SEVERITY_HIGH, $severityConfig, $proxyData['delay300'], !$proxyData['delay300']),
210				getSeverityCell(TRIGGER_SEVERITY_DISASTER, $severityConfig, $proxyData['delay600'], !$proxyData['delay600'])
211			]);
212		}
213	}
214}
215
216// details
217elseif ($config == QUEUE_DETAILS) {
218	$table->setHeader([
219		_('Scheduled check'),
220		_('Delayed by'),
221		_('Host'),
222		_('Name'),
223		_('Proxy')
224	]);
225
226	if (!$zabbixServer->getError()) {
227		$queueData = zbx_toHash($queueData, 'itemid');
228
229		$items = API::Item()->get([
230			'output' => ['itemid', 'hostid', 'name', 'key_'],
231			'selectHosts' => ['name'],
232			'itemids' => array_keys($queueData),
233			'webitems' => true,
234			'preservekeys' => true
235		]);
236
237		if (count($queueData) != count($items)) {
238			$items += API::DiscoveryRule()->get([
239				'output' => ['itemid', 'hostid', 'name', 'key_'],
240				'selectHosts' => ['name'],
241				'itemids' => array_diff(array_keys($queueData), array_keys($items)),
242				'preservekeys' => true
243			]);
244		}
245
246		$items = CMacrosResolverHelper::resolveItemNames($items);
247
248		// get hosts for queue items
249		$hostIds = zbx_objectValues($items, 'hostid');
250		$hostIds = array_keys(array_flip($hostIds));
251
252		$hosts = API::Host()->get([
253			'output' => ['hostid', 'proxy_hostid'],
254			'hostids' => $hostIds,
255			'preservekeys' => true
256		]);
257
258		// get proxies for those hosts
259		$proxyHostIds = [];
260		foreach ($hosts as $host) {
261			if ($host['proxy_hostid']) {
262				$proxyHostIds[$host['proxy_hostid']] = $host['proxy_hostid'];
263			}
264		}
265
266		$proxies = [];
267
268		if ($proxyHostIds) {
269			$proxies = API::Proxy()->get([
270				'proxyids' => $proxyHostIds,
271				'output' => ['proxyid', 'host'],
272				'preservekeys' => true
273			]);
274		}
275
276		$i = 0;
277		foreach ($queueData as $itemData) {
278			if (!isset($items[$itemData['itemid']])) {
279				continue;
280			}
281
282			// display only the first QUEUE_DETAIL_ITEM_COUNT items (can only occur when using old server versions)
283			$i++;
284			if ($i > QUEUE_DETAIL_ITEM_COUNT) {
285				break;
286			}
287
288			$item = $items[$itemData['itemid']];
289			$host = reset($item['hosts']);
290
291			$table->addRow([
292				zbx_date2str(DATE_TIME_FORMAT_SECONDS, $itemData['nextcheck']),
293				zbx_date2age($itemData['nextcheck']),
294				$host['name'],
295				$item['name_expanded'],
296				array_key_exists($hosts[$item['hostid']]['proxy_hostid'], $proxies)
297					? $proxies[$hosts[$item['hostid']]['proxy_hostid']]['host']
298					: ''
299			]);
300		}
301	}
302}
303
304// display the table footer
305if ($config == QUEUE_OVERVIEW_BY_PROXY) {
306	$total = _('Total').': '.$table->getNumRows();
307}
308elseif ($config == QUEUE_DETAILS) {
309	$total = _s('Displaying %1$s of %2$s found', $table->getNumRows(), $zabbixServer->getTotalCount());
310}
311else {
312	$total = null;
313}
314
315if ($total !== null) {
316	$total = (new CDiv())
317		->addClass(ZBX_STYLE_TABLE_PAGING)
318		->addItem((new CDiv())
319			->addClass(ZBX_STYLE_PAGING_BTN_CONTAINER)
320			->addItem((new CDiv())
321				->addClass(ZBX_STYLE_TABLE_STATS)
322				->addItem($total)
323			)
324		);
325}
326
327$widget
328	->addItem($table)
329	->addItem($total)
330	->show();
331
332require_once dirname(__FILE__).'/include/page_footer.php';
333