Files
TheWitness 6bbfb58492 Fit status pills to label text and toggle-clear the status filter on second click (#854)
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).
2026-10-09 09:32:34 -04:00

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
}