mirror of
https://github.com/Cacti/plugin_thold.git
synced 2026-10-23 03:27:05 +09:00
The status pills were being clipped to a fixed width because the single-class theme rules (e.g. .deviceUpFull width:14%, padding:3px) outranked the equal-specificity .thold-pill shape rule, so long labels such as 'Not Monitored' overflowed the coloured pill on the Device Status page. Element-qualify the selector (span.thold-pill) so the shape rule wins and the pill hugs its label in every theme. Also make a second click on an already-selected status pill clear that filter (reset the Status select to All, value -1) instead of re-applying the same value. Applied to all three thold_graph.php sub-tabs (Thresholds, Device Status, Threshold Log) and the matching Thresholds console page (thold.php).
2031 lines
73 KiB
PHP
2031 lines
73 KiB
PHP
<?php
|
|
/*
|
|
+-------------------------------------------------------------------------+
|
|
| Copyright (C) 2004-2026 The Cacti Group |
|
|
| |
|
|
| This program is free software; you can redistribute it and/or |
|
|
| modify it under the terms of the GNU General Public License |
|
|
| as published by the Free Software Foundation; either version 2 |
|
|
| of the License, or (at your option) any later version. |
|
|
| |
|
|
| This program is distributed in the hope that it will be useful, |
|
|
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
| GNU General Public License for more details. |
|
|
+-------------------------------------------------------------------------+
|
|
| Cacti: The Complete RRDTool-based Graphing Solution |
|
|
+-------------------------------------------------------------------------+
|
|
| This code is designed, written, and maintained by the Cacti Group. See |
|
|
| about.php and/or the AUTHORS file for specific developer information. |
|
|
+-------------------------------------------------------------------------+
|
|
| http://www.cacti.net/ |
|
|
+-------------------------------------------------------------------------+
|
|
*/
|
|
|
|
$guest_account = true;
|
|
|
|
chdir('../../');
|
|
include_once('./include/auth.php');
|
|
|
|
require_once($config['base_path'] . '/lib/rrd.php');
|
|
include_once($config['base_path'] . '/plugins/thold/includes/functions.php');
|
|
include_once($config['base_path'] . '/plugins/thold/setup.php');
|
|
include_once($config['base_path'] . '/plugins/thold/includes/database.php');
|
|
include($config['base_path'] . '/plugins/thold/includes/arrays.php');
|
|
|
|
thold_initialize_rusage();
|
|
|
|
plugin_thold_upgrade();
|
|
|
|
delete_old_thresholds();
|
|
|
|
set_default_action('thold');
|
|
|
|
switch(get_request_var('action')) {
|
|
case 'ajax_hosts':
|
|
get_allowed_ajax_hosts(true, false, 'h.id IN (SELECT host_id FROM thold_data)');
|
|
|
|
break;
|
|
case 'ajax_hosts_noany':
|
|
get_allowed_ajax_hosts(false, false, 'h.id IN (SELECT host_id FROM thold_data)');
|
|
|
|
break;
|
|
case 'thold':
|
|
general_header();
|
|
thold_tabs();
|
|
tholds();
|
|
bottom_footer();
|
|
|
|
break;
|
|
case 'ack':
|
|
thold_threshold_ack_prompt(get_filter_request_var('threshold_id'));
|
|
|
|
break;
|
|
case 'ack_confirm':
|
|
thold_threshold_ack(get_filter_request_var('threshold_id'));
|
|
raise_message('reset_ack', __('The Threshold has been Ascknowledged.', 'thold'), MESSAGE_LEVEL_INFO);
|
|
|
|
header('Location: thold_graph.php');
|
|
|
|
break;
|
|
case 'reset_ack':
|
|
thold_threshold_suspend_ack(get_filter_request_var('threshold_id'));
|
|
raise_message('reset_ack', __('The Threshold will no longer generate Alerts, Notifications, or execute commands.', 'thold'), MESSAGE_LEVEL_INFO);
|
|
|
|
header('Location: thold_graph.php');
|
|
|
|
break;
|
|
case 'resume_ack':
|
|
thold_threshold_resume_ack(get_filter_request_var('threshold_id'));
|
|
raise_message('reset_ack', __('The Threshold will restart generating Alerts.', 'thold'), MESSAGE_LEVEL_INFO);
|
|
|
|
header('Location: thold_graph.php');
|
|
|
|
break;
|
|
case 'disable':
|
|
thold_threshold_disable(get_filter_request_var('id'));
|
|
|
|
header('Location: thold_graph.php');
|
|
|
|
exit;
|
|
case 'enable':
|
|
thold_threshold_enable(get_filter_request_var('id'));
|
|
|
|
header('Location: thold_graph.php');
|
|
|
|
exit;
|
|
case 'exportlog':
|
|
thold_export_log();
|
|
|
|
exit;
|
|
case 'hoststat':
|
|
general_header();
|
|
thold_tabs();
|
|
hosts();
|
|
bottom_footer();
|
|
|
|
break;
|
|
default:
|
|
if (api_plugin_hook_function('thold_graph_view', false) === false) {
|
|
general_header();
|
|
thold_tabs();
|
|
thold_show_log();
|
|
bottom_footer();
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// Clear the Nav Cache, so that it doesn't know we came from Thold
|
|
$_SESSION['sess_nav_level_cache'] = [];
|
|
|
|
/**
|
|
* Renders the search/state/host/site/template filter form controls for
|
|
* the thresholds list view.
|
|
*
|
|
* @return void
|
|
*
|
|
* @global array $item_rows Rows-per-page option list used to populate
|
|
* the rows dropdown.
|
|
* @global array $config Cacti global configuration array (declared
|
|
* but not used directly here).
|
|
*/
|
|
function form_thold_filter() {
|
|
global $item_rows, $config;
|
|
|
|
?>
|
|
<tr class='even'>
|
|
<td>
|
|
<form id='thold' action='thold_graph.php'>
|
|
<table class='filterTable'>
|
|
<tr>
|
|
<td>
|
|
<?php print __('Search', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<input type='text' id='rfilter' size='30' value='<?php print html_escape_request_var('rfilter'); ?>'>
|
|
</td>
|
|
<td>
|
|
<?php print __('Site', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='site_id'>
|
|
<option value='-1'<?php if (get_request_var('site_id') == '-1') {?> selected<?php }?>><?php print __('All', 'thold'); ?></option>
|
|
<option value='0'<?php if (get_request_var('site_id') == '0') {?> selected<?php }?>><?php print __('None', 'thold'); ?></option>
|
|
<?php
|
|
$sites = db_fetch_assoc('SELECT id, name
|
|
FROM sites
|
|
ORDER BY name');
|
|
|
|
if (cacti_sizeof($sites)) {
|
|
foreach ($sites as $site) {
|
|
print "<option value='" . $site['id'] . "'";
|
|
|
|
if (get_request_var('site_id') == $site['id']) {
|
|
print ' selected';
|
|
} print '>' . html_escape($site['name']) . '</option>';
|
|
}
|
|
}
|
|
?>
|
|
</select>
|
|
</td>
|
|
<?php print html_host_filter(get_request_var('host_id')); ?>
|
|
<td>
|
|
<span>
|
|
<input id='refresh' type='submit' value='<?php print __esc('Go', 'thold'); ?>'>
|
|
<input id='clear' type='button' value='<?php print __esc('Clear', 'thold'); ?>'>
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<table class='filterTable'>
|
|
<tr>
|
|
<td>
|
|
<?php print __('Template', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='thold_template_id'>
|
|
<option value='-1'<?php if (get_request_var('thold_template_id') == '-1') {?> selected<?php }?>><?php print __('All', 'thold'); ?></option>
|
|
<option value='-2'<?php if (get_request_var('thold_template_id') == '-2') {?> selected<?php }?>><?php print __('None', 'thold'); ?></option>
|
|
<?php
|
|
$thold_templates = db_fetch_assoc('SELECT DISTINCT tt.id, tt.name
|
|
FROM thold_template as tt
|
|
ORDER BY tt.name');
|
|
|
|
foreach ($thold_templates as $row) {
|
|
print "<option value='" . $row['id'] . "'" . (isset_request_var('thold_template_id') && $row['id'] == get_request_var('thold_template_id') ? ' selected' : '') . '>' . html_escape($row['name']) . '</option>';
|
|
}
|
|
?>
|
|
</select>
|
|
</td>
|
|
<td>
|
|
<?php print __('Data Template', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='data_template_id'>
|
|
<option value='-1'<?php if (get_request_var('data_template_id') == '-1') {?> selected<?php }?>><?php print __('All', 'thold'); ?></option>
|
|
<option value='0'<?php if (get_request_var('data_template_id') == '0') {?> selected<?php }?>><?php print __('None', 'thold'); ?></option>
|
|
<?php
|
|
$data_templates = db_fetch_assoc('SELECT DISTINCT data_template.id, data_template.name
|
|
FROM thold_data
|
|
INNER JOIN data_template
|
|
ON thold_data.data_template_id=data_template.id ' .
|
|
(get_request_var('host_id') > 0 ? 'WHERE thold_data.host_id=' . get_request_var('host_id') : '') .
|
|
' ORDER by data_template.name');
|
|
|
|
if (cacti_sizeof($data_templates)) {
|
|
foreach ($data_templates as $data_template) {
|
|
print "<option value='" . $data_template['id'] . "'";
|
|
|
|
if (get_request_var('data_template_id') == $data_template['id']) {
|
|
print ' selected';
|
|
} print '>' . html_escape($data_template['name']) . '</option>';
|
|
}
|
|
}
|
|
?>
|
|
</select>
|
|
</td>
|
|
<td>
|
|
<?php print __('Status', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='state'>
|
|
<option value='-1'<?php if (get_request_var('state') == '-1') {?> selected<?php }?>><?php print __('All', 'thold'); ?></option>
|
|
<option value='0'<?php if (get_request_var('state') == '0') {?> selected<?php }?>><?php print __('Breached or Triggered', 'thold'); ?></option>
|
|
<option value='1'<?php if (get_request_var('state') == '1') {?> selected<?php }?>><?php print __('Breached', 'thold'); ?></option>
|
|
<option value='3'<?php if (get_request_var('state') == '3') {?> selected<?php }?>><?php print __('Triggered', 'thold'); ?></option>
|
|
<option value='2'<?php if (get_request_var('state') == '2') {?> selected<?php }?>><?php print __('Enabled', 'thold'); ?></option>
|
|
<option value='6'<?php if (get_request_var('state') == '6') {?> selected<?php }?>><?php print __('Disabled', 'thold'); ?></option>
|
|
<option value='7'<?php if (get_request_var('state') == '7') {?> selected<?php }?>><?php print __('Disabled at Template', 'thold'); ?></option>
|
|
<option value='5'<?php if (get_request_var('state') == '5') {?> selected<?php }?>><?php print __('Disabled at Threshold', 'thold'); ?></option>
|
|
<option value='4'<?php if (get_request_var('state') == '4') {?> selected<?php }?>><?php print __('Ack Required', 'thold'); ?></option>
|
|
<optgroup label='<?php print html_escape(__('By Status', 'thold')); ?>'>
|
|
<?php foreach ([101 => __('Alert', 'thold'), 102 => __('Baseline Alert', 'thold'), 103 => __('Warning', 'thold'), 104 => __('Notice', 'thold'), 105 => __('Ok', 'thold'), 106 => __('Acknowledgment', 'thold'), 107 => __('Disabled', 'thold')] as $sev_value => $sev_label) { ?>
|
|
<option value='<?php print $sev_value; ?>'<?php if (get_request_var('state') == $sev_value) {?> selected<?php }?>><?php print html_escape($sev_label); ?></option>
|
|
<?php } ?>
|
|
</optgroup>
|
|
</select>
|
|
</td>
|
|
<td>
|
|
<?php print __('Thresholds', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='rows'>
|
|
<option value='-1'<?php if (get_request_var('rows') == '-1') {?> selected<?php }?>><?php print __('Default', 'thold'); ?></option>
|
|
<?php
|
|
if (cacti_sizeof($item_rows)) {
|
|
foreach ($item_rows as $key => $value) {
|
|
print "<option value='" . $key . "'";
|
|
|
|
if (get_request_var('rows') == $key) {
|
|
print ' selected';
|
|
} print '>' . $value . '</option>';
|
|
}
|
|
}
|
|
?>
|
|
</select>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<input type='hidden' id='page' value='<?php print html_escape(get_request_var('page')); ?>'>
|
|
<input type='hidden' id='tab' value='thold'>
|
|
</form>
|
|
<script type='text/javascript' <?php print plugin_thold_csp_nonce(); ?>>
|
|
|
|
function applyFilter() {
|
|
strURL = 'thold_graph.php?header=false&action=thold';
|
|
strURL += '&state=' + encodeURIComponent($('#state').val());
|
|
strURL += '&thold_template_id=' + encodeURIComponent($('#thold_template_id').val());
|
|
strURL += '&data_template_id=' + encodeURIComponent($('#data_template_id').val());
|
|
strURL += '&host_id=' + encodeURIComponent($('#host_id').val());
|
|
strURL += '&site_id=' + encodeURIComponent($('#site_id').val());
|
|
strURL += '&rows=' + encodeURIComponent($('#rows').val());
|
|
strURL += '&rfilter=' + encodeURIComponent(base64_encode($('#rfilter').val()));
|
|
loadPageNoHeader(strURL);
|
|
}
|
|
|
|
function clearFilter() {
|
|
strURL = 'thold_graph.php?header=false&action=thold&clear=1';
|
|
loadPageNoHeader(strURL);
|
|
}
|
|
|
|
$(function() {
|
|
$('#thold').submit(function(event) {
|
|
event.preventDefault();
|
|
applyFilter();
|
|
});
|
|
|
|
$('#site_id, #thold_template_id, #data_template_id, #state, #rows').change(function() {
|
|
applyFilter();
|
|
});
|
|
|
|
$('.thold-pill').on('click keydown', function(e) {
|
|
if (e.type === 'keydown' && e.which !== 13 && e.which !== 32) {
|
|
return;
|
|
}
|
|
|
|
e.preventDefault();
|
|
var state = $(this).attr('data-state');
|
|
$('#state').val($('#state').val() === state ? '-1' : state);
|
|
applyFilter();
|
|
});
|
|
|
|
$('#clear').click(function() {
|
|
clearFilter();
|
|
});
|
|
|
|
$('.ackMessage').tooltip({
|
|
items: '.ackMessage',
|
|
track: false,
|
|
position: { my: 'left', of: event, at: 'right+10', collision: 'fit' },
|
|
content: function() {
|
|
var text = atob($(this).attr('data-ack'));
|
|
return text;
|
|
},
|
|
open: function(event, ui) {
|
|
if (typeof(event.originalEvent) === 'undefined') {
|
|
return false;
|
|
}
|
|
|
|
var id = $(ui.tooltip).attr('id');
|
|
|
|
$('div.ui-tooltip').not('#' + id).remove();
|
|
|
|
ui.tooltip.css('width', '800px');
|
|
ui.tooltip.css('max-width', '800px');
|
|
},
|
|
close: function(event, ui) {
|
|
ui.tooltip.hover(
|
|
function() {
|
|
$(this).stop(true).fadeTo(400, 1);
|
|
},
|
|
function() {
|
|
$(this).fadeOut('400', function() {
|
|
$(this).remove();
|
|
});
|
|
}
|
|
);
|
|
}
|
|
});
|
|
});
|
|
|
|
</script>
|
|
</td>
|
|
</tr>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Renders the main thresholds list page (the plugin's primary
|
|
* dashboard view): validates/stores this view's filter request
|
|
* variables, displays the threshold filter form, then displays a
|
|
* filtered, sorted, paginated table of thresholds with a bulk-actions
|
|
* dropdown and status legend. Called from this script's main
|
|
* request-dispatch switch as the default 'thold' view.
|
|
*
|
|
* @return void
|
|
*
|
|
* @global array $config Cacti global configuration array.
|
|
* @global array $device_actions Map of drp_action value => action
|
|
* label, used for the bulk-actions
|
|
* dropdown.
|
|
* @global array $item_rows Default number of rows per page from
|
|
* Cacti settings.
|
|
* @global array $thold_classes Reserved/declared for parity with
|
|
* other functions in this file; not used
|
|
* directly here.
|
|
* @global array $thold_states Threshold state option list used by
|
|
* the filter form.
|
|
*/
|
|
function tholds() {
|
|
global $config, $device_actions, $item_rows, $thold_classes, $thold_states;
|
|
|
|
$default_status = read_config_option('thold_filter_default');
|
|
|
|
if (!is_numeric($default_status)) {
|
|
set_config_option('thold_filter_default', '-1');
|
|
$default_status = '-1';
|
|
}
|
|
|
|
// ================= input validation and session storage =================
|
|
$filters = [
|
|
'rows' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
],
|
|
'page' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'default' => '1'
|
|
],
|
|
'rfilter' => [
|
|
'filter' => FILTER_VALIDATE_IS_REGEX,
|
|
'pageset' => true,
|
|
'default' => ''
|
|
],
|
|
'sort_column' => [
|
|
'filter' => FILTER_CALLBACK,
|
|
'default' => 'name_cache',
|
|
'options' => ['options' => 'sanitize_thold_sort_string']
|
|
],
|
|
'sort_direction' => [
|
|
'filter' => FILTER_CALLBACK,
|
|
'default' => 'ASC',
|
|
'options' => ['options' => 'sanitize_search_string']
|
|
],
|
|
'data_template_id' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
],
|
|
'thold_template_id' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
],
|
|
'host_id' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
],
|
|
'site_id' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
],
|
|
'state' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => $default_status
|
|
]
|
|
];
|
|
|
|
validate_store_request_vars($filters, 'sess_thold');
|
|
// ================= input validation =================
|
|
|
|
// if the number of rows is -1, set it to the default
|
|
if (get_request_var('rows') == -1) {
|
|
$rows = intval(read_config_option('num_rows_table'));
|
|
} else {
|
|
$rows = intval(get_request_var('rows'));
|
|
}
|
|
|
|
html_start_box(__('Threshold Status', 'thold'), '100%', false, '3', 'center', '');
|
|
form_thold_filter();
|
|
html_end_box();
|
|
|
|
$sql_order = get_order_string();
|
|
$sql_limit = ($rows * (intval(get_request_var('page')) - 1)) . ',' . $rows;
|
|
$sql_order = str_replace('ORDER BY ', '', $sql_order);
|
|
|
|
if (get_request_var('sort_column') == 'severity') {
|
|
$sql_order = thold_severity_sql() . ' ' . (get_request_var('sort_direction') == 'DESC' ? 'DESC' : 'ASC');
|
|
}
|
|
|
|
$sql_where = '(h.status = 3';
|
|
$statefilter = thold_get_state_filter(get_request_var('state'));
|
|
|
|
if (get_request_var('rfilter') != '') {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . 'td.name_cache ' . thold_rlike_clause(get_request_var('rfilter'));
|
|
}
|
|
|
|
if (get_request_var('data_template_id') != '-1') {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND') . ' td.data_template_id = ' . get_request_var('data_template_id');
|
|
}
|
|
|
|
if (!isempty_request_var('thold_template_id')) {
|
|
if (get_request_var('thold_template_id') > 0) {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . '(td.thold_template_id = ' . get_request_var('thold_template_id') . ' AND td.template_enabled = "on")';
|
|
} elseif (get_request_var('thold_template_id') == '-2') {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . '(td.template_enabled != "on")';
|
|
}
|
|
}
|
|
|
|
if (get_request_var('host_id') != '-1') {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND') . ' td.host_id = ' . get_request_var('host_id');
|
|
}
|
|
|
|
if ($statefilter != '') {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . $statefilter;
|
|
}
|
|
|
|
if (get_request_var('site_id') == '-1') {
|
|
// Show all items
|
|
} elseif (get_request_var('site_id') == '0') {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . 'h.site_id IS NULL';
|
|
} elseif (!isempty_request_var('site_id')) {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . 'h.site_id = ' . get_request_var('site_id');
|
|
}
|
|
|
|
if ($sql_where != '') {
|
|
$sql_where .= ')';
|
|
}
|
|
|
|
$tholds = get_allowed_thresholds($sql_where, $sql_order, $sql_limit, $total_rows);
|
|
|
|
$nav = html_nav_bar('thold_graph.php?action=thold', MAX_DISPLAY_PAGES, get_request_var('page'), $rows, $total_rows, 13, 'Thresholds', 'page', 'main');
|
|
|
|
print $nav;
|
|
|
|
html_start_box('', '100%', false, '3', 'center', '');
|
|
|
|
$display_text = [
|
|
'nosort' => [
|
|
'display' => __('Actions', 'thold'),
|
|
'sort' => '',
|
|
'align' => 'left'
|
|
],
|
|
'name_cache' => [
|
|
'display' => __('Name', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'left'
|
|
],
|
|
'severity' => [
|
|
'display' => __('Status', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'left',
|
|
'tip' => __('The current threshold status. Click a status pill to filter the list to that status.', 'thold')
|
|
],
|
|
'external_id' => [
|
|
'display' => __('External ID', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'left'
|
|
],
|
|
'nosort99' => [
|
|
'display' => __('Enabled', 'thold'),
|
|
'align' => 'right'
|
|
],
|
|
'id' => [
|
|
'display' => __('ID', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'right'
|
|
],
|
|
'nosort6' => [
|
|
'display' => __('Ack Detail', 'thold'),
|
|
'align' => 'center'
|
|
],
|
|
'thold_type' => [
|
|
'display' => __('Type', 'thold'),
|
|
'sort' => 'ASC',
|
|
'tip' => __('The Threshold Type. For Baseline Types: [TIP] refers to the Time In the Past with MIN, MAX, AVG, and LAST from no more than a day in time from that period. [AOT] refers to the Average over the entire Time period. If there is a colon followed by MIN, MAX, AVG, LAST, the Value came from that Consolidation Function.', 'thold'),
|
|
'align' => 'right'
|
|
],
|
|
'flastread' => [
|
|
'display' => __('Current', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'right',
|
|
'tip' => __('The last measured value for the Data Source', 'thold')
|
|
],
|
|
'nosort4' => [
|
|
'display' => __('High', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'right',
|
|
'tip' => __('The High Warning / Alert values. NOTE: Baseline values are a percent, all other values are display values that may be modified by a cdef.', 'thold')
|
|
],
|
|
'nosort5' => [
|
|
'display' => __('Low', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'right',
|
|
'tip' => __('The Low Warning / Alert values. NOTE: Baseline values are a percent, all other values are display values that may be modified by a cdef.', 'thold')
|
|
],
|
|
'nosort2' => [
|
|
'display' => __('Trigger', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'right'
|
|
],
|
|
'nosort3' => [
|
|
'display' => __('Duration', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'right'
|
|
],
|
|
'repeat_alert' => [
|
|
'display' => __('Repeat', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'right'
|
|
],
|
|
'thold_alert' => [
|
|
'display' => __('Triggered', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'right'
|
|
],
|
|
'instate' => [
|
|
'display' => __('In State', 'thold'),
|
|
'sort' => 'DESC',
|
|
'align' => 'right',
|
|
'tip' => __('The amount of time that has passed since the Threshold either Breached or was Triggered', 'thold')
|
|
],
|
|
'acknowledgment' => [
|
|
'display' => __('Ack Required', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'right',
|
|
'tip' => __('Acknowledgment required for this Threshold', 'thold')
|
|
]
|
|
];
|
|
|
|
html_header_sort($display_text, get_request_var('sort_column'), get_request_var('sort_direction'), false, 'thold_graph.php?action=thold');
|
|
|
|
$c = 0;
|
|
|
|
if (cacti_sizeof($tholds)) {
|
|
foreach ($tholds as $thold_data) {
|
|
$step = db_fetch_cell_prepared('SELECT rrd_step
|
|
FROM data_template_data
|
|
WHERE local_data_id = ?',
|
|
[$thold_data['local_data_id']]);
|
|
|
|
include($config['base_path'] . '/plugins/thold/includes/arrays.php');
|
|
|
|
$c++;
|
|
$alertstat = __('No', 'thold');
|
|
$bgcolor = 'green';
|
|
|
|
$severity = get_thold_severity($thold_data);
|
|
|
|
switch($severity) {
|
|
case THOLD_SEVERITY_DISABLED:
|
|
$bgcolor = 'grey';
|
|
|
|
break;
|
|
case THOLD_SEVERITY_NORMAL:
|
|
$bgcolor = 'green';
|
|
|
|
break;
|
|
case THOLD_SEVERITY_ALERT:
|
|
$bgcolor = 'red';
|
|
|
|
break;
|
|
case THOLD_SEVERITY_WARNING:
|
|
$bgcolor = 'warning';
|
|
|
|
break;
|
|
case THOLD_SEVERITY_BASELINE:
|
|
$bgcolor = 'orange';
|
|
|
|
break;
|
|
case THOLD_SEVERITY_NOTICE:
|
|
$bgcolor = 'yellow';
|
|
|
|
break;
|
|
case THOLD_SEVERITY_ACKREQ:
|
|
$bgcolor = 'purple';
|
|
|
|
break;
|
|
}
|
|
|
|
if ($thold_data['thold_type'] == 0) {
|
|
if ($thold_data['thold_alert'] != 0) {
|
|
$alertstat = __('Yes', 'thold');
|
|
}
|
|
} elseif ($thold_data['thold_type'] == 2) {
|
|
if ($thold_data['thold_alert'] != 0) {
|
|
$alertstat = __('Yes', 'thold');
|
|
}
|
|
} else {
|
|
if ($thold_data['bl_alert'] == 1) {
|
|
$alertstat = __('baseline-LOW', 'thold');
|
|
} elseif ($thold_data['bl_alert'] == 2) {
|
|
$alertstat = __('baseline-HIGH', 'thold');
|
|
}
|
|
}
|
|
|
|
print "<tr class='tableRow selectable' id='line" . $thold_data['id'] . "'>";
|
|
|
|
$baseu = db_fetch_cell_prepared('SELECT base_value
|
|
FROM graph_templates_graph
|
|
WHERE local_graph_id = ?',
|
|
[$thold_data['local_graph_id']]);
|
|
|
|
if ($thold_data['data_type'] == 2) {
|
|
$suffix = false;
|
|
} else {
|
|
$suffix = true;
|
|
}
|
|
|
|
$show_units = ($thold_data['show_units'] ? true : false);
|
|
$units_suffix = $thold_data['units_suffix'];
|
|
$decimals = $thold_data['decimals'];
|
|
|
|
if (empty($baseu)) {
|
|
cacti_log('WARNING: Graph Template for local_graph_id ' . $thold_data['local_graph_id'] . ' has been removed!');
|
|
$baseu = 1024;
|
|
}
|
|
|
|
// Check is the graph item has a cdef and modify the output
|
|
thold_modify_values_by_cdef($thold_data);
|
|
|
|
$actions_url = '';
|
|
|
|
if (api_user_realm_auth('thold.php')) {
|
|
$actions_url .= '<a class="pic" href="' . html_escape($config['url_path'] . 'plugins/thold/thold.php?action=edit&id=' . $thold_data['id']) . '" title="' . __esc('Edit Threshold', 'thold') . '"><i class="tholdGlyphEdit fas fa-wrench"></i></a>';
|
|
}
|
|
|
|
if (api_user_realm_auth('thold.php')) {
|
|
if ($thold_data['thold_per_enabled'] == 'on') {
|
|
$actions_url .= '<a class="pic" href="' . html_escape($config['url_path'] . 'plugins/thold/thold_graph.php?action=disable&id=' . $thold_data['id']) . '" title="' . __esc('Disable Threshold', 'thold') . '"><i class="tholdGlyphDisable fas fa-stop-circle"></i></a>';
|
|
} elseif ((($thold_data['template_enabled'] == 'on' && $thold_data['thold_enabled'] == 'on') || $thold_data['template_enabled'] != 'on') &&
|
|
$thold_data['thold_per_enabled'] == '') {
|
|
$actions_url .= '<a class="pic" href="' . html_escape($config['url_path'] . 'plugins/thold/thold_graph.php?action=enable&id=' . $thold_data['id']) . '" title="' . __esc('Enable Threshold', 'thold') . '"><i class="tholdGlyphEnable fas fa-play-circle"></i></a>';
|
|
} else {
|
|
$actions_url .= '<a class="pic" href="#" title="' . __esc('To enable the Threshold, enable the Template first', 'thold') . '"><i class="deviceDisabled fas fa-play-circle"></i></a>';
|
|
}
|
|
}
|
|
|
|
thold_get_cached_name($thold_data);
|
|
|
|
$actions_url .= "<a href='" . html_escape($config['url_path'] . 'graph.php?local_graph_id=' . $thold_data['local_graph_id'] . '&rra_id=all') . "' title='" . __esc('View Graph', 'thold') . "'><i class='tholdGlyphChart fas fa-chart-area'></i></a>";
|
|
|
|
$actions_url .= "<a class='pic' href='" . html_escape($config['url_path'] . 'plugins/thold/thold_graph.php?action=log&reset=1&threshold_id=' . $thold_data['id'] . '&host_id=' . $thold_data['host_id'] . '&status=-1') . "' title='" . __esc('View Threshold History', 'thold') . "'><i class='tholdGlyphLog fas fa-exclamation-triangle'></i></a>";
|
|
|
|
if (api_user_realm_auth('thold.php')) {
|
|
if ($thold_data['acknowledgment'] == 'on') {
|
|
$actions_url .= "<a class='pic' href='" . html_escape($config['url_path'] . 'plugins/thold/thold_graph.php?action=ack&threshold_id=' . $thold_data['id']) . "' title='" . __esc('Acknowledge Threshold', 'thold') . "'><i class='tholdGlyphAcknowledge fas fa-clipboard-check'></i></a>";
|
|
|
|
if ($thold_data['reset_ack'] == 'on') {
|
|
$actions_url .= "<a class='pic' href='" . html_escape($config['url_path'] . 'plugins/thold/thold_graph.php?action=reset_ack&threshold_id=' . $thold_data['id']) . "' title='" . __esc('Suspend Notifications until the Threshold clears', 'thold') . "'><i class='tholdGlyphAcknowledgeSuspend fas fa-clipboard-check'></i></a>";
|
|
}
|
|
} elseif ($thold_data['thold_alert'] > 0 && $thold_data['reset_ack'] == 'on') {
|
|
$actions_url .= "<a class='pic' href='" . html_escape($config['url_path'] . 'plugins/thold/thold_graph.php?action=resume_ack&threshold_id=' . $thold_data['id']) . "' title='" . __esc('Resume Notifications for this breached Threshold', 'thold') . "'><i class='tholdGlyphAcknowledgeResume fas fa-clipboard-check'></i></a>";
|
|
}
|
|
}
|
|
|
|
$data = [
|
|
'thold_data' => $thold_data,
|
|
'actions_url' => $actions_url
|
|
];
|
|
|
|
$data = api_plugin_hook_function('thold_graph_actions_url', $data);
|
|
|
|
if (isset($data['actions_url'])) {
|
|
$actions_url = $data['actions_url'];
|
|
}
|
|
|
|
if ($thold_data['reset_ack'] == 'on' || $thold_data['persist_ack'] == 'on') {
|
|
$acks = db_fetch_assoc_prepared('SELECT *
|
|
FROM plugin_thold_log
|
|
WHERE type = 99
|
|
AND threshold_id = ?
|
|
LIMIT 5',
|
|
[$thold_data['id']]);
|
|
|
|
if (cacti_sizeof($acks)) {
|
|
$table = '<table class="cactiTable">
|
|
<tr class="tableHeader">
|
|
<th>' . __('Acknowledgement Message', 'thold') . '</th>
|
|
<th>' . __('Date', 'thold') . '</th>
|
|
</tr>';
|
|
|
|
foreach ($acks as $a) {
|
|
$parts = explode('Additional Comments:', $a['description']);
|
|
|
|
if (isset($parts[1])) {
|
|
$comment = trim($parts[1], '" ');
|
|
} else {
|
|
$comment = __('Comment Not Found', 'thold');
|
|
}
|
|
|
|
$table .= '<tr>
|
|
<td>' . $comment . '</td>
|
|
<td>' . date('Y-m-d H:i:s', $a['time']) . '</td>
|
|
</tr>';
|
|
}
|
|
|
|
$details = '<a class="ackMessage" href="#" data-ack="' . base64_encode($table) . '">' . __('Ack History', 'thold') . '</a>';
|
|
} else {
|
|
$details = '';
|
|
}
|
|
} else {
|
|
$details = '';
|
|
}
|
|
|
|
form_selectable_cell($actions_url, $thold_data['id'], '', 'left');
|
|
|
|
form_selectable_cell($thold_data['name_cache'] != '' ? filter_value($thold_data['name_cache'], get_request_var('rfilter')) : __('No name set', 'thold'), $thold_data['id'], '', 'left');
|
|
|
|
form_selectable_cell("<span class='thold-pill " . $thold_states[$bgcolor]['class'] . "' data-state='" . ['red' => 101, 'orange' => 102, 'warning' => 103, 'yellow' => 104, 'green' => 105, 'purple' => 106, 'grey' => 107][$bgcolor] . "' tabindex='0' role='button'>" . html_escape($thold_states[$bgcolor]['display']) . '</span>', $thold_data['id'], '', 'left');
|
|
form_selectable_cell($thold_data['external_id'], $thold_data['id'], '', 'left');
|
|
|
|
if ((($thold_data['template_enabled'] == 'on' && $thold_data['thold_enabled'] == 'on') || $thold_data['template_enabled'] != 'on') && $thold_data['thold_per_enabled'] == 'on') {
|
|
$enabled = __('Yes', 'thold');
|
|
} elseif ($thold_data['template_enabled'] == 'on' && $thold_data['thold_enabled'] == 'off' && $thold_data['thold_per_enabled'] == '') {
|
|
$enabled = __('No [Template:Thold]', 'thold');
|
|
} elseif ($thold_data['template_enabled'] == 'on' && $thold_data['thold_enabled'] == 'off') {
|
|
$enabled = __('No [Template]', 'thold');
|
|
} else {
|
|
$enabled = __('No [Thold]', 'thold');
|
|
}
|
|
|
|
form_selectable_cell($enabled, $thold_data['id'], '', 'right');
|
|
|
|
form_selectable_cell($thold_data['id'], $thold_data['id'], '', 'right');
|
|
|
|
form_selectable_cell($details, $thold_data['id'], '', 'center');
|
|
|
|
if ($thold_data['thold_type'] != 1) {
|
|
form_selectable_cell($thold_types[$thold_data['thold_type']], $thold_data['id'], '', 'right');
|
|
} else {
|
|
$bl_type = get_bl_type($thold_data['bl_type'], $thold_data['bl_cf']);
|
|
form_selectable_cell($bl_type, $thold_data['id'], '', 'right');
|
|
}
|
|
|
|
form_selectable_cell(thold_format_number($thold_data['lastread'], $decimals, $baseu, $suffix, $show_units, $units_suffix), $thold_data['id'], '', 'right');
|
|
|
|
switch($thold_data['thold_type']) {
|
|
case 0:
|
|
form_selectable_cell(thold_format_number($thold_data['thold_warning_hi'], $decimals, $baseu, $suffix, $show_units, $units_suffix) . ' / ' . thold_format_number($thold_data['thold_hi'], $decimals, $baseu, $suffix, $show_units, $units_suffix), $thold_data['id'], '', 'right');
|
|
form_selectable_cell(thold_format_number($thold_data['thold_warning_low'], $decimals, $baseu, $suffix, $show_units, $units_suffix) . ' / ' . thold_format_number($thold_data['thold_low'], $decimals, $baseu, $suffix, $show_units, $units_suffix), $thold_data['id'], '', 'right');
|
|
form_selectable_cell('<i>' . plugin_thold_duration_convert($thold_data['local_data_id'], $thold_data['thold_fail_trigger'], 'alert') . '</i>', $thold_data['id'], '', 'right');
|
|
form_selectable_cell(__('N/A', 'thold'), $thold_data['id'], '', 'right');
|
|
|
|
break;
|
|
case 1:
|
|
$hi = thold_format_number($thold_data['thold_hi'], $decimals, $baseu, $suffix, $show_units, $units_suffix);
|
|
$hi_var = thold_format_number($thold_data['bl_pct_up'], $decimals, $baseu, $suffix, $show_units, $units_suffix);
|
|
$low = thold_format_number($thold_data['thold_low'], $decimals, $baseu, $suffix, $show_units, $units_suffix);
|
|
$low_var = thold_format_number($thold_data['bl_pct_down'], $decimals, $baseu, $suffix, $show_units, $units_suffix);
|
|
|
|
if ($thold_data['bl_type'] == 0 || $thold_data['bl_type'] == 2) {
|
|
$suffix = ' %';
|
|
} else {
|
|
$suffix = '';
|
|
}
|
|
|
|
form_selectable_cell($hi != '' ? $hi . ' [ ' . $hi_var . " $suffix ]" : '-', $thold_data['id'], '', 'right');
|
|
form_selectable_cell($low != '' ? $low . ' [ ' . $low_var . " $suffix ]" : '-', $thold_data['id'], '', 'right');
|
|
|
|
form_selectable_cell('<i>' . plugin_thold_duration_convert($thold_data['local_data_id'], $thold_data['bl_fail_trigger'], 'alert') . '</i>', $thold_data['id'], '', 'right');
|
|
form_selectable_cell($timearray[$thold_data['bl_ref_time_range'] / $thold_data['rrd_step']], $thold_data['id'], '', 'right');
|
|
|
|
break;
|
|
case 2:
|
|
form_selectable_cell(thold_format_number($thold_data['time_warning_hi'], $decimals, $baseu, $suffix, $show_units, $units_suffix) . ' / ' . thold_format_number($thold_data['time_hi'], $decimals, $baseu, $suffix, $show_units, $units_suffix), $thold_data['id'], '', 'right');
|
|
form_selectable_cell(thold_format_number($thold_data['time_warning_low'], $decimals, $baseu, $suffix, $show_units, $units_suffix) . ' / ' . thold_format_number($thold_data['time_low'], $decimals, $baseu, $suffix, $show_units, $units_suffix), $thold_data['id'], '', 'right');
|
|
form_selectable_cell('<i>' . __('%d Triggers', $thold_data['time_fail_trigger'], 'thold') . '</i>', $thold_data['id'], '', 'right');
|
|
form_selectable_cell('<i>' . plugin_thold_duration_convert($thold_data['local_data_id'], $thold_data['time_fail_length'], 'time') . '</i>', $thold_data['id'], '', 'right');
|
|
|
|
break;
|
|
default:
|
|
form_selectable_cell('- / -', $thold_data['id'], '', 'right');
|
|
form_selectable_cell('- / -', $thold_data['id'], '', 'right');
|
|
form_selectable_cell(__('N/A', 'thold'), $thold_data['id'], '', 'right');
|
|
form_selectable_cell(__('N/A', 'thold'), $thold_data['id'], '', 'right');
|
|
}
|
|
|
|
form_selectable_cell(($thold_data['repeat_alert'] == '' ? '' : plugin_thold_duration_convert($thold_data['local_data_id'], $thold_data['repeat_alert'], 'repeat')), $thold_data['id'], '', 'right');
|
|
|
|
form_selectable_cell($alertstat, $thold_data['id'], '', 'right');
|
|
|
|
// The time since this threshold was triggered
|
|
form_selectable_cell('<i>' . get_time_since_last_event($thold_data) . '</i>', $thold_data['id'], '', 'right');
|
|
|
|
form_selectable_cell(($thold_data['acknowledgment'] == '' ? __('No', 'thold') : __('Yes', 'thold')), $thold_data['id'], '', 'right ' . ($thold_data['acknowledgment'] == '' ? '' : 'tholdAckCol'));
|
|
|
|
form_end_row();
|
|
}
|
|
} else {
|
|
print '<tr class="tableRow"><td class="center" colspan="' . cacti_sizeof($display_text) . '">' . __('No Thresholds', 'thold') . '</td></tr>';
|
|
}
|
|
|
|
html_end_box(false);
|
|
|
|
if (cacti_sizeof($tholds)) {
|
|
print $nav;
|
|
}
|
|
|
|
print '<div class="center tholdLegendFooter">';
|
|
|
|
thold_legend();
|
|
|
|
print '</div>';
|
|
|
|
// thold_display_rusage();
|
|
}
|
|
|
|
/**
|
|
* Builds a clickable status "pill" for a device-status-list row, using a
|
|
* CSS class derived from the host's disabled flag, current status, and
|
|
* (when a per-host failure-count override is set) whether its
|
|
* consecutive down-event count has reached that threshold. The pill's
|
|
* data-state maps to the Device Status filter so clicking it filters the
|
|
* list to that status.
|
|
*
|
|
* @param array &$host The host record to build the status pill for.
|
|
*
|
|
* @return string The status pill markup.
|
|
*
|
|
* @global array $thold_host_states Map of status/state key => display
|
|
* info (including 'class') used to pick
|
|
* the pill's colour class.
|
|
*/
|
|
function thold_device_status_pill(&$host) {
|
|
global $thold_host_states;
|
|
|
|
$status = $host['status'];
|
|
|
|
if ($host['disabled']) {
|
|
$key = 'disabled';
|
|
} elseif ($host['thold_failure_count'] > 0 && $status != HOST_RECOVERING && $host['status_event_count'] >= $host['thold_failure_count']) {
|
|
$key = HOST_DOWN;
|
|
} elseif (isset($thold_host_states[$status])) {
|
|
$key = $status;
|
|
} else {
|
|
$key = HOST_UNKNOWN;
|
|
}
|
|
|
|
// Each state maps to its matching Device Status filter (host_status) value.
|
|
$state_map = [
|
|
HOST_DOWN => '1',
|
|
HOST_RECOVERING => '2',
|
|
HOST_UP => '3',
|
|
HOST_UNKNOWN => '0',
|
|
HOST_ERROR => '4',
|
|
'disabled' => '-2'
|
|
];
|
|
|
|
$state = isset($state_map[$key]) ? $state_map[$key] : '-1';
|
|
|
|
return "<span class='thold-pill " . $thold_host_states[$key]['class'] . "' data-state='" . $state . "' tabindex='0' role='button'>" . html_escape(get_uncolored_device_status($host)) . '</span>';
|
|
}
|
|
|
|
/**
|
|
* Determines a human-readable status label for a host (Disabled, Down,
|
|
* Recovering, Up, Error, or Unknown), applying the same per-host
|
|
* failure-count override logic as thold_device_status_pill() but
|
|
* without any HTML/color output.
|
|
*
|
|
* @param array &$host The host record to determine the status label
|
|
* for.
|
|
*
|
|
* @return string The human-readable, translated status label.
|
|
*/
|
|
function get_uncolored_device_status(&$host) {
|
|
$disabled = $host['disabled'];
|
|
$status = $host['status'];
|
|
|
|
if ($disabled) {
|
|
return __('Disabled', 'thold');
|
|
} else {
|
|
if ($host['thold_failure_count'] > 0 && $host['status'] != HOST_RECOVERING) {
|
|
if ($host['status_event_count'] >= $host['thold_failure_count']) {
|
|
return __('Down', 'thold');
|
|
}
|
|
}
|
|
|
|
switch ($status) {
|
|
case HOST_DOWN:
|
|
return __('Down', 'thold');
|
|
|
|
break;
|
|
case HOST_RECOVERING:
|
|
return __('Recovering', 'thold');
|
|
|
|
break;
|
|
case HOST_UP:
|
|
return __('Up', 'thold');
|
|
|
|
break;
|
|
case HOST_ERROR:
|
|
return __('Error', 'thold');
|
|
|
|
break;
|
|
default:
|
|
return __('Unknown', 'thold');
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Renders the device status list view: validates/stores this view's
|
|
* filter request variables, displays the host filter form, then
|
|
* displays a filtered, sorted, paginated table of hosts with their
|
|
* current up/down/recovering status. Called from this script's main
|
|
* request-dispatch switch when action=hoststat.
|
|
*
|
|
* @return void
|
|
*
|
|
* @global array $config Cacti global configuration array.
|
|
* @global array $device_actions Map of drp_action value => action
|
|
* label, used for the bulk-actions
|
|
* dropdown.
|
|
* @global array $item_rows Default number of rows per page from
|
|
* Cacti settings.
|
|
*/
|
|
function hosts() {
|
|
global $config, $device_actions, $item_rows;
|
|
|
|
// ================= input validation and session storage =================
|
|
$filters = [
|
|
'rows' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
],
|
|
'page' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'default' => '1'
|
|
],
|
|
'rfilter' => [
|
|
'filter' => FILTER_VALIDATE_IS_REGEX,
|
|
'pageset' => true,
|
|
'default' => ''
|
|
],
|
|
'sort_column' => [
|
|
'filter' => FILTER_CALLBACK,
|
|
'default' => 'description',
|
|
'options' => ['options' => 'sanitize_thold_sort_string']
|
|
],
|
|
'sort_direction' => [
|
|
'filter' => FILTER_CALLBACK,
|
|
'default' => 'ASC',
|
|
'options' => ['options' => 'sanitize_search_string']
|
|
],
|
|
'site_id' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
],
|
|
'host_template_id' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
],
|
|
'host_status' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-4'
|
|
]
|
|
];
|
|
|
|
validate_store_request_vars($filters, 'sess_thold_hstatus');
|
|
// ================= input validation =================
|
|
|
|
// if the number of rows is -1, set it to the default
|
|
if (get_request_var('rows') == -1) {
|
|
$rows = read_config_option('num_rows_table');
|
|
} else {
|
|
$rows = get_request_var('rows');
|
|
}
|
|
|
|
html_start_box(__('Device Status', 'thold'), '100%', false, '3', 'center', '');
|
|
form_host_filter();
|
|
html_end_box();
|
|
|
|
// form the 'where' clause for our main sql query
|
|
$sql_where = '';
|
|
|
|
if (get_request_var('rfilter') != '') {
|
|
$sql_where .= " (h.deleted = ''
|
|
AND (h.hostname " . thold_rlike_clause(get_request_var('rfilter')) . '
|
|
OR h.description ' . thold_rlike_clause(get_request_var('rfilter')) . ')';
|
|
}
|
|
|
|
if (get_request_var('host_status') == '-1') {
|
|
// Show all items
|
|
} elseif (get_request_var('host_status') == '-2') {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . "h.disabled = 'on'";
|
|
} elseif (get_request_var('host_status') == '-3') {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . "h.disabled = ''";
|
|
} elseif (get_request_var('host_status') == '-4') {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . "(h.status != '3' OR h.disabled = 'on')";
|
|
} elseif (get_request_var('host_status') == '-5') {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . '(h.availability_method = 0)';
|
|
} else {
|
|
// Match the exact state-classification rules used by thold_device_status_pill():
|
|
// a per-host failure-count override (status_event_count >= thold_failure_count, excluding
|
|
// Recovering) reclassifies the device as Down, so the Down filter includes those hosts and
|
|
// the Up/Unknown/Error filters exclude them.
|
|
$override_down = 'h.thold_failure_count > 0 AND h.status != ' . HOST_RECOVERING . ' AND h.status_event_count >= h.thold_failure_count';
|
|
|
|
if (get_request_var('host_status') == HOST_DOWN) {
|
|
$status_clause = '(h.status = ' . HOST_DOWN . " OR ($override_down))";
|
|
} elseif (get_request_var('host_status') == HOST_RECOVERING) {
|
|
$status_clause = 'h.status = ' . HOST_RECOVERING;
|
|
} else {
|
|
$status_clause = 'h.status = ' . get_request_var('host_status') . " AND NOT ($override_down)";
|
|
}
|
|
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . "(h.availability_method != 0 AND h.disabled = '' AND $status_clause)";
|
|
}
|
|
|
|
if (get_request_var('host_template_id') == '-1') {
|
|
// Show all items
|
|
} elseif (get_request_var('host_template_id') == '0') {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . 'h.host_template_id = 0';
|
|
} elseif (!isempty_request_var('host_template_id')) {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . 'h.host_template_id = ' . get_request_var('host_template_id');
|
|
}
|
|
|
|
if (get_request_var('site_id') == '-1') {
|
|
// Show all items
|
|
} elseif (get_request_var('site_id') == '0') {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . 'h.site_id = 0';
|
|
} elseif (!isempty_request_var('site_id')) {
|
|
$sql_where .= ($sql_where == '' ? '(' : ' AND ') . 'h.site_id = ' . get_request_var('site_id');
|
|
}
|
|
|
|
$sql_where .= ($sql_where != '' ? ')' : '');
|
|
|
|
$sql_order = get_order_string();
|
|
$sql_limit = ($rows * (intval(get_request_var('page')) - 1)) . ',' . $rows;
|
|
$sql_order = str_replace('ORDER BY ', '', $sql_order);
|
|
|
|
$hosts = thold_get_allowed_devices($sql_where, $sql_order, $sql_limit, $total_rows);
|
|
|
|
$nav = html_nav_bar('thold_graph.php?action=hoststat', MAX_DISPLAY_PAGES, get_request_var('page'), $rows, $total_rows, 12, __('Devices', 'thold'), 'page', 'main');
|
|
|
|
print $nav;
|
|
|
|
html_start_box('', '100%', false, '3', 'center', '');
|
|
|
|
$display_text = [
|
|
'nosort' => [
|
|
'display' => __('Actions', 'thold'),
|
|
'align' => 'left',
|
|
'sort' => '',
|
|
'tip' => __('Hover over icons for help', 'thold')
|
|
],
|
|
'description' => [
|
|
'display' => __('Description', 'thold'),
|
|
'align' => 'left',
|
|
'sort' => 'ASC',
|
|
'tip' => __('A description for the Device', 'thold')
|
|
],
|
|
'id' => [
|
|
'display' => __('ID', 'thold'),
|
|
'align' => 'right',
|
|
'sort' => 'ASC',
|
|
'tip' => __('A Cacti unique identifier for the Device', 'thold')
|
|
],
|
|
'graphs' => [
|
|
'display' => __('Graphs', 'thold'),
|
|
'align' => 'right',
|
|
'sort' => 'ASC',
|
|
'tip' => __('The number of Graphs for this Device', 'thold')
|
|
],
|
|
'data_sources' => [
|
|
'display' => __('Data Sources', 'thold'),
|
|
'align' => 'right',
|
|
'sort' => 'ASC',
|
|
'tip' => __('The number of Data Sources for this Device', 'thold')
|
|
],
|
|
'status' => [
|
|
'display' => __('Status', 'thold'),
|
|
'align' => 'center',
|
|
'sort' => 'ASC',
|
|
'tip' => __('The status for this Device as of the last time it was polled', 'thold')
|
|
],
|
|
'instate' => [
|
|
'display' => __('In State', 'thold'),
|
|
'align' => 'right',
|
|
'sort' => 'ASC',
|
|
'tip' => __('The last time Cacti found an issue with this Device. It can be higher than the Uptime for the Device, if it was rebooted between Cacti polling cycles', 'thold')
|
|
],
|
|
'snmp_sysUpTimeInstance' => [
|
|
'display' => __('Uptime', 'thold'),
|
|
'align' => 'right',
|
|
'sort' => 'ASC',
|
|
'tip' => __('The official uptime of the Device as reported by SNMP', 'thold')
|
|
],
|
|
'hostname' => [
|
|
'display' => __('Hostname', 'thold'),
|
|
'align' => 'right',
|
|
'sort' => 'ASC',
|
|
'tip' => __('The official hostname for this Device', 'thold')
|
|
],
|
|
'cur_time' => [
|
|
'display' => __('Current (ms)', 'thold'),
|
|
'align' => 'right',
|
|
'sort' => 'DESC',
|
|
'tip' => __('The current response time for the Cacti Availability check', 'thold')
|
|
],
|
|
'avg_time' => [
|
|
'display' => __('Average (ms)', 'thold'),
|
|
'align' => 'right',
|
|
'sort' => 'DESC',
|
|
'tip' => __('The average response time for the Cacti Availability check', 'thold')
|
|
],
|
|
'availability' => [
|
|
'display' => __('Availability', 'thold'),
|
|
'align' => 'right',
|
|
'sort' => 'ASC',
|
|
'tip' => __('The overall Availability of this Device since the last counter reset in Cacti', 'thold')
|
|
]
|
|
];
|
|
|
|
html_header_sort($display_text, get_request_var('sort_column'), get_request_var('sort_direction'), false, 'thold_graph.php?action=hoststat');
|
|
|
|
if (cacti_sizeof($hosts)) {
|
|
foreach ($hosts as $host) {
|
|
if ($host['disabled'] == '' &&
|
|
($host['status'] == HOST_RECOVERING || $host['status'] == HOST_UP) &&
|
|
($host['availability_method'] != AVAIL_NONE && $host['availability_method'] != AVAIL_PING)) {
|
|
$snmp_uptime = $host['snmp_sysUpTimeInstance'];
|
|
$days = intval($snmp_uptime / (60 * 60 * 24 * 100));
|
|
$remainder = $snmp_uptime % (60 * 60 * 24 * 100);
|
|
$hours = intval($remainder / (60 * 60 * 100));
|
|
$remainder = $remainder % (60 * 60 * 100);
|
|
$minutes = intval($remainder / (60 * 100));
|
|
$uptime = $days . 'd:' . substr('00' . $hours, -2) . 'h:' . substr('00' . $minutes, -2) . 'm';
|
|
} else {
|
|
$uptime = __('N/A', 'thold');
|
|
}
|
|
|
|
if ($host['availability_method'] != 0) {
|
|
print "<tr class='tableRow selectable' id='line" . $host['id'] . "'>";
|
|
|
|
$actions_url = '';
|
|
|
|
if (api_user_realm_auth('host.php')) {
|
|
$actions_url .= '<a href="' . html_escape($config['url_path'] . 'host.php?action=edit&id=' . $host['id']) . '" title="' . __esc('Edit Device', 'thold') . '"><i class="tholdGlyphEdit fas fa-wrench"></i></a>';
|
|
}
|
|
$actions_url .= "<a href='" . html_escape($config['url_path'] . 'graph_view.php?action=preview&reset=true&host_id=' . $host['id']) . "' title='" . __esc('View Graphs', 'thold') . "'><i class='tholdGlyphChart fas fa-chart-area'></i></a>";
|
|
|
|
form_selectable_cell($actions_url, $host['id'], '', 'left');
|
|
|
|
form_selectable_cell(filter_value($host['description'], get_request_var('rfilter')), $host['id'], '', 'left');
|
|
|
|
form_selectable_cell(number_format_i18n($host['id'], -1), $host['id'], '', 'right');
|
|
form_selectable_cell(number_format_i18n($host['graphs'], -1), $host['id'], '', 'right');
|
|
form_selectable_cell(number_format_i18n($host['data_sources'], -1), $host['id'], '', 'right');
|
|
|
|
form_selectable_cell(thold_device_status_pill($host), $host['id'], '', 'center');
|
|
|
|
form_selectable_cell(get_timeinstate($host), $host['id'], '', 'right');
|
|
form_selectable_cell($uptime, $host['id'], '', 'right');
|
|
form_selectable_cell(filter_value($host['hostname'], get_request_var('rfilter')), $host['id'], '', 'right');
|
|
form_selectable_cell(number_format_i18n(($host['cur_time']), 2), $host['id'], '', 'right');
|
|
form_selectable_cell(number_format_i18n(($host['avg_time']), 2), $host['id'], '', 'right');
|
|
form_selectable_cell(number_format_i18n($host['availability'], 2), $host['id'], '', 'right');
|
|
} else {
|
|
print "<tr class='tableRow selectable' id='line" . $host['id'] . "'>";
|
|
|
|
$actions_url = '';
|
|
|
|
if (api_user_realm_auth('host.php')) {
|
|
$actions_url .= '<a href="' . html_escape($config['url_path'] . 'host.php?action=edit&id=' . $host['id']) . '" title="' . __esc('Edit Device', 'thold') . '"><i class="tholdGlyphEdit fas fa-wrench"></i></a>';
|
|
}
|
|
$actions_url .= "<a href='" . html_escape($config['url_path'] . 'graph_view.php?action=preview&reset=true&host_id=' . $host['id']) . "' title='" . __esc('View Graphs', 'thold') . "'><i class='tholdGlyphChart fas fa-chart-area'></i></a>";
|
|
|
|
form_selectable_cell($actions_url, $host['id'], '', 'left');
|
|
|
|
form_selectable_cell(filter_value($host['description'], get_request_var('rfilter')), $host['id'], '', 'left');
|
|
|
|
form_selectable_cell(number_format_i18n($host['id'], -1), $host['id'], '', 'right');
|
|
form_selectable_cell(number_format_i18n($host['graphs'], -1), $host['id'], '', 'right');
|
|
form_selectable_cell(number_format_i18n($host['data_sources'], -1), $host['id'], '', 'right');
|
|
|
|
form_selectable_cell("<span class='thold-pill deviceNotMonFull' data-state='-5' tabindex='0' role='button'>" . __esc('Not Monitored', 'thold') . '</span>', $host['id'], '', 'center');
|
|
|
|
form_selectable_cell(__('N/A', 'thold'), $host['id'], '', 'right');
|
|
form_selectable_cell($uptime, $host['id'], '', 'right');
|
|
form_selectable_cell(filter_value($host['hostname'], get_request_var('rfilter')), $host['id'], '', 'right');
|
|
form_selectable_cell(__('N/A', 'thold'), $host['id'], '', 'right');
|
|
form_selectable_cell(__('N/A', 'thold'), $host['id'], '', 'right');
|
|
form_selectable_cell(__('N/A', 'thold'), $host['id'], '', 'right');
|
|
}
|
|
|
|
form_end_row();
|
|
}
|
|
} else {
|
|
print '<tr class="tableRow"><td class="center" colspan="12">' . __('No Devices', 'thold') . '</td></tr>';
|
|
}
|
|
|
|
html_end_box(false);
|
|
|
|
if (cacti_sizeof($hosts)) {
|
|
print $nav;
|
|
}
|
|
|
|
print '<div class="center tholdLegendFooter">';
|
|
|
|
host_legend();
|
|
|
|
print '</div>';
|
|
|
|
// thold_display_rusage();
|
|
}
|
|
|
|
/**
|
|
* Renders the search/site filter form controls for the device status
|
|
* list view.
|
|
*
|
|
* @return void
|
|
*
|
|
* @global array $item_rows Rows-per-page option list used to populate
|
|
* the rows dropdown.
|
|
* @global array $config Cacti global configuration array (declared
|
|
* but not used directly here).
|
|
*/
|
|
function form_host_filter() {
|
|
global $item_rows, $config;
|
|
|
|
?>
|
|
<tr class='even'>
|
|
<td>
|
|
<form id='form_devices' action='thold_graph.php?action=hoststat'>
|
|
<table class='filterTable'>
|
|
<tr>
|
|
<td>
|
|
<?php print __('Search', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<input type='text' id='rfilter' size='30' value='<?php print html_escape_request_var('rfilter'); ?>'>
|
|
</td>
|
|
<td>
|
|
<?php print __('Site', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='site_id'>
|
|
<option value='-1'<?php if (get_request_var('site_id') == '-1') {?> selected<?php }?>><?php print __('All', 'thold'); ?></option>
|
|
<option value='0'<?php if (get_request_var('site_id') == '0') {?> selected<?php }?>><?php print __('None', 'thold'); ?></option>
|
|
<?php
|
|
$sites = db_fetch_assoc('SELECT id, name
|
|
FROM sites
|
|
ORDER BY name');
|
|
|
|
if (cacti_sizeof($sites)) {
|
|
foreach ($sites as $site) {
|
|
print "<option value='" . $site['id'] . "'";
|
|
|
|
if (get_request_var('site_id') == $site['id']) {
|
|
print ' selected';
|
|
} print '>' . html_escape($site['name']) . '</option>';
|
|
}
|
|
}
|
|
?>
|
|
</select>
|
|
</td>
|
|
<td>
|
|
<?php print __('Status', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='host_status'>
|
|
<option value='-1'<?php if (get_request_var('host_status') == '-1') {?> selected<?php }?>><?php print __('All', 'thold'); ?></option>
|
|
<option value='-3'<?php if (get_request_var('host_status') == '-3') {?> selected<?php }?>><?php print __('Enabled', 'thold'); ?></option>
|
|
<?php print(read_user_setting('hide_disabled') == '' ? "<option value='-2'" . (get_request_var('host_status') == '-2' ? ' selected' : '') . "'>" . __('Disabled', 'thold') . '</option>' : ''); ?>
|
|
<option value='-4'<?php if (get_request_var('host_status') == '-4') {?> selected<?php }?>><?php print __('Not Up', 'thold'); ?></option>
|
|
<option value='-5'<?php if (get_request_var('host_status') == '-5') {?> selected<?php }?>><?php print __('Not Monitored', 'thold'); ?></option>
|
|
<option value='3'<?php if (get_request_var('host_status') == '3') {?> selected<?php }?>><?php print __('Up', 'thold'); ?></option>
|
|
<option value='1'<?php if (get_request_var('host_status') == '1') {?> selected<?php }?>><?php print __('Down', 'thold'); ?></option>
|
|
<option value='2'<?php if (get_request_var('host_status') == '2') {?> selected<?php }?>><?php print __('Recovering', 'thold'); ?></option>
|
|
<option value='0'<?php if (get_request_var('host_status') == '0') {?> selected<?php }?>><?php print __('Unknown', 'thold'); ?></option>
|
|
<option value='4'<?php if (get_request_var('host_status') == '4') {?> selected<?php }?>><?php print __('Error', 'thold'); ?></option>
|
|
</select>
|
|
</td>
|
|
<td>
|
|
<span>
|
|
<input id='refresh' type='submit' value='<?php print __esc('Go', 'thold'); ?>'>
|
|
<input id='clear' type='button' value='<?php print __esc('Clear', 'thold'); ?>'>
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<table class='filterTable'>
|
|
<tr>
|
|
<td>
|
|
<?php print __('Type', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='host_template_id'>
|
|
<option value='-1'<?php if (get_request_var('host_template_id') == '-1') {?> selected<?php }?>><?php print __('All', 'thold'); ?></option>
|
|
<option value='0'<?php if (get_request_var('host_template_id') == '0') {?> selected<?php }?>><?php print __('None', 'thold'); ?></option>
|
|
<?php
|
|
$host_templates = db_fetch_assoc('SELECT id, name
|
|
FROM host_template
|
|
ORDER BY name');
|
|
|
|
if (cacti_sizeof($host_templates)) {
|
|
foreach ($host_templates as $host_template) {
|
|
print "<option value='" . $host_template['id'] . "'";
|
|
|
|
if (get_request_var('host_template_id') == $host_template['id']) {
|
|
print ' selected';
|
|
} print '>' . html_escape($host_template['name']) . '</option>';
|
|
}
|
|
}
|
|
?>
|
|
</select>
|
|
</td>
|
|
<td>
|
|
<?php print __('Devices', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='rows'>
|
|
<option value='-1'<?php if (get_request_var('rows') == '-1') {?> selected<?php }?>><?php print __('Default', 'thold'); ?></option>
|
|
<?php
|
|
if (cacti_sizeof($item_rows)) {
|
|
foreach ($item_rows as $key => $value) {
|
|
print "<option value='" . $key . "'";
|
|
|
|
if (get_request_var('rows') == $key) {
|
|
print ' selected';
|
|
} print '>' . $value . '</option>';
|
|
}
|
|
}
|
|
?>
|
|
</select>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<input type='hidden' name='page' value='<?php print html_escape(get_request_var('page')); ?>'>
|
|
<input type='hidden' name='tab' value='hoststat'>
|
|
</form>
|
|
<script type='text/javascript' <?php print plugin_thold_csp_nonce(); ?>>
|
|
|
|
function applyFilter() {
|
|
strURL = 'thold_graph.php?header=false&action=hoststat';
|
|
strURL += '&host_status=' + encodeURIComponent($('#host_status').val());
|
|
strURL += '&host_template_id=' + encodeURIComponent($('#host_template_id').val());
|
|
strURL += '&site_id=' + encodeURIComponent($('#site_id').val());
|
|
strURL += '&rows=' + encodeURIComponent($('#rows').val());
|
|
strURL += '&rfilter=' + encodeURIComponent(base64_encode($('#rfilter').val()));
|
|
loadPageNoHeader(strURL);
|
|
}
|
|
|
|
function clearFilter() {
|
|
strURL = 'thold_graph.php?header=false&action=hoststat&clear=1';
|
|
loadPageNoHeader(strURL);
|
|
}
|
|
|
|
$(function() {
|
|
$('#form_devices').submit(function(event) {
|
|
event.preventDefault();
|
|
applyFilter();
|
|
});
|
|
|
|
$('#site_id, #host_status, #host_template_id, #rows').change(function() {
|
|
applyFilter();
|
|
});
|
|
|
|
$('.thold-pill').on('click keydown', function(e) {
|
|
if (e.type === 'keydown' && e.which !== 13 && e.which !== 32) {
|
|
return;
|
|
}
|
|
|
|
e.preventDefault();
|
|
var state = $(this).attr('data-state');
|
|
$('#host_status').val($('#host_status').val() === state ? '-1' : state);
|
|
applyFilter();
|
|
});
|
|
|
|
$('#clear').click(function() {
|
|
clearFilter();
|
|
});
|
|
});
|
|
|
|
</script>
|
|
</td>
|
|
</tr>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Validates and stores this view's filter request variables (rows,
|
|
* page, filter text, sort column/direction, threshold id, threshold
|
|
* template id, host id, site id, status) into the session for the
|
|
* threshold log list view.
|
|
*
|
|
* @return void
|
|
*/
|
|
function thold_validate_log_vars() {
|
|
// ================= input validation and session storage =================
|
|
$filters = [
|
|
'rows' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
],
|
|
'page' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'default' => '1'
|
|
],
|
|
'rfilter' => [
|
|
'filter' => FILTER_VALIDATE_IS_REGEX,
|
|
'pageset' => true,
|
|
'default' => ''
|
|
],
|
|
'sort_column' => [
|
|
'filter' => FILTER_CALLBACK,
|
|
'default' => 'time',
|
|
'options' => ['options' => 'sanitize_thold_sort_string']
|
|
],
|
|
'sort_direction' => [
|
|
'filter' => FILTER_CALLBACK,
|
|
'default' => 'DESC',
|
|
'options' => ['options' => 'sanitize_search_string']
|
|
],
|
|
'threshold_id' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
],
|
|
'thold_template_id' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
],
|
|
'host_id' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
],
|
|
'site_id' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
],
|
|
'status' => [
|
|
'filter' => FILTER_VALIDATE_INT,
|
|
'pageset' => true,
|
|
'default' => '-1'
|
|
]
|
|
];
|
|
|
|
validate_store_request_vars($filters, 'sess_thold_log');
|
|
// ================= input validation =================
|
|
}
|
|
|
|
/**
|
|
* Exports the current filtered threshold log entries (up to 100000
|
|
* rows) as a downloaded CSV file. Called from this script's main
|
|
* request-dispatch switch when action=logexport.
|
|
*
|
|
* @return void
|
|
*/
|
|
function thold_export_log() {
|
|
$sql_where = '';
|
|
|
|
thold_validate_log_vars();
|
|
|
|
if (get_request_var('host_id') == '-1') {
|
|
// Show all items
|
|
} elseif (get_request_var('host_id') == '0') {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.id IS NULL';
|
|
} elseif (!isempty_request_var('host_id')) {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' tl.host_id=' . get_request_var('host_id');
|
|
}
|
|
|
|
if (get_request_var('site_id') == '-1') {
|
|
// Show all items
|
|
} elseif (get_request_var('site_id') == '0') {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.site_id IS NULL';
|
|
} elseif (!isempty_request_var('site_id')) {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.site_id=' . get_request_var('site_id');
|
|
}
|
|
|
|
if (get_request_var('threshold_id') == '-1') {
|
|
// Show all items
|
|
} elseif (get_request_var('threshold_id') == '0') {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' td.id IS NULL';
|
|
} elseif (get_request_var('threshold_id') > 0) {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' td.id=' . get_request_var('threshold_id');
|
|
}
|
|
|
|
// thold template id filter
|
|
if (!isempty_request_var('thold_template_id')) {
|
|
if (get_request_var('thold_template_id') > 0) {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND ') . '(td.thold_template_id = ' . get_request_var('thold_template_id') . ' AND td.template_enabled = "on")';
|
|
} elseif (get_request_var('thold_template_id') == '-2') {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND ') . '(td.template_enabled != "on")';
|
|
}
|
|
}
|
|
|
|
if (get_request_var('status') != '-1') {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' tl.status=' . get_request_var('status');
|
|
}
|
|
|
|
if (get_request_var('rfilter') != '') {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' tl.description ' . thold_rlike_clause(get_request_var('rfilter'));
|
|
}
|
|
|
|
$sql_order = '';
|
|
$total_rows = 0;
|
|
|
|
$logs = get_allowed_threshold_logs($sql_where, $sql_order, 100000, $total_rows);
|
|
|
|
if (sizeof($logs)) {
|
|
$columns = array_keys($logs[0]);
|
|
header('Content-type: application/csv');
|
|
header('Content-Disposition: attachment; filename=thold_log_export.csv');
|
|
|
|
print implode(',', $columns) . PHP_EOL;
|
|
|
|
foreach ($logs as $log) {
|
|
print implode(',', array_values($log)) . PHP_EOL;
|
|
}
|
|
} else {
|
|
raise_message('norows', __('No Export Rows Found.', 'thold'), MESSAGE_LEVEL_ERROR);
|
|
header('Location: thold_graph.php?action=log');
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Renders the main threshold log list page: validates/stores this
|
|
* view's filter request variables, displays the log filter form, then
|
|
* displays a filtered, sorted, paginated table of threshold log
|
|
* entries. Called from this script's main request-dispatch switch when
|
|
* action=log.
|
|
*
|
|
* @return void
|
|
*
|
|
* @global array $config Cacti global configuration
|
|
* array.
|
|
* @global array $item_rows Default number of rows per page
|
|
* from Cacti settings.
|
|
* @global array $thold_log_states Log status option list used by
|
|
* the filter form.
|
|
* @global array $thold_status Reserved/declared for parity with
|
|
* other functions in this file; not
|
|
* used directly here.
|
|
* @global array $thold_types Map of log entry type id => label,
|
|
* used to render each log row's
|
|
* type column ('Acknowledgment'
|
|
* added here for type 99).
|
|
* @global int $thold_log_retention Reserved/declared for parity with
|
|
* other functions in this file; not
|
|
* used directly here.
|
|
*/
|
|
function thold_show_log() {
|
|
global $config, $item_rows, $thold_log_states, $thold_status, $thold_types, $thold_log_retention;
|
|
|
|
thold_validate_log_vars();
|
|
|
|
// if the number of rows is -1, set it to the default
|
|
if (get_request_var('rows') == -1) {
|
|
$rows = read_config_option('num_rows_table');
|
|
} else {
|
|
$rows = get_request_var('rows');
|
|
}
|
|
|
|
$days = read_config_option('thold_log_storage');
|
|
|
|
if (empty($days)) {
|
|
set_config_option('thold_log_storage', '31');
|
|
|
|
$days = 31;
|
|
}
|
|
|
|
$days = __('%d Days', $days, 'thold');
|
|
|
|
html_start_box(__('Threshold Log for [ %s ]', $days, 'thold'), '100%', false, '3', 'center', '');
|
|
form_thold_log_filter();
|
|
html_end_box();
|
|
|
|
$sql_where = '';
|
|
|
|
if (get_request_var('host_id') == '-1') {
|
|
// Show all items
|
|
} elseif (get_request_var('host_id') == '0') {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.id IS NULL';
|
|
} elseif (!isempty_request_var('host_id')) {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' tl.host_id = ' . get_request_var('host_id');
|
|
}
|
|
|
|
if (get_request_var('site_id') == '-1') {
|
|
// Show all items
|
|
} elseif (get_request_var('site_id') == '0') {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.site_id IS NULL';
|
|
} elseif (!isempty_request_var('site_id')) {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.site_id = ' . get_request_var('site_id');
|
|
}
|
|
|
|
if (get_request_var('threshold_id') == '-1') {
|
|
// Show all items
|
|
} elseif (get_request_var('threshold_id') == '0') {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' td.id IS NULL';
|
|
} elseif (get_request_var('threshold_id') > 0) {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' td.id = ' . get_request_var('threshold_id');
|
|
}
|
|
|
|
// thold template id filter
|
|
if (!isempty_request_var('thold_template_id')) {
|
|
if (get_request_var('thold_template_id') > 0) {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND ') . '(td.thold_template_id = ' . get_request_var('thold_template_id') . ' AND td.template_enabled = "on")';
|
|
} elseif (get_request_var('thold_template_id') == '-2') {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND ') . '(td.template_enabled != "on")';
|
|
}
|
|
}
|
|
|
|
if (get_request_var('status') != '-1') {
|
|
if (get_request_var('status') == 2) {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' tl.status IN (2,8)';
|
|
} else {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' tl.status = ' . get_request_var('status');
|
|
}
|
|
}
|
|
|
|
if (get_request_var('rfilter') != '') {
|
|
$sql_where .= ($sql_where == '' ? '' : ' AND') . ' tl.description ' . thold_rlike_clause(get_request_var('rfilter'));
|
|
}
|
|
|
|
$sql_order = get_order_string();
|
|
$sql_limit = ($rows * (intval(get_request_var('page')) - 1)) . ',' . $rows;
|
|
$sql_order = str_replace('ORDER BY ', '', $sql_order);
|
|
|
|
$logs = get_allowed_threshold_logs($sql_where, $sql_order, $sql_limit, $total_rows);
|
|
|
|
$nav = html_nav_bar('thold_graph.php?action=log', MAX_DISPLAY_PAGES, get_request_var('page'), $rows, $total_rows, 9, __('Log Entries', 'thold'), 'page', 'main');
|
|
|
|
print $nav;
|
|
|
|
html_start_box('', '100%', false, '3', 'center', '');
|
|
|
|
$display_text = [
|
|
'hdescription' => [
|
|
'display' => __('Device', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'left'
|
|
],
|
|
'time' => [
|
|
'display' => __('Time', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'left'
|
|
],
|
|
'type' => [
|
|
'display' => __('Type', 'thold'),
|
|
'sort' => 'DESC',
|
|
'align' => 'left'
|
|
],
|
|
'status' => [
|
|
'display' => __('Status', 'thold'),
|
|
'sort' => '',
|
|
'align' => 'left'
|
|
],
|
|
'description' => [
|
|
'display' => __('Event Description', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'left'
|
|
],
|
|
'threshold_value' => [
|
|
'display' => __('Alert Value', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'right'
|
|
],
|
|
'current' => [
|
|
'display' => __('Measured Value', 'thold'),
|
|
'sort' => 'ASC',
|
|
'align' => 'right'
|
|
]
|
|
];
|
|
|
|
html_header_sort($display_text, get_request_var('sort_column'), get_request_var('sort_direction'), false, 'thold_graph.php?action=log');
|
|
|
|
$thold_types[99] = __('Acknowledgment', 'thold');
|
|
|
|
if (cacti_sizeof($logs)) {
|
|
foreach ($logs as $l) {
|
|
if ($l['status'] == 8) {
|
|
$l['status'] = 2;
|
|
}
|
|
|
|
$baseu = db_fetch_cell_prepared('SELECT base_value
|
|
FROM graph_templates_graph
|
|
WHERE local_graph_id = ?',
|
|
[$l['local_graph_id']]);
|
|
|
|
$data_type = db_fetch_cell_prepared('SELECT data_type FROM thold_data WHERE id = ?', [$l['threshold_id']]);
|
|
|
|
if ($data_type == 2) {
|
|
$suffix = false;
|
|
} else {
|
|
$suffix = true;
|
|
}
|
|
|
|
$show_units = (db_fetch_cell_prepared('SELECT show_units FROM thold_data WHERE id = ?', [$l['threshold_id']]) ? true : false);
|
|
$units_suffix = db_fetch_cell_prepared('SELECT units_suffix FROM thold_data WHERE id = ?', [$l['threshold_id']]);
|
|
$decimals = db_fetch_cell_prepared('SELECT decimals FROM thold_data WHERE id = ?', [$l['threshold_id']]);
|
|
|
|
if (empty($baseu)) {
|
|
cacti_log('WARNING: Graph Template for local_graph_id ' . $l['local_graph_id'] . ' has been removed!');
|
|
$baseu = 1024;
|
|
}
|
|
|
|
print "<tr class='tableRow selectable' id='line" . $l['id'] . "'>";
|
|
|
|
form_selectable_cell($l['hdescription'], $l['id'], '', 'left');
|
|
form_selectable_cell(date('Y-m-d H:i:s', $l['time']), $l['id'], '', 'left');
|
|
form_selectable_cell($thold_types[$l['type']], $l['id'], '', 'left');
|
|
form_selectable_cell("<span class='thold-pill " . $thold_log_states[$l['status']]['class'] . "' data-state='" . $l['status'] . "' tabindex='0' role='button'>" . html_escape($thold_log_states[$l['status']]['display_short']) . '</span>', $l['id'], '', 'left');
|
|
form_selectable_cell((strlen($l['description']) ? filter_value($l['description'], get_request_var('rfilter')) : __('Restoral Event', 'thold')), $l['id'], '', 'left tholdLog');
|
|
form_selectable_cell($l['threshold_value'] != '' ? thold_format_number($l['threshold_value'], $decimals, $baseu, $suffix, $show_units, $units_suffix) : __('N/A', 'thold'), $l['id'], '', 'right');
|
|
form_selectable_cell($l['current'] != '' ? thold_format_number($l['current'], $decimals, $baseu, $suffix, $show_units, $units_suffix) : __('N/A', 'thold'), $l['id'], '', 'right');
|
|
form_end_row();
|
|
}
|
|
} else {
|
|
print '<tr class="tableRow"><td class="center" colspan="9">' . __('No Threshold Logs Found', 'thold') . '</td></tr>';
|
|
}
|
|
|
|
html_end_box(false);
|
|
|
|
if (cacti_sizeof($logs)) {
|
|
print $nav;
|
|
}
|
|
|
|
print '<div class="center tholdLegendFooter">';
|
|
|
|
log_legend();
|
|
|
|
print '</div>';
|
|
}
|
|
|
|
/**
|
|
* Renders the search/site/status/host/template filter form controls for
|
|
* the threshold log list view.
|
|
*
|
|
* @return void
|
|
*
|
|
* @global array $item_rows Rows-per-page option list used to
|
|
* populate the rows dropdown.
|
|
* @global array $thold_log_states Log status option list used to
|
|
* populate the status dropdown.
|
|
* @global array $config Cacti global configuration array
|
|
* (declared but not used directly
|
|
* here).
|
|
*/
|
|
function form_thold_log_filter() {
|
|
global $item_rows, $thold_log_states, $config;
|
|
|
|
?>
|
|
<tr class='even'>
|
|
<td>
|
|
<form id='form_log' action='thold_graph.php?action=log'>
|
|
<table class='filterTable'>
|
|
<tr>
|
|
<td>
|
|
<?php print __('Search', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<input type='text' id='rfilter' size='30' value='<?php print html_escape_request_var('rfilter'); ?>'>
|
|
</td>
|
|
<td>
|
|
<?php print __('Site', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='site_id'>
|
|
<option value='-1'<?php if (get_request_var('site_id') == '-1') {?> selected<?php }?>><?php print __('All', 'thold'); ?></option>
|
|
<option value='0'<?php if (get_request_var('site_id') == '0') {?> selected<?php }?>><?php print __('None', 'thold'); ?></option>
|
|
<?php
|
|
$sites = db_fetch_assoc('SELECT id, name
|
|
FROM sites
|
|
ORDER BY name');
|
|
|
|
if (cacti_sizeof($sites)) {
|
|
foreach ($sites as $site) {
|
|
print "<option value='" . $site['id'] . "'";
|
|
|
|
if (get_request_var('site_id') == $site['id']) {
|
|
print ' selected';
|
|
} print '>' . html_escape($site['name']) . '</option>';
|
|
}
|
|
}
|
|
?>
|
|
</select>
|
|
</td>
|
|
<?php print html_host_filter(get_request_var('host_id')); ?>
|
|
<td>
|
|
<span>
|
|
<input id='refresh' type='submit' value='<?php print __esc('Go', 'thold'); ?>'>
|
|
<input id='clear' type='button' value='<?php print __esc('Clear', 'thold'); ?>'>
|
|
<input id='export' type='button' value='<?php print __esc('Export', 'thold'); ?>'>
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<table class='filterTable'>
|
|
<tr>
|
|
<td>
|
|
<?php print __('Template', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='thold_template_id'>
|
|
<option value='-1'<?php if (get_request_var('thold_template_id') == '-1') {?> selected<?php }?>><?php print __('All', 'thold'); ?></option>
|
|
<option value='-2'<?php if (get_request_var('thold_template_id') == '-2') {?> selected<?php }?>><?php print __('None', 'thold'); ?></option>
|
|
<?php
|
|
$thold_templates = db_fetch_assoc('SELECT DISTINCT tt.id, tt.name
|
|
FROM thold_template as tt
|
|
ORDER BY tt.name');
|
|
|
|
foreach ($thold_templates as $row) {
|
|
print "<option value='" . $row['id'] . "'" . (isset_request_var('thold_template_id') && $row['id'] == get_request_var('thold_template_id') ? ' selected' : '') . '>' . html_escape($row['name']) . '</option>';
|
|
}
|
|
?>
|
|
</select>
|
|
</td>
|
|
<td>
|
|
<?php print __('Threshold', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='threshold_id'>
|
|
<option value='-1'<?php if (get_request_var('threshold_id') == '-1') {?> selected<?php }?>><?php print __('All'); ?></option>
|
|
<?php
|
|
$tholds = db_fetch_assoc('SELECT DISTINCT td.id, td.name_cache
|
|
FROM thold_data AS td
|
|
INNER JOIN plugin_thold_log AS tl
|
|
ON td.id = tl.threshold_id ' .
|
|
(get_request_var('host_id') > 0 ? 'WHERE td.host_id=' . get_request_var('host_id') : '') .
|
|
' ORDER by td.name_cache');
|
|
|
|
if (cacti_sizeof($tholds)) {
|
|
foreach ($tholds as $thold) {
|
|
print "<option value='" . $thold['id'] . "'";
|
|
|
|
if (get_request_var('threshold_id') == $thold['id']) {
|
|
print ' selected';
|
|
} print '>' . html_escape($thold['name_cache']) . '</option>';
|
|
}
|
|
}
|
|
?>
|
|
</select>
|
|
</td>
|
|
<td>
|
|
<?php print __('Status', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='status'>
|
|
<option value='-1'<?php if (get_request_var('status') == '-1') {?> selected<?php }?>><?php print __('All', 'thold'); ?></option>
|
|
<?php
|
|
if (cacti_sizeof($thold_log_states)) {
|
|
foreach ($thold_log_states as $key => $value) {
|
|
print "<option value='" . $key . "'";
|
|
|
|
if (get_request_var('status') == $key) {
|
|
print ' selected';
|
|
} print '>' . html_escape($value['display']) . '</option>';
|
|
}
|
|
}
|
|
?>
|
|
</select>
|
|
</td>
|
|
<td>
|
|
<?php print __('Entries', 'thold'); ?>
|
|
</td>
|
|
<td>
|
|
<select id='rows'>
|
|
<option value='-1'<?php if (get_request_var('rows') == '-1') {?> selected<?php }?>><?php print __('Default', 'thold'); ?></option>
|
|
<?php
|
|
if (cacti_sizeof($item_rows)) {
|
|
foreach ($item_rows as $key => $value) {
|
|
print "<option value='" . $key . "'";
|
|
|
|
if (get_request_var('rows') == $key) {
|
|
print ' selected';
|
|
} print '>' . $value . '</option>';
|
|
}
|
|
}
|
|
?>
|
|
</select>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<input type='hidden' name='tab' value='log'>
|
|
</form>
|
|
<script type='text/javascript' <?php print plugin_thold_csp_nonce(); ?>>
|
|
|
|
function applyFilter() {
|
|
strURL = 'thold_graph.php?header=false&action=log';
|
|
strURL += '&status=' + encodeURIComponent($('#status').val());
|
|
strURL += '&threshold_id=' + encodeURIComponent($('#threshold_id').val());
|
|
strURL += '&thold_template_id=' + encodeURIComponent($('#thold_template_id').val());
|
|
strURL += '&host_id=' + encodeURIComponent($('#host_id').val());
|
|
strURL += '&site_id=' + encodeURIComponent($('#site_id').val());
|
|
strURL += '&rows=' + encodeURIComponent($('#rows').val());
|
|
strURL += '&rfilter=' + encodeURIComponent(base64_encode($('#rfilter').val()));
|
|
loadPageNoHeader(strURL);
|
|
}
|
|
|
|
function clearFilter() {
|
|
strURL = 'thold_graph.php?header=false&action=log&clear=1';
|
|
loadPageNoHeader(strURL);
|
|
}
|
|
|
|
function exportLog() {
|
|
strURL = 'thold_graph.php?action=exportlog';
|
|
strURL += '&status=' + encodeURIComponent($('#status').val());
|
|
strURL += '&threshold_id=' + encodeURIComponent($('#threshold_id').val());
|
|
strURL += '&thold_template_id=' + encodeURIComponent($('#thold_template_id').val());
|
|
strURL += '&host_id=' + encodeURIComponent($('#host_id').val());
|
|
strURL += '&site_id=' + encodeURIComponent($('#site_id').val());
|
|
strURL += '&rows=' + encodeURIComponent($('#rows').val());
|
|
strURL += '&rfilter=' + encodeURIComponent(base64_encode($('#rfilter').val()));
|
|
document.location = strURL;
|
|
Pace.stop();
|
|
}
|
|
|
|
$(function() {
|
|
$('#form_log').submit(function(event) {
|
|
event.preventDefault();
|
|
applyFilter();
|
|
});
|
|
|
|
$('#site_id, #thold_template_id, #threshold_id, #status, #rows').change(function() {
|
|
applyFilter();
|
|
});
|
|
|
|
$('.thold-pill').on('click keydown', function(e) {
|
|
if (e.type === 'keydown' && e.which !== 13 && e.which !== 32) {
|
|
return;
|
|
}
|
|
|
|
e.preventDefault();
|
|
var state = $(this).attr('data-state');
|
|
$('#status').val($('#status').val() === state ? '-1' : state);
|
|
applyFilter();
|
|
});
|
|
|
|
$('#clear').click(function() {
|
|
clearFilter();
|
|
});
|
|
|
|
$('#export').click(function() {
|
|
exportLog();
|
|
});
|
|
});
|
|
|
|
</script>
|
|
</td>
|
|
</tr>
|
|
<?php
|
|
}
|