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
22/**
23 * A class to display web scenario details as a screen element by given "httptestid".
24 */
25class CScreenHttpTestDetails extends CScreenBase {
26
27	/**
28	 * Process screen.
29	 *
30	 * @return CDiv (screen inside container)
31	 */
32	public function get() {
33		$this->dataId = 'httptest_details';
34
35		$httptest = API::HttpTest()->get([
36			'output' => ['httptestid', 'name', 'hostid'],
37			'selectSteps' => ['httpstepid', 'name', 'no'],
38			'httptestids' => $this->profileIdx2,
39			'preservekeys' => true
40		]);
41		$httptest = reset($httptest);
42
43		if (!$httptest) {
44			$messages = [[
45				'type' => 'error',
46				'message' => _('No permissions to referred object or it does not exist!')
47			]];
48
49			return $this->getOutput(makeMessageBox(false, $messages, null, false, false));
50		}
51
52		$httptest['lastfailedstep'] = 0;
53		$httptest['error'] = '';
54
55		// fetch http test execution data
56		$httptest_data = Manager::HttpTest()->getLastData([$httptest['httptestid']]);
57
58		if ($httptest_data) {
59			$httptest_data = reset($httptest_data);
60		}
61
62		// fetch HTTP step items
63		$items = DBfetchArray(DBselect(
64			'SELECT i.value_type,i.valuemapid,i.units,i.itemid,hi.type,hs.httpstepid'.
65			' FROM items i,httpstepitem hi,httpstep hs'.
66			' WHERE hi.itemid=i.itemid'.
67				' AND hi.httpstepid=hs.httpstepid'.
68				' AND hs.httptestid='.zbx_dbstr($httptest['httptestid'])
69		));
70
71		$step_items = [];
72
73		foreach ($items as $item) {
74			$step_items[$item['httpstepid']][$item['type']] = $item;
75		}
76
77		// fetch HTTP item history
78		$item_history = Manager::History()->getLastValues($items);
79
80		$table = (new CTableInfo())
81			->setHeader([
82				_('Step'),
83				_('Speed'),
84				_('Response time'),
85				_('Response code'),
86				_('Status')
87		]);
88
89		$total_time = [
90			'value' => 0,
91			'value_type' => null,
92			'valuemapid' => null,
93			'units' => null
94		];
95
96		order_result($httptest['steps'], 'no');
97
98		foreach ($httptest['steps'] as $step_data) {
99			$items_by_type = $step_items[$step_data['httpstepid']];
100
101			$status['msg'] = _('OK');
102			$status['style'] = ZBX_STYLE_GREEN;
103			$status['afterError'] = false;
104
105			if (!array_key_exists('lastfailedstep', $httptest_data)) {
106				$status['msg'] = '';
107			}
108			elseif ($httptest_data['lastfailedstep'] != 0) {
109				if ($httptest_data['lastfailedstep'] == $step_data['no']) {
110					$status['msg'] = ($httptest_data['error'] === null)
111						? _('Unknown error')
112						: _s('Error: %1$s', $httptest_data['error']);
113					$status['style'] = ZBX_STYLE_RED;
114				}
115				elseif ($httptest_data['lastfailedstep'] < $step_data['no']) {
116					$status['msg'] = _('Unknown');
117					$status['style'] = ZBX_STYLE_GREY;
118					$status['afterError'] = true;
119				}
120			}
121
122			foreach ($items_by_type as &$item) {
123				// Calculate the total time it took to execute the scenario.
124				// Skip steps that come after a failed step.
125				if (!$status['afterError'] && $item['type'] == HTTPSTEP_ITEM_TYPE_TIME) {
126					$total_time['value_type'] = $item['value_type'];
127					$total_time['valuemapid'] = $item['valuemapid'];
128					$total_time['units'] = $item['units'];
129
130					if (array_key_exists($item['itemid'], $item_history)) {
131						$history = $item_history[$item['itemid']][0];
132						$total_time['value'] += $history['value'];
133					}
134				}
135			}
136			unset($item);
137
138			// step speed
139			$speed_item = $items_by_type[HTTPSTEP_ITEM_TYPE_IN];
140			if (!$status['afterError'] && array_key_exists($speed_item['itemid'], $item_history)
141					&& $item_history[$speed_item['itemid']][0]['value'] > 0) {
142				$speed = formatHistoryValue($item_history[$speed_item['itemid']][0]['value'], $speed_item);
143			}
144			else {
145				$speed = UNKNOWN_VALUE;
146			}
147
148			// step response time
149			$resptime_item = $items_by_type[HTTPSTEP_ITEM_TYPE_TIME];
150			if (!$status['afterError'] && array_key_exists($resptime_item['itemid'], $item_history)
151					&& $item_history[$resptime_item['itemid']][0]['value'] > 0) {
152				$resp_time = formatHistoryValue($item_history[$resptime_item['itemid']][0]['value'], $resptime_item);
153			}
154			else {
155				$resp_time = UNKNOWN_VALUE;
156			}
157
158			// step response code
159			$resp_item = $items_by_type[HTTPSTEP_ITEM_TYPE_RSPCODE];
160			if (!$status['afterError'] && array_key_exists($resp_item['itemid'], $item_history)
161					&& $item_history[$resp_item['itemid']][0]['value'] > 0) {
162				$resp = formatHistoryValue($item_history[$resp_item['itemid']][0]['value'], $resp_item);
163			}
164			else {
165				$resp = UNKNOWN_VALUE;
166			}
167
168			$table->addRow([
169				CMacrosResolverHelper::resolveHttpTestName($httptest['hostid'], $step_data['name']),
170				$speed,
171				$resp_time,
172				$resp,
173				(new CSpan($status['msg']))->addClass($status['style'])
174			]);
175		}
176
177
178		if (!array_key_exists('lastfailedstep', $httptest_data)) {
179			$status_info = '';
180		}
181		elseif ($httptest_data['lastfailedstep'] != 0) {
182			$status_info = (new CSpan(
183				($httptest_data['error'] === null) ? _('Unknown error') : _s('Error: %1$s', $httptest_data['error'])
184			))->addClass(ZBX_STYLE_RED);
185		}
186		else {
187			$status_info = (new CSpan(_('OK')))->addClass(ZBX_STYLE_GREEN);
188		}
189
190		$table->addRow([
191			bold(_('TOTAL')),
192			'',
193			bold(($total_time['value']) ? formatHistoryValue($total_time['value'], $total_time) : UNKNOWN_VALUE),
194			'',
195			$status_info
196		]);
197
198		return $this->getOutput($table);
199	}
200}
201