示例#1
0
/**
 * Expand functional macros in given map label.
 *
 * @param string $label label to expand
 * @param array $replaceHosts list of hosts in order which they appear in trigger expression if trigger label is given,
 * or single host when host label is given
 *
 * @return string expanded label
 */
function resolveMapLabelMacros($label, $replaceHosts = null)
{
    // find functional macro pattern
    $pattern = null === $replaceHosts ? '/{' . ZBX_PREG_HOST_FORMAT . ":.+\\.(last|max|min|avg)\\([0-9]+[smhdwKMGT]?\\)}/Uu" : '/{(' . ZBX_PREG_HOST_FORMAT . "|{HOSTNAME[0-9]?}|{HOST\\.HOST[0-9]?}):.+\\.(last|max|min|avg)\\([0-9]+[smhdwKMGT]?\\)}/Uu";
    preg_match_all($pattern, $label, $matches);
    // for each functional macro
    foreach ($matches[0] as $expr) {
        $macro = $expr;
        if ($replaceHosts !== null) {
            // search for macros with all possible indecies
            foreach ($replaceHosts as $i => $host) {
                $macroTmp = $macro;
                // repalce only macro in first position
                $macro = preg_replace('/{({HOSTNAME' . $i . '}|{HOST\\.HOST' . $i . '}):(.*)}/U', '{' . $host['host'] . ':$2}', $macro);
                // only one simple macro possible inside functional macro
                if ($macro != $macroTmp) {
                    break;
                }
            }
        }
        // try to create valid expression
        $expressionData = new CTriggerExpression();
        if (!$expressionData->parse($macro) || !isset($expressionData->expressions[0])) {
            continue;
        }
        // look in DB for coressponding item
        $itemHost = $expressionData->expressions[0]['host'];
        $key = $expressionData->expressions[0]['item'];
        $function = $expressionData->expressions[0]['functionName'];
        $parameter = convertFunctionValue($expressionData->expressions[0]['functionParamList'][0]);
        $item = API::Item()->get(array('webitems' => true, 'filter' => array('host' => $itemHost, 'key_' => $key), 'output' => array('lastclock', 'value_type', 'lastvalue', 'units', 'valuemapid')));
        $item = reset($item);
        // if no corresponding item found with functional macro key and host
        if (!$item) {
            $label = str_replace($expr, '???', $label);
            continue;
        }
        // do function type (last, min, max, avg) related actions
        if (0 == strcmp($function, 'last')) {
            $value = $item['lastclock'] ? formatHistoryValue($item['lastvalue'], $item) : UNRESOLVED_MACRO_STRING;
        } elseif (0 == strcmp($function, 'min') || 0 == strcmp($function, 'max') || 0 == strcmp($function, 'avg')) {
            $value = getItemFunctionalValue($item, $function, $parameter);
        }
        if (isset($value)) {
            $label = str_replace($expr, $value, $label);
        }
    }
    return $label;
}
示例#2
0
 /**
  * Expand functional macros in given map label.
  *
  * @param string $label			label to expand
  * @param array  $replaceHosts	list of hosts in order which they appear in trigger expression if trigger label is given,
  * or single host when host label is given
  *
  * @return string
  */
 public function resolveMapLabelMacros($label, $replaceHosts = null)
 {
     $functionsPattern = '(last|max|min|avg)\\(([0-9]+[' . ZBX_TIME_SUFFIXES . ']?)?\\)';
     // Find functional macro pattern.
     $pattern = $replaceHosts === null ? '/{' . ZBX_PREG_HOST_FORMAT . ':.+\\.' . $functionsPattern . '}/Uu' : '/{(' . ZBX_PREG_HOST_FORMAT . '|{HOSTNAME[0-9]?}|{HOST\\.HOST[0-9]?}):.+\\.' . $functionsPattern . '}/Uu';
     preg_match_all($pattern, $label, $matches);
     // For each functional macro.
     foreach ($matches[0] as $expr) {
         $macro = $expr;
         if ($replaceHosts !== null) {
             // Search for macros with all possible indices.
             foreach ($replaceHosts as $i => $host) {
                 $macroTmp = $macro;
                 // Replace only macro in first position.
                 $macro = preg_replace('/{({HOSTNAME' . $i . '}|{HOST\\.HOST' . $i . '}):(.*)}/U', '{' . $host['host'] . ':$2}', $macro);
                 // Only one simple macro possible inside functional macro.
                 if ($macro !== $macroTmp) {
                     break;
                 }
             }
         }
         // Try to create valid expression.
         $expressionData = new CTriggerExpression();
         if (!$expressionData->parse($macro) || !isset($expressionData->expressions[0])) {
             continue;
         }
         // Look in DB for corresponding item.
         $itemHost = $expressionData->expressions[0]['host'];
         $key = $expressionData->expressions[0]['item'];
         $function = $expressionData->expressions[0]['functionName'];
         $item = API::Item()->get(['output' => ['itemid', 'value_type', 'units', 'valuemapid', 'lastvalue', 'lastclock'], 'webitems' => true, 'filter' => ['host' => $itemHost, 'key_' => $key]]);
         $item = reset($item);
         // If no corresponding item found with functional macro key and host.
         if (!$item) {
             $label = str_replace($expr, UNRESOLVED_MACRO_STRING, $label);
             continue;
         }
         // Do function type (last, min, max, avg) related actions.
         if ($function === 'last') {
             $value = $item['lastclock'] ? formatHistoryValue($item['lastvalue'], $item) : UNRESOLVED_MACRO_STRING;
         } else {
             $value = getItemFunctionalValue($item, $function, $expressionData->expressions[0]['functionParamList'][0]);
         }
         if (isset($value)) {
             $label = str_replace($expr, $value, $label);
         }
     }
     return $label;
 }
示例#3
0
 /**
  * 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;
 }