/** * Process screen. * * @return CDiv (screen inside container) */ public function get() { $error = null; $timeOffset = null; $timeZone = null; switch ($this->screenitem['style']) { case TIME_TYPE_HOST: $items = API::Item()->get(array('itemids' => $this->screenitem['resourceid'], 'selectHosts' => array('host'), 'output' => array('itemid', 'value_type'))); $item = reset($items); $host = reset($item['hosts']); $lastValue = Manager::History()->getLast(array($item)); if ($lastValue) { $lastValue = reset($lastValue[$item['itemid']]); $item['lastvalue'] = $lastValue['value']; $item['lastclock'] = $lastValue['clock']; } else { $item['lastvalue'] = '0'; $item['lastclock'] = '0'; } $timeType = $host['host']; preg_match('/([+-]{1})([\\d]{1,2}):([\\d]{1,2})/', $item['lastvalue'], $arr); if (!empty($arr)) { $timeZone = $arr[2] * SEC_PER_HOUR + $arr[3] * SEC_PER_MIN; if ($arr[1] == '-') { $timeZone = 0 - $timeZone; } } if ($lastvalue = strtotime($item['lastvalue'])) { $diff = time() - $item['lastclock']; $timeOffset = $lastvalue + $diff; } else { $error = _('NO DATA'); } break; case TIME_TYPE_SERVER: $error = null; $timeType = _('SERVER'); $timeOffset = time(); $timeZone = date('Z'); break; default: $error = null; $timeType = _('LOCAL'); $timeOffset = null; $timeZone = null; break; } if ($this->screenitem['width'] > $this->screenitem['height']) { $this->screenitem['width'] = $this->screenitem['height']; } $item = new CFlashClock($this->screenitem['width'], $this->screenitem['height'], $this->action); $item->setTimeError($error); $item->setTimeType($timeType); $item->setTimeZone($timeZone); $item->setTimeOffset($timeOffset); $flashclockOverDiv = new CDiv(null, 'flashclock'); $flashclockOverDiv->setAttribute('style', 'width: ' . $this->screenitem['width'] . 'px; height: ' . $this->screenitem['height'] . 'px;'); return $this->getOutput(array($item, $flashclockOverDiv)); }
protected function selectData() { $this->data = array(); $now = time(null); if (isset($this->stime)) { $this->from_time = $this->stime; $this->to_time = $this->stime + $this->period; } else { $this->to_time = $now - SEC_PER_HOUR * $this->from; $this->from_time = $this->to_time - $this->period; } $strvaluelength = 0; // we need to know how long in px will be our legend // fetch values for items with the "last" function $lastValueItems = array(); foreach ($this->items as $item) { if ($item['calc_fnc'] == CALC_FNC_LST) { $lastValueItems[] = $item; } } if ($lastValueItems) { $history = Manager::History()->getLast($lastValueItems); } $config = select_config(); for ($i = 0; $i < $this->num; $i++) { $item = get_item_by_itemid($this->items[$i]['itemid']); $type = $this->items[$i]['calc_type']; $from_time = $this->from_time; $to_time = $this->to_time; $sql_arr = array(); // override item history setting with housekeeping settings if ($config['hk_history_global']) { $item['history'] = $config['hk_history']; } $trendsEnabled = $config['hk_trends_global'] ? $config['hk_trends'] > 0 : $item['trends'] > 0; if (!$trendsEnabled || $item['history'] * SEC_PER_DAY > time() - ($from_time + $this->period / 2)) { $this->dataFrom = 'history'; array_push($sql_arr, 'SELECT h.itemid,' . 'AVG(h.value) AS avg,MIN(h.value) AS min,' . 'MAX(h.value) AS max,MAX(h.clock) AS clock' . ' FROM history h' . ' WHERE h.itemid=' . zbx_dbstr($this->items[$i]['itemid']) . ' AND h.clock>=' . zbx_dbstr($from_time) . ' AND h.clock<=' . zbx_dbstr($to_time) . ' GROUP BY h.itemid', 'SELECT hu.itemid,' . 'AVG(hu.value) AS avg,MIN(hu.value) AS min,' . 'MAX(hu.value) AS max,MAX(hu.clock) AS clock' . ' FROM history_uint hu' . ' WHERE hu.itemid=' . zbx_dbstr($this->items[$i]['itemid']) . ' AND hu.clock>=' . zbx_dbstr($from_time) . ' AND hu.clock<=' . zbx_dbstr($to_time) . ' GROUP BY hu.itemid'); } else { $this->dataFrom = 'trends'; array_push($sql_arr, 'SELECT t.itemid,' . 'AVG(t.value_avg) AS avg,MIN(t.value_min) AS min,' . 'MAX(t.value_max) AS max,MAX(t.clock) AS clock' . ' FROM trends t' . ' WHERE t.itemid=' . zbx_dbstr($this->items[$i]['itemid']) . ' AND t.clock>=' . zbx_dbstr($from_time) . ' AND t.clock<=' . zbx_dbstr($to_time) . ' GROUP BY t.itemid', 'SELECT t.itemid,' . 'AVG(t.value_avg) AS avg,MIN(t.value_min) AS min,' . 'MAX(t.value_max) AS max,MAX(t.clock) AS clock' . ' FROM trends_uint t' . ' WHERE t.itemid=' . zbx_dbstr($this->items[$i]['itemid']) . ' AND t.clock>=' . zbx_dbstr($from_time) . ' AND t.clock<=' . zbx_dbstr($to_time) . ' GROUP BY t.itemid'); } $this->data[$this->items[$i]['itemid']][$type]['last'] = isset($history[$item['itemid']]) ? $history[$item['itemid']][0]['value'] : null; $this->data[$this->items[$i]['itemid']][$type]['shift_min'] = 0; $this->data[$this->items[$i]['itemid']][$type]['shift_max'] = 0; $this->data[$this->items[$i]['itemid']][$type]['shift_avg'] = 0; foreach ($sql_arr as $sql) { $result = DBselect($sql); while ($row = DBfetch($result)) { $this->data[$this->items[$i]['itemid']][$type]['min'] = $row['min']; $this->data[$this->items[$i]['itemid']][$type]['max'] = $row['max']; $this->data[$this->items[$i]['itemid']][$type]['avg'] = $row['avg']; $this->data[$this->items[$i]['itemid']][$type]['clock'] = $row['clock']; } unset($row); } switch ($this->items[$i]['calc_fnc']) { case CALC_FNC_MIN: $fncName = 'min'; break; case CALC_FNC_MAX: $fncName = 'max'; break; case CALC_FNC_LST: $fncName = 'last'; break; case CALC_FNC_AVG: default: $fncName = 'avg'; } $item_value = empty($this->data[$this->items[$i]['itemid']][$type][$fncName]) ? 0 : abs($this->data[$this->items[$i]['itemid']][$type][$fncName]); if ($type == GRAPH_ITEM_SUM) { $this->background = $i; $graph_sum = $item_value; } $this->sum += $item_value; $convertedUnit = zbx_strlen(convert_units(array('value' => $item_value, 'units' => $this->items[$i]['units']))); $strvaluelength = max($strvaluelength, $convertedUnit); } if (isset($graph_sum)) { $this->sum = $graph_sum; } $this->shiftlegendright += $strvaluelength * 7; }
public function addRelatedObjects(array $options, array $result) { $result = parent::addRelatedObjects($options, $result); $itemids = array_keys($result); // adding applications if ($options['selectApplications'] !== null && $options['selectApplications'] != API_OUTPUT_COUNT) { $relationMap = $this->createRelationMap($result, 'itemid', 'applicationid', 'items_applications'); $applications = API::Application()->get(array('output' => $options['selectApplications'], 'applicationids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); $result = $relationMap->mapMany($result, $applications, 'applications'); } // adding interfaces if ($options['selectInterfaces'] !== null && $options['selectInterfaces'] != API_OUTPUT_COUNT) { $relationMap = $this->createRelationMap($result, 'itemid', 'interfaceid'); $interfaces = API::HostInterface()->get(array('output' => $options['selectInterfaces'], 'interfaceids' => $relationMap->getRelatedIds(), 'nopermissions' => true, 'preservekeys' => true)); $result = $relationMap->mapMany($result, $interfaces, 'interfaces'); } // adding triggers if (!is_null($options['selectTriggers'])) { if ($options['selectTriggers'] != API_OUTPUT_COUNT) { $relationMap = $this->createRelationMap($result, 'itemid', 'triggerid', 'functions'); $triggers = API::Trigger()->get(array('output' => $options['selectTriggers'], 'triggerids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); if (!is_null($options['limitSelects'])) { order_result($triggers, 'description'); } $result = $relationMap->mapMany($result, $triggers, 'triggers', $options['limitSelects']); } else { $triggers = API::Trigger()->get(array('countOutput' => true, 'groupCount' => true, 'itemids' => $itemids)); $triggers = zbx_toHash($triggers, 'itemid'); foreach ($result as $itemid => $item) { if (isset($triggers[$itemid])) { $result[$itemid]['triggers'] = $triggers[$itemid]['rowscount']; } else { $result[$itemid]['triggers'] = 0; } } } } // adding graphs if (!is_null($options['selectGraphs'])) { if ($options['selectGraphs'] != API_OUTPUT_COUNT) { $relationMap = $this->createRelationMap($result, 'itemid', 'graphid', 'graphs_items'); $graphs = API::Graph()->get(array('output' => $options['selectGraphs'], 'graphids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); if (!is_null($options['limitSelects'])) { order_result($graphs, 'name'); } $result = $relationMap->mapMany($result, $graphs, 'graphs', $options['limitSelects']); } else { $graphs = API::Graph()->get(array('countOutput' => true, 'groupCount' => true, 'itemids' => $itemids)); $graphs = zbx_toHash($graphs, 'itemid'); foreach ($result as $itemid => $item) { if (isset($graphs[$itemid])) { $result[$itemid]['graphs'] = $graphs[$itemid]['rowscount']; } else { $result[$itemid]['graphs'] = 0; } } } } // adding discoveryrule if ($options['selectDiscoveryRule'] !== null && $options['selectDiscoveryRule'] != API_OUTPUT_COUNT) { $relationMap = new CRelationMap(); // discovered items $dbRules = DBselect('SELECT id1.itemid,id2.parent_itemid' . ' FROM item_discovery id1,item_discovery id2,items i' . ' WHERE ' . dbConditionInt('id1.itemid', $itemids) . ' AND id1.parent_itemid=id2.itemid' . ' AND i.itemid=id1.itemid' . ' AND i.flags=' . ZBX_FLAG_DISCOVERY_CREATED); while ($rule = DBfetch($dbRules)) { $relationMap->addRelation($rule['itemid'], $rule['parent_itemid']); } // item prototypes // TODO: this should not be in the item API $dbRules = DBselect('SELECT id.parent_itemid,id.itemid' . ' FROM item_discovery id,items i' . ' WHERE ' . dbConditionInt('id.itemid', $itemids) . ' AND i.itemid=id.itemid' . ' AND i.flags=' . ZBX_FLAG_DISCOVERY_PROTOTYPE); while ($rule = DBfetch($dbRules)) { $relationMap->addRelation($rule['itemid'], $rule['parent_itemid']); } $discoveryRules = API::DiscoveryRule()->get(array('output' => $options['selectDiscoveryRule'], 'itemids' => $relationMap->getRelatedIds(), 'nopermissions' => true, 'preservekeys' => true)); $result = $relationMap->mapOne($result, $discoveryRules, 'discoveryRule'); } // adding item discovery if ($options['selectItemDiscovery'] !== null) { $itemDiscoveries = API::getApiService()->select('item_discovery', array('output' => $this->outputExtend($options['selectItemDiscovery'], array('itemdiscoveryid', 'itemid')), 'filter' => array('itemid' => array_keys($result)), 'preservekeys' => true)); $relationMap = $this->createRelationMap($itemDiscoveries, 'itemid', 'itemdiscoveryid'); $itemDiscoveries = $this->unsetExtraFields($itemDiscoveries, array('itemid', 'itemdiscoveryid'), $options['selectItemDiscovery']); $result = $relationMap->mapOne($result, $itemDiscoveries, 'itemDiscovery'); } // adding history data $requestedOutput = array(); if ($this->outputIsRequested('lastclock', $options['output'])) { $requestedOutput['lastclock'] = true; } if ($this->outputIsRequested('lastns', $options['output'])) { $requestedOutput['lastns'] = true; } if ($this->outputIsRequested('lastvalue', $options['output'])) { $requestedOutput['lastvalue'] = true; } if ($this->outputIsRequested('prevvalue', $options['output'])) { $requestedOutput['prevvalue'] = true; } if ($requestedOutput) { $history = Manager::History()->getLast($result, 2, ZBX_HISTORY_PERIOD); foreach ($result as &$item) { $lastHistory = isset($history[$item['itemid']][0]) ? $history[$item['itemid']][0] : null; $prevHistory = isset($history[$item['itemid']][1]) ? $history[$item['itemid']][1] : null; if (isset($requestedOutput['lastclock'])) { $item['lastclock'] = $lastHistory ? $lastHistory['clock'] : '0'; } if (isset($requestedOutput['lastns'])) { $item['lastns'] = $lastHistory ? $lastHistory['ns'] : '0'; } if (isset($requestedOutput['lastvalue'])) { $item['lastvalue'] = $lastHistory ? $lastHistory['value'] : '0'; } if (isset($requestedOutput['prevvalue'])) { $item['prevvalue'] = $prevHistory ? $prevHistory['value'] : '0'; } } unset($item); } return $result; }
$httpTest['error'] = ''; // fetch http test execution data $httpTestData = Manager::HttpTest()->getLastData(array($httpTest['httptestid'])); if ($httpTestData) { $httpTestData = reset($httpTestData); } // fetch HTTP step items $query = DBselect('SELECT i.value_type,i.valuemapid,i.units,i.itemid,hi.type AS httpitem_type,hs.httpstepid' . ' FROM items i,httpstepitem hi,httpstep hs' . ' WHERE hi.itemid=i.itemid' . ' AND hi.httpstepid=hs.httpstepid' . ' AND hs.httptestid=' . zbx_dbstr($httpTest['httptestid'])); $httpStepItems = array(); $items = array(); while ($item = DBfetch($query)) { $items[] = $item; $httpStepItems[$item['httpstepid']][$item['httpitem_type']] = $item; } // fetch HTTP item history $itemHistory = Manager::History()->getLast($items); /* * Display */ $httpdetailsWidget = new CWidget(); $httpdetailsWidget->addPageHeader(array(_('DETAILS OF SCENARIO'), SPACE, bold(CMacrosResolverHelper::resolveHttpTestName($httpTest['hostid'], $httpTest['name'])), isset($httpTestData['lastcheck']) ? ' [' . zbx_date2str(_('d M Y H:i:s'), $httpTestData['lastcheck']) . ']' : null), array(get_icon('reset', array('id' => get_request('httptestid'))), get_icon('fullscreen', array('fullscreen' => $_REQUEST['fullscreen'])))); // append table to widget $httpdetailsTable = new CTableInfo(); $httpdetailsTable->setHeader(array(_('Step'), _('Speed'), _('Response time'), _('Response code'), _('Status'))); $db_httpsteps = DBselect('SELECT * FROM httpstep WHERE httptestid=' . zbx_dbstr($httpTest['httptestid']) . ' ORDER BY no'); $totalTime = array('value' => 0, 'value_type' => null, 'valuemapid' => null, 'units' => null); $itemIds = array(); while ($httpstep_data = DBfetch($db_httpsteps)) { $httpStepItemsByType = $httpStepItems[$httpstep_data['httpstepid']]; $status['msg'] = _('OK'); $status['style'] = 'enabled';
/** * Retrieve overview table object for items. * * @param array $hostIds * @param string $application name of application to filter * @param int $viewMode * * @return CTableInfo */ function getItemsDataOverview($hostIds, $application, $viewMode) { $sqlFrom = ''; $sqlWhere = ''; if ($application !== '') { $sqlFrom = 'applications a,items_applications ia,'; $sqlWhere = ' AND i.itemid=ia.itemid AND a.applicationid=ia.applicationid AND a.name=' . zbx_dbstr($application); } $dbItems = DBfetchArray(DBselect('SELECT DISTINCT h.hostid,h.name AS hostname,i.itemid,i.key_,i.value_type,i.units,' . 'i.name,t.priority,i.valuemapid,t.value AS tr_value,t.triggerid' . ' FROM hosts h,' . $sqlFrom . 'items i' . ' LEFT JOIN functions f ON f.itemid=i.itemid' . ' LEFT JOIN triggers t ON t.triggerid=f.triggerid AND t.status=' . TRIGGER_STATUS_ENABLED . ' WHERE ' . dbConditionInt('h.hostid', $hostIds) . ' AND h.status=' . HOST_STATUS_MONITORED . ' AND h.hostid=i.hostid' . ' AND i.status=' . ITEM_STATUS_ACTIVE . ' AND ' . dbConditionInt('i.flags', array(ZBX_FLAG_DISCOVERY_NORMAL, ZBX_FLAG_DISCOVERY_CREATED)) . $sqlWhere)); $dbItems = CMacrosResolverHelper::resolveItemNames($dbItems); CArrayHelper::sort($dbItems, array(array('field' => 'name_expanded', 'order' => ZBX_SORT_UP), array('field' => 'itemid', 'order' => ZBX_SORT_UP))); // fetch latest values $history = Manager::History()->getLast(zbx_toHash($dbItems, 'itemid'), 1, ZBX_HISTORY_PERIOD); // fetch data for the host JS menu $hosts = API::Host()->get(array('output' => array('name', 'hostid', 'status'), 'monitored_hosts' => true, 'hostids' => $hostIds, 'with_monitored_items' => true, 'preservekeys' => true, 'selectScreens' => $viewMode == STYLE_LEFT ? API_OUTPUT_COUNT : null)); $items = array(); foreach ($dbItems as $dbItem) { $name = $dbItem['name_expanded']; $dbItem['hostname'] = get_node_name_by_elid($dbItem['hostid'], null, NAME_DELIMITER) . $dbItem['hostname']; $hostNames[$dbItem['hostid']] = $dbItem['hostname']; // a little tricky check for attempt to overwrite active trigger (value=1) with // inactive or active trigger with lower priority. if (!isset($items[$name][$dbItem['hostname']]) || ($items[$name][$dbItem['hostname']]['tr_value'] == TRIGGER_VALUE_FALSE && $dbItem['tr_value'] == TRIGGER_VALUE_TRUE || ($items[$name][$dbItem['hostname']]['tr_value'] == TRIGGER_VALUE_FALSE || $dbItem['tr_value'] == TRIGGER_VALUE_TRUE) && $dbItem['priority'] > $items[$name][$dbItem['hostname']]['severity'])) { $items[$name][$dbItem['hostname']] = array('itemid' => $dbItem['itemid'], 'value_type' => $dbItem['value_type'], 'value' => isset($history[$dbItem['itemid']]) ? $history[$dbItem['itemid']][0]['value'] : null, 'units' => $dbItem['units'], 'name' => $name, 'valuemapid' => $dbItem['valuemapid'], 'severity' => $dbItem['priority'], 'tr_value' => $dbItem['tr_value'], 'triggerid' => $dbItem['triggerid']); } } $table = new CTableInfo(_('No items found.')); if (empty($hostNames)) { return $table; } $table->makeVerticalRotation(); order_result($hostNames); if ($viewMode == STYLE_TOP) { $header = array(new CCol(_('Items'), 'center')); foreach ($hostNames as $hostName) { $header[] = new CCol($hostName, 'vertical_rotation'); } $table->setHeader($header, 'vertical_header'); foreach ($items as $descr => $ithosts) { $tableRow = array(nbsp($descr)); foreach ($hostNames as $hostName) { $tableRow = getItemDataOverviewCells($tableRow, $ithosts, $hostName); } $table->addRow($tableRow); } } else { $scripts = API::Script()->getScriptsByHosts(zbx_objectValues($hosts, 'hostid')); $header = array(new CCol(_('Hosts'), 'center')); foreach ($items as $descr => $ithosts) { $header[] = new CCol($descr, 'vertical_rotation'); } $table->setHeader($header, 'vertical_header'); foreach ($hostNames as $hostId => $hostName) { $host = $hosts[$hostId]; $name = new CSpan($host['name'], 'link_menu'); $name->setMenuPopup(getMenuPopupHost($host, $scripts[$hostId])); $tableRow = array(new CCol($name)); foreach ($items as $ithosts) { $tableRow = getItemDataOverviewCells($tableRow, $ithosts, $hostName); } $table->addRow($tableRow); } } return $table; }
// macros $items = CMacrosResolverHelper::resolveItemKeys($items); $items = CMacrosResolverHelper::resolveItemNames($items); // filter items by name foreach ($items as $key => $item) { if ($filter['select'] !== '') { $haystack = mb_strtolower($item['name_expanded']); $needle = mb_strtolower($filter['select']); if (mb_strpos($haystack, $needle) === false) { unset($items[$key]); } } } if ($items) { // get history $history = Manager::History()->getLast($items, 2, ZBX_HISTORY_PERIOD); // filter items without history if (!$filter['showWithoutData']) { foreach ($items as $key => $item) { if (!isset($history[$item['itemid']])) { unset($items[$key]); } } } } if ($items) { // add item last update date for sorting foreach ($items as &$item) { if (isset($history[$item['itemid']])) { $item['lastclock'] = $history[$item['itemid']][0]['clock']; }
protected function calculateMaxY($side) { if ($this->ymax_type == GRAPH_YAXIS_TYPE_FIXED) { return $this->yaxismax; } if ($this->ymax_type == GRAPH_YAXIS_TYPE_ITEM_VALUE) { $item = get_item_by_itemid($this->ymax_itemid); $history = Manager::History()->getLast(array($item)); if (isset($history[$item['itemid']])) { return $history[$item['itemid']][0]['value']; } } $maxY = null; for ($i = 0; $i < $this->num; $i++) { if ($this->items[$i]['axisside'] != $side) { continue; } if (!isset($this->data[$this->items[$i]['itemid']][GRAPH_ITEM_SIMPLE])) { continue; } $data =& $this->data[$this->items[$i]['itemid']][GRAPH_ITEM_SIMPLE]; if (!isset($data)) { continue; } $calc_fnc = $this->items[$i]['calc_fnc']; switch ($calc_fnc) { case CALC_FNC_ALL: case CALC_FNC_MAX: $val = $data['max']; $shift_val = $data['shift_max']; break; case CALC_FNC_MIN: $val = $data['min']; $shift_val = $data['shift_min']; break; case CALC_FNC_AVG: default: $val = $data['avg']; $shift_val = $data['shift_avg']; } if (!isset($val)) { continue; } for ($ci = 0; $ci < min(count($val), count($shift_val)); $ci++) { if ($data['count'][$ci] == 0) { continue; } $val[$ci] = bcadd($shift_val[$ci], $val[$ci]); } if (!isset($maxY)) { if (isset($val) && count($val) > 0) { $maxY = max($val); } } else { $maxY = max($maxY, max($val)); } } return $maxY; }
/** * Process screen. * * @return CDiv (screen inside container) */ public function get() { $this->dataId = 'httptest_details'; $httptest = API::HttpTest()->get(['output' => ['httptestid', 'name', 'hostid'], 'selectSteps' => ['httpstepid', 'name', 'no'], 'httptestids' => $this->profileIdx2, 'preservekeys' => true]); $httptest = reset($httptest); if (!$httptest) { $messages = [['type' => 'error', 'message' => _('No permissions to referred object or it does not exist!')]]; return $this->getOutput(makeMessageBox(false, $messages, null, false, false)); } $httptest['lastfailedstep'] = 0; $httptest['error'] = ''; // fetch http test execution data $httptest_data = Manager::HttpTest()->getLastData([$httptest['httptestid']]); if ($httptest_data) { $httptest_data = reset($httptest_data); } // fetch HTTP step items $items = DBfetchArray(DBselect('SELECT i.value_type,i.valuemapid,i.units,i.itemid,hi.type,hs.httpstepid' . ' FROM items i,httpstepitem hi,httpstep hs' . ' WHERE hi.itemid=i.itemid' . ' AND hi.httpstepid=hs.httpstepid' . ' AND hs.httptestid=' . zbx_dbstr($httptest['httptestid']))); $step_items = []; foreach ($items as $item) { $step_items[$item['httpstepid']][$item['type']] = $item; } // fetch HTTP item history $item_history = Manager::History()->getLast($items); $table = (new CTableInfo())->setHeader([_('Step'), _('Speed'), _('Response time'), _('Response code'), _('Status')]); $total_time = ['value' => 0, 'value_type' => null, 'valuemapid' => null, 'units' => null]; order_result($httptest['steps'], 'no'); foreach ($httptest['steps'] as $step_data) { $items_by_type = $step_items[$step_data['httpstepid']]; $status['msg'] = _('OK'); $status['style'] = ZBX_STYLE_GREEN; $status['afterError'] = false; if (!array_key_exists('lastfailedstep', $httptest_data)) { $status['msg'] = _('Never executed'); $status['style'] = ZBX_STYLE_GREY; } elseif ($httptest_data['lastfailedstep'] != 0) { if ($httptest_data['lastfailedstep'] == $step_data['no']) { $status['msg'] = $httptest_data['error'] === null ? _('Unknown error') : _s('Error: %1$s', $httptest_data['error']); $status['style'] = ZBX_STYLE_RED; } elseif ($httptest_data['lastfailedstep'] < $step_data['no']) { $status['msg'] = _('Unknown'); $status['style'] = ZBX_STYLE_GREY; $status['afterError'] = true; } } foreach ($items_by_type as &$item) { // Calculate the total time it took to execute the scenario. // Skip steps that come after a failed step. if (!$status['afterError'] && $item['type'] == HTTPSTEP_ITEM_TYPE_TIME) { $total_time['value_type'] = $item['value_type']; $total_time['valuemapid'] = $item['valuemapid']; $total_time['units'] = $item['units']; if (array_key_exists($item['itemid'], $item_history)) { $history = $item_history[$item['itemid']][0]; $total_time['value'] += $history['value']; } } } unset($item); // step speed $speed_item = $items_by_type[HTTPSTEP_ITEM_TYPE_IN]; if (!$status['afterError'] && array_key_exists($speed_item['itemid'], $item_history) && $item_history[$speed_item['itemid']][0]['value'] > 0) { $speed = formatHistoryValue($item_history[$speed_item['itemid']][0]['value'], $speed_item); } else { $speed = UNKNOWN_VALUE; } // step response time $resptime_item = $items_by_type[HTTPSTEP_ITEM_TYPE_TIME]; if (!$status['afterError'] && array_key_exists($resptime_item['itemid'], $item_history) && $item_history[$resptime_item['itemid']][0]['value'] > 0) { $resp_time = formatHistoryValue($item_history[$resptime_item['itemid']][0]['value'], $resptime_item); } else { $resp_time = UNKNOWN_VALUE; } // step response code $resp_item = $items_by_type[HTTPSTEP_ITEM_TYPE_RSPCODE]; if (!$status['afterError'] && array_key_exists($resp_item['itemid'], $item_history) && $item_history[$resp_item['itemid']][0]['value'] > 0) { $resp = formatHistoryValue($item_history[$resp_item['itemid']][0]['value'], $resp_item); } else { $resp = UNKNOWN_VALUE; } $table->addRow([CMacrosResolverHelper::resolveHttpTestName($httptest['hostid'], $step_data['name']), $speed, $resp_time, $resp, (new CSpan($status['msg']))->addClass($status['style'])]); } if (!array_key_exists('lastfailedstep', $httptest_data)) { $status['msg'] = _('Never executed'); $status['style'] = ZBX_STYLE_GREY; } elseif ($httptest_data['lastfailedstep'] != 0) { $status['msg'] = $httptest_data['error'] === null ? _('Unknown error') : _s('Error: %1$s', $httptest_data['error']); $status['style'] = ZBX_STYLE_RED; } else { $status['msg'] = _('OK'); $status['style'] = ZBX_STYLE_GREEN; } $table->addRow([bold(_('TOTAL')), '', bold($total_time['value'] ? formatHistoryValue($total_time['value'], $total_time) : UNKNOWN_VALUE), '', (new CSpan($status['msg']))->addClass($status['style'])]); return $this->getOutput($table); }
/** * Returns the data about the last execution of the given HTTP tests. * * The following values will be returned for each executed HTTP test: * - lastcheck - time when the test has been executed last * - lastfailedstep - number of the last failed step * - error - error message * * If a HTTP test has never been executed, no value will be returned. * * @param array $httpTestIds * * @return array an array with HTTP test IDs as keys and arrays of data as values */ public function getLastData(array $httpTestIds) { $httpItems = DBfetchArray(DBselect('SELECT hti.httptestid,hti.type,i.itemid,i.value_type' . ' FROM httptestitem hti,items i' . ' WHERE hti.itemid=i.itemid' . ' AND hti.type IN (' . HTTPSTEP_ITEM_TYPE_LASTSTEP . ',' . HTTPSTEP_ITEM_TYPE_LASTERROR . ')' . ' AND ' . dbConditionInt('hti.httptestid', $httpTestIds))); $history = Manager::History()->getLast($httpItems); $data = array(); foreach ($httpItems as $httpItem) { if (isset($history[$httpItem['itemid']])) { $itemHistory = $history[$httpItem['itemid']][0]; if ($httpItem['type'] == HTTPSTEP_ITEM_TYPE_LASTSTEP) { $data[$httpItem['httptestid']]['lastcheck'] = $itemHistory['clock']; $data[$httpItem['httptestid']]['lastfailedstep'] = $itemHistory['value']; } else { $data[$httpItem['httptestid']]['error'] = $itemHistory['value']; } } } return $data; }
/** * Get item macros. * * @param array $macros * @param array $triggers * @param array $macroValues * * @return array */ protected function getItemMacros(array $macros, array $triggers, array $macroValues) { if ($macros) { $functions = DbFetchArray(DBselect('SELECT f.triggerid,f.functionid,i.itemid,i.value_type,i.units,i.valuemapid' . ' FROM functions f' . ' JOIN items i ON f.itemid=i.itemid' . ' JOIN hosts h ON i.hostid=h.hostid' . ' WHERE ' . dbConditionInt('f.functionid', array_keys($macros)))); $history = Manager::History()->getLast($functions, 1, ZBX_HISTORY_PERIOD); // false passed to DBfetch to get data without null converted to 0, which is done by default foreach ($functions as $func) { foreach ($macros[$func['functionid']] as $macro => $fNums) { $lastValue = isset($history[$func['itemid']]) ? $history[$func['itemid']][0]['value'] : null; switch ($macro) { case 'ITEM.LASTVALUE': $replace = $this->getItemLastValueMacro($lastValue, $func); break; case 'ITEM.VALUE': $replace = $this->getItemValueMacro($lastValue, $func, $triggers[$func['triggerid']]); break; } $macroValues = $this->getFunctionMacroValues($macroValues, $fNums, $func['triggerid'], $macro, $replace); } } } return $macroValues; }
/** * Process screen. * * @return CDiv (screen inside container) */ public function get() { $time = null; $title = null; $time_zone_string = null; $time_zone_offset = null; $error = null; switch ($this->screenitem['style']) { case TIME_TYPE_HOST: $itemid = $this->screenitem['resourceid']; if (!empty($this->hostid)) { $new_itemid = get_same_item_for_host($itemid, $this->hostid); $itemid = !empty($new_itemid) ? $new_itemid : ''; } $items = API::Item()->get(['output' => ['itemid', 'value_type'], 'selectHosts' => ['name'], 'itemids' => [$itemid]]); if ($items) { $item = $items[0]; $title = $item['hosts'][0]['name']; unset($items, $item['hosts']); $last_value = Manager::History()->getLast([$item]); if ($last_value) { $last_value = $last_value[$item['itemid']][0]; try { $now = new DateTime($last_value['value']); $time_zone_string = 'GMT' . $now->format('P'); $time_zone_offset = $now->format('Z'); $time = time() - ($last_value['clock'] - $now->getTimestamp()); } catch (Exception $e) { $error = _('No data'); } } else { $error = _('No data'); } } else { $error = _('No data'); } break; case TIME_TYPE_SERVER: $title = _('Server'); $now = new DateTime(); $time = $now->getTimestamp(); $time_zone_string = 'GMT' . $now->format('P'); $time_zone_offset = $now->format('Z'); break; default: $title = _('Local'); break; } if ($this->screenitem['width'] > $this->screenitem['height']) { $this->screenitem['width'] = $this->screenitem['height']; } $item = (new CClock())->setWidth($this->screenitem['width'])->setHeight($this->screenitem['height'])->setTimeZoneString($time_zone_string)->setFooter($title); if ($error !== null) { $item->setError($error); } if ($time !== null) { $item->setTime($time); } if ($time_zone_offset !== null) { $item->setTimeZoneOffset($time_zone_offset); } return $this->getOutput($item); }
/** * Resolve functional macros, like {hostname:key.function(param)}. * If macro can not be resolved it is replaced with UNRESOLVED_MACRO_STRING string i.e. "*UNKNOWN*" * Supports function "last", "min", "max" and "avg". * Supports seconds as parameters, except "last" function. * Supports postfixes s,m,h,d and w for parameter. * * @param array $strList list of string in which macros should be resolved * @param array $itemsList list of lists of graph items * @param int $items[n][m]['hostid'] n-th graph m-th item corresponding host Id * @param string $items[n][m]['host'] n-th graph m-th item corresponding host name * * @return array list of strings with macros replaced with corresponding values */ private function resolveGraphsFunctionalItemMacros($strList, $itemsList) { // retrieve all string macros and all host-key pairs $hostKeyPairs = array(); $matchesList = array(); $items = reset($itemsList); foreach ($strList as $str) { // extract all macros into $matches - keys: macros, hosts, keys, functions and parameters are used // searches for macros, for example, "{somehost:somekey["param[123]"].min(10m)}" preg_match_all('/(?<macros>{' . '(?<hosts>(' . ZBX_PREG_HOST_FORMAT . '|({(' . self::PATTERN_HOST_INTERNAL . ')' . self::PATTERN_MACRO_PARAM . '}))):' . '(?<keys>' . ZBX_PREG_ITEM_KEY_FORMAT . ')\\.' . '(?<functions>(last|max|min|avg))\\(' . '(?<parameters>([0-9]+[smhdw]?))' . '\\)}{1})/Uux', $str, $matches, PREG_OFFSET_CAPTURE); if (!empty($matches['hosts'])) { foreach ($matches['hosts'] as $i => $host) { $matches['hosts'][$i][0] = $this->resolveGraphPositionalMacros($host[0], $items); if ($matches['hosts'][$i][0] !== UNRESOLVED_MACRO_STRING) { if (!isset($hostKeyPairs[$matches['hosts'][$i][0]])) { $hostKeyPairs[$matches['hosts'][$i][0]] = array(); } $hostKeyPairs[$matches['hosts'][$i][0]][$matches['keys'][$i][0]] = 1; } } $matchesList[] = $matches; $items = next($itemsList); } } // stop, if no macros found if (empty($matchesList)) { return $strList; } // build item retrieval query from host-key pairs $query = 'SELECT h.host,i.key_,i.itemid,i.value_type,i.units,i.valuemapid' . ' FROM items i, hosts h' . ' WHERE i.hostid=h.hostid AND ('; foreach ($hostKeyPairs as $host => $keys) { $query .= '(h.host=' . zbx_dbstr($host) . ' AND i.key_ IN('; foreach ($keys as $key => $val) { $query .= zbx_dbstr($key) . ','; } $query = substr($query, 0, -1) . ')) OR '; } $query = substr($query, 0, -4) . ')'; // get necessary items for all graph strings $items = DBfetchArrayAssoc(DBselect($query), 'itemid'); $allowedItems = API::Item()->get(array('itemids' => array_keys($items), 'webitems' => true, 'output' => array('itemid', 'value_type'), 'preservekeys' => true)); // map item data only for allowed items foreach ($items as $item) { if (isset($allowedItems[$item['itemid']])) { $hostKeyPairs[$item['host']][$item['key_']] = $item; } } // fetch history $history = Manager::History()->getLast($items); // replace macros with their corresponding values in graph strings $matches = reset($matchesList); foreach ($strList as &$str) { // iterate array backwards! $i = count($matches['macros']); while ($i--) { // host is real and item exists and has permissions if ($matches['hosts'][$i][0] !== UNRESOLVED_MACRO_STRING && is_array($hostKeyPairs[$matches['hosts'][$i][0]][$matches['keys'][$i][0]])) { $item = $hostKeyPairs[$matches['hosts'][$i][0]][$matches['keys'][$i][0]]; // macro function is "last" if ($matches['functions'][$i][0] == 'last') { $value = isset($history[$item['itemid']]) ? formatHistoryValue($history[$item['itemid']][0]['value'], $item) : UNRESOLVED_MACRO_STRING; } else { $value = getItemFunctionalValue($item, $matches['functions'][$i][0], $matches['parameters'][$i][0]); } } else { $value = UNRESOLVED_MACRO_STRING; } $str = substr_replace($str, $value, $matches['macros'][$i][1], strlen($matches['macros'][$i][0])); } $matches = next($matchesList); } unset($str); return $strList; }
/** * Retrieve overview table object for items. * * @param array $hostIds * @param array|null $applicationIds IDs of applications to filter items by * @param int $viewMode * * @return CTableInfo */ function getItemsDataOverview($hostIds, array $applicationIds = null, $viewMode) { $sqlFrom = ''; $sqlWhere = ''; if ($applicationIds !== null) { $sqlFrom = 'items_applications ia,'; $sqlWhere = ' AND i.itemid=ia.itemid AND ' . dbConditionInt('ia.applicationid', $applicationIds); } $dbItems = DBfetchArray(DBselect('SELECT DISTINCT h.hostid,h.name AS hostname,i.itemid,i.key_,i.value_type,i.units,' . 'i.name,t.priority,i.valuemapid,t.value AS tr_value,t.triggerid' . ' FROM hosts h,' . $sqlFrom . 'items i' . ' LEFT JOIN functions f ON f.itemid=i.itemid' . ' LEFT JOIN triggers t ON t.triggerid=f.triggerid AND t.status=' . TRIGGER_STATUS_ENABLED . ' WHERE ' . dbConditionInt('h.hostid', $hostIds) . ' AND h.status=' . HOST_STATUS_MONITORED . ' AND h.hostid=i.hostid' . ' AND i.status=' . ITEM_STATUS_ACTIVE . ' AND ' . dbConditionInt('i.flags', [ZBX_FLAG_DISCOVERY_NORMAL, ZBX_FLAG_DISCOVERY_CREATED]) . $sqlWhere)); $dbItems = CMacrosResolverHelper::resolveItemNames($dbItems); CArrayHelper::sort($dbItems, [['field' => 'name_expanded', 'order' => ZBX_SORT_UP], ['field' => 'itemid', 'order' => ZBX_SORT_UP]]); // fetch latest values $history = Manager::History()->getLast(zbx_toHash($dbItems, 'itemid'), 1, ZBX_HISTORY_PERIOD); // fetch data for the host JS menu $hosts = API::Host()->get(['output' => ['name', 'hostid', 'status'], 'monitored_hosts' => true, 'hostids' => $hostIds, 'with_monitored_items' => true, 'preservekeys' => true, 'selectGraphs' => API_OUTPUT_COUNT, 'selectScreens' => $viewMode == STYLE_LEFT ? API_OUTPUT_COUNT : null]); $items = []; $item_counter = []; $host_items = []; foreach ($dbItems as $dbItem) { $item_name = $dbItem['name_expanded']; $host_name = $dbItem['hostname']; $hostNames[$dbItem['hostid']] = $host_name; if (!array_key_exists($host_name, $item_counter)) { $item_counter[$host_name] = []; } if (!array_key_exists($item_name, $item_counter[$host_name])) { $item_counter[$host_name][$item_name] = 0; } if (!array_key_exists($item_name, $host_items) || !array_key_exists($host_name, $host_items[$item_name])) { $host_items[$item_name][$host_name] = []; } // a little tricky check for attempt to overwrite active trigger (value=1) with // inactive or active trigger with lower priority. if (!array_key_exists($dbItem['itemid'], $host_items[$item_name][$host_name]) || ($host_items[$item_name][$host_name][$dbItem['itemid']]['tr_value'] == TRIGGER_VALUE_FALSE && $dbItem['tr_value'] == TRIGGER_VALUE_TRUE || ($host_items[$item_name][$host_name][$dbItem['itemid']]['tr_value'] == TRIGGER_VALUE_FALSE || $dbItem['tr_value'] == TRIGGER_VALUE_TRUE) && $dbItem['priority'] > $host_items[$item_name][$host_name][$dbItem['itemid']]['severity'])) { if (array_key_exists($dbItem['itemid'], $host_items[$item_name][$host_name])) { $item_place = $host_items[$item_name][$host_name][$dbItem['itemid']]['item_place']; } else { $item_place = $item_counter[$host_name][$item_name]; $item_counter[$host_name][$item_name]++; } $items[$item_name][$item_place][$host_name] = ['itemid' => $dbItem['itemid'], 'value_type' => $dbItem['value_type'], 'value' => isset($history[$dbItem['itemid']]) ? $history[$dbItem['itemid']][0]['value'] : null, 'units' => $dbItem['units'], 'valuemapid' => $dbItem['valuemapid'], 'severity' => $dbItem['priority'], 'tr_value' => $dbItem['tr_value'], 'triggerid' => $dbItem['triggerid'], 'item_place' => $item_place]; $host_items[$item_name][$host_name][$dbItem['itemid']] = $items[$item_name][$item_place][$host_name]; } } $table = new CTableInfo(); if (empty($hostNames)) { return $table; } $table->makeVerticalRotation(); order_result($hostNames); if ($viewMode == STYLE_TOP) { $header = [_('Items')]; foreach ($hostNames as $hostName) { $header[] = (new CColHeader($hostName))->addClass('vertical_rotation'); } $table->setHeader($header); foreach ($items as $item_name => $item_data) { foreach ($item_data as $ithosts) { $tableRow = [nbsp($item_name)]; foreach ($hostNames as $hostName) { $tableRow = getItemDataOverviewCells($tableRow, $ithosts, $hostName); } $table->addRow($tableRow); } } } else { $scripts = API::Script()->getScriptsByHosts(zbx_objectValues($hosts, 'hostid')); $header = [_('Hosts')]; foreach ($items as $item_name => $item_data) { foreach ($item_data as $ithosts) { $header[] = (new CColHeader($item_name))->addClass('vertical_rotation'); } } $table->setHeader($header); foreach ($hostNames as $hostId => $hostName) { $host = $hosts[$hostId]; $name = (new CSpan($host['name']))->addClass(ZBX_STYLE_LINK_ACTION)->setMenuPopup(CMenuPopupHelper::getHost($host, $scripts[$hostId])); $tableRow = [(new CCol($name))->addClass(ZBX_STYLE_NOWRAP)]; foreach ($items as $item_data) { foreach ($item_data as $ithosts) { $tableRow = getItemDataOverviewCells($tableRow, $ithosts, $hostName); } } $table->addRow($tableRow); } } return $table; }
// get items if ($hosts) { $items = API::Item()->get(array('hostids' => array_keys($hosts), 'output' => array('itemid', 'name', 'type', 'value_type', 'units', 'hostid', 'state', 'valuemapid', 'status', 'error', 'trends', 'history', 'delay', 'key_', 'flags'), 'selectApplications' => array('applicationid'), 'selectItemDiscovery' => array('ts_delete'), 'webitems' => true, 'filter' => array('status' => array(ITEM_STATUS_ACTIVE)), 'preservekeys' => true)); } if ($items) { // filter items by name foreach ($items as $key => &$item) { $item['resolvedName'] = itemName($item); if (!zbx_empty($filterSelect) && !zbx_stristr($item['resolvedName'], $filterSelect)) { unset($items[$key]); } } unset($item); if ($items) { // get history $history = Manager::History()->getLast($items, 2); // filter items without history if (!$filterShowWithoutData) { foreach ($items as $key => $item) { if (!isset($history[$item['itemid']])) { unset($items[$key]); } } } } if ($items) { $hostIds = array_keys(array_flip(zbx_objectValues($items, 'hostid'))); // add item last update date for sorting foreach ($items as &$item) { if (isset($history[$item['itemid']])) { $item['lastclock'] = $history[$item['itemid']][0]['clock'];