99)) - display last 99 syslog messages from all device * print_syslogs(array('pagesize' => 10, 'pageno' => 3, 'pagination' => TRUE)) - display 10 syslog messages from page 3 with pagination header * print_syslogs(array('pagesize' => 10, 'device' = 4)) - display last 10 syslog messages for device_id 4 * print_syslogs(array('short' => TRUE)) - show small block with last syslog messages * * @param array $vars * @return null * */ function print_syslogs($vars) { // Short events? (no pagination, small out) $short = (isset($vars['short']) && $vars['short']); // With pagination? (display page numbers in header) $pagination = (isset($vars['pagination']) && $vars['pagination']); pagination($vars, 0, TRUE); // Get default pagesize/pageno $pageno = $vars['pageno']; $pagesize = $vars['pagesize']; $start = $pagesize * $pageno - $pagesize; $device_single = FALSE; // Show syslog entries for single device or multiple (use approximate counts for multiple) $param = array(); $where = ' WHERE 1 '; foreach ($vars as $var => $value) { if ($value != '') { $cond = array(); switch ($var) { case 'device': case 'device_id': $device_single = is_numeric($value); $where .= generate_query_values($value, 'device_id'); break; case 'priority': $value = get_var_csv($value); foreach ($value as $k => $v) { // Rewrite priority strings to numbers $value[$k] = priority_string_to_numeric($v); } $where .= generate_query_values($value, $var); break; case 'tag': case 'program': $condition = str_contains($value, '*') ? 'LIKE' : '='; $value = get_var_csv($value); $where .= generate_query_values($value, $var, $condition); break; case 'message': if (preg_match('/^!(=)?\s*(?.+)/', $value, $matches)) { $where .= generate_query_values($matches['msg'], 'msg', '%!=LIKE%'); } else { $where .= generate_query_values($value, 'msg', '%LIKE%'); } break; case 'timestamp_from': $where .= ' AND `timestamp` > ?'; $param[] = $value; break; case 'timestamp_to': $where .= ' AND `timestamp` < ?'; $param[] = $value; break; } } } // Show entries only for permitted devices $query_permitted = generate_query_permitted(); /* // Convert NOT IN to IN for correctly use indexes $devices_permitted = dbFetchColumn('SELECT DISTINCT `device_id` FROM `syslog` WHERE 1 '.$query_permitted, NULL, TRUE); $query_permitted = generate_query_values($devices_permitted, 'device_id'); //r($devices_permitted); */ $query = 'FROM `syslog` '; $query .= $where . $query_permitted; $query_count = 'SELECT COUNT(*) ' . $query; $query_count_approx = 'EXPLAIN SELECT * ' . $query; // Fast approximate count $query = 'SELECT * ' . $query; $query .= ' ORDER BY `seq` DESC '; $query .= "LIMIT $start,$pagesize"; // Query syslog messages $entries = dbFetchRows($query, $param); // Query syslog count if ($pagination && !$short) { dbSetVariable('MAX_EXECUTION_TIME', 500); // Set 0.5 sec maximum query execution time // Exactly count, but it's very SLOW on huge tables $count = dbFetchCell($query_count, $param); dbSetVariable('MAX_EXECUTION_TIME', 0); // Reset maximum query execution time //r($count); if (!is_numeric($count)) { // Approximate count correctly around 100-80% dbQuery('ANALYZE TABLE `syslog`;'); // Update INFORMATION_SCHEMA for more correctly count $tmp = dbFetchRow($query_count_approx, $param); $count = $tmp['rows']; } } else { $count = safe_count($entries); } if (!$count) { // There have been no entries returned. Print the warning. print_warning('

No syslog entries found!

Check that the syslog daemon and Observium configuration options are set correctly, that your devices are configured to send syslog to Observium and that there are no firewalls blocking the messages. See Syslog Integration guide and configuration options for more information.'); } else { // Entries have been returned. Print the table. $list = array('device' => FALSE, 'priority' => TRUE); // For now (temporarily) priority always displayed if (!isset($vars['device']) || empty($vars['device']) || $vars['page'] === 'syslog') { $list['device'] = TRUE; } if ($short || !isset($vars['priority']) || empty($vars['priority'])) { $list['priority'] = TRUE; } $string = generate_box_open($vars['header']); if((isset($vars['short']) && $vars['short'])) { $string .= '' . PHP_EOL; } else { $string .= '
' . PHP_EOL; } // Generate table header if (!$short) { $cols = []; $cols[] = [ NULL, 'class="state-marker"' ]; //$cols[] = [ NULL, 'class="no-width"' ]; // Measured entity link $cols[] = [ 'Date' ]; if ($list['device']) { //$cols['device'] = [ 'Device' ]; $cols[] = [ 'Device' ]; } if ($list['priority']) { //$cols['priority'] = [ 'Priority' ]; $cols[] = [ 'Priority' ]; } $cols[] = [ '[Program] [Tags] Message' ]; $string .= get_table_header($cols, $vars); } // Table body $string .= ' ' . PHP_EOL; foreach ($entries as $entry) { $string .= generate_syslog_row($entry, $vars, $list); } //print_vars($GLOBALS['cache']['syslog']); $string .= ' ' . PHP_EOL; $string .= '
' . PHP_EOL; $string .= generate_box_close(); // Print pagination header if ($pagination && !$short) { $string = pagination($vars, $count) . $string . pagination($vars, $count); } // Print syslog echo $string; } } function generate_syslog_row($entry, $vars, $list = NULL) { // Short events? (no pagination, small out) $short = (isset($vars['short']) && $vars['short']); $priorities = $GLOBALS['config']['syslog']['priorities']; $is_alert = isset($entry['la_id']); // This is syslog alert entry? // List of displayed columns if (is_null($list)) { $list = [ 'device' => FALSE, 'priority' => TRUE ]; // For now (temporarily) priority always displayed if (!isset($vars['device']) || empty($vars['device']) || $vars['page'] == 'syslog') { $list['device'] = TRUE; } if ($short || !isset($vars['priority']) || empty($vars['priority'])) { $list['priority'] = TRUE; } } $row_class = strlen($entry['html_row_class']) ? $entry['html_row_class'] : $priorities[$entry['priority']]['row-class']; $string = ' ' . PHP_EOL; $string .= '' . PHP_EOL; $timediff = $GLOBALS['config']['time']['now'] - strtotime($entry['timestamp']); if ($short || $timediff < 3600) { $string .= ' '; $timediff = $GLOBALS['config']['time']['now'] - strtotime($entry['timestamp']); $string .= generate_tooltip_link('', format_uptime($timediff, "short-3"), format_timestamp($entry['timestamp']), NULL) . '' . PHP_EOL; } else { //$string .= ' '; $string .= ' '; $string .= format_timestamp($entry['timestamp']) . '' . PHP_EOL; } // Device column if ($list['device']) { $dev = device_by_id_cache($entry['device_id']); $device_vars = array('page' => 'device', 'device' => $entry['device_id'], 'tab' => 'logs', 'section' => 'syslog'); if ($is_alert) { $device_vars['section'] = 'logalert'; } $string .= ' ' . generate_device_link_short($dev, $device_vars) . '' . PHP_EOL; } // Alert Rule column (in syslog alerts) if ($list['la_id']) { $syslog_rules = $GLOBALS['cache']['syslog']['syslog_rules']; // Cached syslog rules $string .= '' . (is_array($syslog_rules[$entry['la_id']]) ? $syslog_rules[$entry['la_id']]['la_name'] : 'Rule Deleted') . '' . PHP_EOL; } // Priority column if ($list['priority']) { if (!$short) { $string .= ' ' . nicecase($priorities[$entry['priority']]['name']) . ' (' . $entry['priority'] . ')' . PHP_EOL; } } // Program and Tags column $entry['program'] = (empty($entry['program'])) ? '[[EMPTY]]' : $entry['program']; if ($short) { $string .= ' '; $string .= '' . escape_html($entry['program']) . ''; } else { $string .= ' '; $string .= '' . escape_html($entry['program']) . ''; /* Show tags if not short */ $tags = array(); foreach(explode(',', $entry['tag']) as $tag) { if (!str_istarts($tag, $entry['program']) && !preg_match('/^(\d+\:|[\da-f]{2})$/i', $tag) && !preg_match('/^<(Emer|Aler|Crit|Err|Warn|Noti|Info|Debu)/i', $tag)) // Skip tags same as program or old numeric tags or syslog-ng 2x hex numbers { $tags[] = escape_html($tag); } } if ($tags) { $string .= ''; $string .= implode('', $tags); $string .= ''; } /* End tags */ } if ($list['program']) { // Program in separate column (from message) $string .= $short ? '' : ''; } // Link with syslog ports cache if (!isset($GLOBALS['cache']['syslog']['ports_links'])) { $GLOBALS['cache']['syslog']['ports_links'] = []; } $ports_links = &$GLOBALS['cache']['syslog']['ports_links']; // Highlight port links if (!isset($ports_links[$entry['device_id']])) { $ports_links[$entry['device_id']] = []; $sql = 'SELECT `port_id`, `port_label_short`, `port_label_base`, `port_label_num`, `ifDescr`, `ifName` FROM `ports` WHERE `device_id` = ? AND `deleted` = ?'; foreach (dbFetchRows($sql, [ $entry['device_id'], 0 ]) as $port_descr) { $search = [ $port_descr['ifDescr'], $port_descr['ifName'], $port_descr['port_label_short'] ]; // FIXME. Currently as hack for Extreme (should make universal with lots of examples), see: // https://jira.observium.org/browse/OBS-3304 if (preg_match('/\s(port\s*\d.*)/i', $port_descr['ifDescr'], $matches)) { $search[] = $matches[1]; } elseif (strlen($port_descr['port_label_base']) && str_contains($port_descr['port_label_num'], '/')) { // Brocade NOS derp interfaces with rbridge ids, ie: // TenGigabitEthernet 22/0/20 or Te 22/0/20 -> TenGigabitEthernet 0/20 $search[] = $port_descr['port_label_base'] . '\d+/' . $port_descr['port_label_num']; // and short $search[] = short_ifname($port_descr['port_label_base'] . '\d+/' . $port_descr['port_label_num']); } $ports_links[$entry['device_id']][$port_descr['port_id']] = [ 'search' => $search, 'replace' => generate_entity_link('port', $port_descr['port_id'], '$2') ]; } } $entity_links = $ports_links[$entry['device_id']]; // Highlight bgp peer links (try only when program match BGP) if (str_icontains_array($entry['program'], 'bgp')) { // Link with syslog bgp cache if (!isset($GLOBALS['cache']['syslog']['bgp_links'])) { $GLOBALS['cache']['syslog']['bgp_links'] = []; } $bgp_links = &$GLOBALS['cache']['syslog']['bgp_links']; if (!isset($bgp_links[$entry['device_id']])) { $bgp_links[$entry['device_id']] = []; //SELECT `bgpPeer_id`, `bgpPeerRemoteAs`, `bgpPeerIdentifier`, `bgpPeerRemoteAddr` FROM `bgpPeers` WHERE `device_id` = 2 foreach (dbFetchRows('SELECT * FROM `bgpPeers` WHERE `device_id` = ?', [ $entry['device_id'] ]) as $bgp_descr) { $search = []; foreach ([ 'bgpPeerIdentifier', 'bgpPeerRemoteAddr' ] as $param) { if ($bgp_descr[$param] === '0.0.0.0') { continue; } $search[] = 'Nbr ' . $bgp_descr[$param]; $search[] = 'Neighbor ' . $bgp_descr[$param]; if (get_ip_version($bgp_descr[$param]) == 6) { // For IPv6 append compressed form $bgp_descr[$param] = Net_IPv6::compress($bgp_descr[$param], TRUE); $search[] = 'Nbr ' . $bgp_descr[$param]; $search[] = 'Neighbor ' . $bgp_descr[$param]; } } $bgp_links[$entry['device_id']][] = [ 'search' => $search, 'replace' => generate_entity_link('bgp_peer', $bgp_descr, '$2') ]; // Additionally append AS text if ($bgp_descr['astext'] && !isset($bgp_links[$entry['device_id']]['as'.$bgp_descr['bgpPeerRemoteAs']])) { $bgp_links[$entry['device_id']]['as'.$bgp_descr['bgpPeerRemoteAs']] = [ 'search' => [ 'AS ' . $bgp_descr['bgpPeerRemoteAs'], 'AS: ' . $bgp_descr['bgpPeerRemoteAs'], 'AS' . $bgp_descr['bgpPeerRemoteAs'] ], 'replace' => generate_tooltip_link('', '$2', $bgp_descr['astext']) ]; } } } $entity_links = array_merge($entity_links, $bgp_links[$entry['device_id']]); } // Linkify entities in syslog messages if (isset($entry['msg']) && !isset($entry['message'])) { // Different field in syslog alerts and syslog $entry['message'] = $entry['msg']; } // Restore escaped quotes (for old entries) $entry['message'] = str_replace([ '\"', "\'" ], [ '"', "'" ], $entry['message']); $string .= ' ' . html_highlight(escape_html($entry['message']), $entity_links, NULL, TRUE) . '' . PHP_EOL; //$string .= ' ' . escape_html($entry['msg']) . '' . PHP_EOL; // if (!$short) // { // //$string .= '' . escape_html($entry['log_type']) . '' . PHP_EOL; // //$string .= ''. ($entry['notified'] == '1' ? 'YES' : ($entry['notified'] == '-1' ? 'SKIP' : 'NO')) . '' . PHP_EOL; // } $string .= ' ' . PHP_EOL; return $string; } function generate_syslog_form_values($form_filter = FALSE, $column = NULL) { //global $cache; $form_items = array(); $filter = is_array($form_filter); // Use filer or not switch ($column) { case 'priorities': case 'priority': foreach ($GLOBALS['config']['syslog']['priorities'] as $p => $priority) { if ($filter && !in_array($p, $form_filter)) { continue; } // Skip filtered entries if ($p > 7) { continue; } $form_items[$p] = $priority; $form_items[$p]['name'] = nicecase($priority['name']); switch ($p) { case 0: // Emergency case 1: // Alert case 2: // Critical case 3: // Error $form_items[$p]['class'] = "bg-danger"; break; case 4: // Warning $form_items[$p]['class'] = "bg-warning"; break; case 5: // Notification $form_items[$p]['class'] = "bg-success"; break; case 6: // Informational $form_items[$p]['class'] = "bg-info"; break; case 7: // Debugging $form_items[$p]['class'] = "bg-suppressed"; break; default: $form_items[$p]['class'] = "bg-disabled"; } } krsort($form_items); break; case 'programs': case 'program': // Use filter as items foreach ($form_filter as $program) { $name = ($program != '' ? $program : OBS_VAR_UNSET); $form_items[$program] = $name; } break; } return $form_items; } // EOF