mirror of
https://github.com/librenms/librenms.git
synced 2024-09-21 10:28:13 +00:00
Added support for allowing alerts to un-ack (#9136)
* Add support for allowing alerts to un-ack * Updated db_schema.yaml * Update and rename 263.sql to 265.sql * Fix up ui a bit. * Renamed sql file
This commit is contained in:
parent
7682093fd0
commit
86d862fb25
@ -44,6 +44,8 @@ Acknowledge an alert
|
||||
Route: `/api/v0/alerts/:id`
|
||||
|
||||
- id is the alert id, you can obtain a list of alert ids from [`list_alerts`](#function-list_alerts).
|
||||
- note is the note to add to the alert
|
||||
- until_clear is a boolean and if set to false, the alert will re-alert if it worsens/betters.
|
||||
|
||||
Input:
|
||||
|
||||
|
34
doc/Alerting/Introduction.md
Normal file
34
doc/Alerting/Introduction.md
Normal file
@ -0,0 +1,34 @@
|
||||
source: Alerting/Introduction.md
|
||||
|
||||
# Introduction
|
||||
|
||||
To get started, you first need some alert rules which will react to changes with your devices before raising an alert.
|
||||
|
||||
[Creating alert rules](Rules.md)
|
||||
|
||||
After that you also need to tell LibreNMS how to notify you when an alert is raised, this is done using `Alert Transports`.
|
||||
|
||||
[Configuring alert transports](Transports.md)
|
||||
|
||||
The next step is not strictly required but most people find it useful. Creating custom alert templates will help you get
|
||||
the benefit out of the alert system in general. Whilst we include a default template, it is limited in the data that you
|
||||
will receive in the alerts.
|
||||
|
||||
[Configuring alert templates](Templates.md)
|
||||
|
||||
### Managing alerts
|
||||
|
||||
When an alert has triggered you will see these in the Alerts -> Notifications page within the Web UI.
|
||||
|
||||
This list has a couple of options available to it and we'll explain what these are here.
|
||||
|
||||
#### ACK
|
||||
This column provides you visibility on the status of the alert:
|
||||
![ack alert](img/ack.png) This alert is currently active and sending alerts. Click this icon to acknowledge the alert.
|
||||
![unack alert](img/unack.png) This alert is currently acknowledged until the alert clears. Click this icon to un-acknowledge the alert.
|
||||
![unack alert until fault worsens](img/nunack.png) This alert is currently acknowledged until the alert worsens or gets
|
||||
better, at which stage it will be automatically unacknowledged and alerts will resume. Click this icon to un-acknowledge the alert.
|
||||
|
||||
#### Notes
|
||||
This column will allow you access to the acknowledge/unacknowledge notes for this alert.
|
||||
![alert notes](img/notes.png)
|
BIN
doc/Alerting/img/ack.png
Normal file
BIN
doc/Alerting/img/ack.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
BIN
doc/Alerting/img/notes.png
Normal file
BIN
doc/Alerting/img/notes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.6 KiB |
BIN
doc/Alerting/img/nunack.png
Normal file
BIN
doc/Alerting/img/nunack.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
BIN
doc/Alerting/img/unack.png
Normal file
BIN
doc/Alerting/img/unack.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
@ -9,6 +9,7 @@ The system requires a set of user-defined rules to evaluate the situation of eac
|
||||
|
||||
Table of Content:
|
||||
|
||||
- [Introduction](Introduction.md)
|
||||
- [Rules](Rules.md)
|
||||
- [Syntax](Rules.md#syntax)
|
||||
- [Options](Rules.md#options)
|
||||
|
@ -12,8 +12,9 @@
|
||||
* the source code distribution for details.
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\LegacyAuth;
|
||||
use LibreNMS\Alerting\QueryBuilderParser;
|
||||
use LibreNMS\Authentication\LegacyAuth;
|
||||
use LibreNMS\Config;
|
||||
|
||||
function authToken(\Slim\Route $route)
|
||||
{
|
||||
@ -1185,15 +1186,27 @@ function delete_rule()
|
||||
function ack_alert()
|
||||
{
|
||||
check_is_admin();
|
||||
global $config;
|
||||
|
||||
$app = \Slim\Slim::getInstance();
|
||||
$router = $app->router()->getCurrentRoute()->getParams();
|
||||
$alert_id = mres($router['id']);
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (!is_numeric($alert_id)) {
|
||||
api_error(400, 'Invalid alert has been provided');
|
||||
}
|
||||
if (dbUpdate(array('state' => 2), 'alerts', '`id` = ? LIMIT 1', array($alert_id))) {
|
||||
|
||||
$alert = dbFetchRow('SELECT note, info FROM alerts WHERE id=?', [$alert_id]);
|
||||
$note = $alert['note'];
|
||||
$info = json_decode($alert['info'], true);
|
||||
if (!empty($note)) {
|
||||
$note .= PHP_EOL;
|
||||
}
|
||||
$note .= date(Config::get('dateformat.long')) . " - Ack (" . Auth::user()->username . ") {$data['note']}";
|
||||
$info['until_clear'] = $data['until_clear'];
|
||||
$info = json_encode($info);
|
||||
|
||||
if (dbUpdate(['state' => 2, 'note' => $note, 'info' => $info], 'alerts', '`id` = ? LIMIT 1', [$alert_id])) {
|
||||
api_success_noresult(200, 'Alert has been acknowledged');
|
||||
} else {
|
||||
api_success_noresult(200, 'No Alert by that ID');
|
||||
@ -1203,16 +1216,25 @@ function ack_alert()
|
||||
function unmute_alert()
|
||||
{
|
||||
check_is_admin();
|
||||
global $config;
|
||||
|
||||
$app = \Slim\Slim::getInstance();
|
||||
$router = $app->router()->getCurrentRoute()->getParams();
|
||||
$alert_id = mres($router['id']);
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (!is_numeric($alert_id)) {
|
||||
api_success_noresult(200, 'Alert has been acknowledged');
|
||||
api_error(400, 'Invalid alert has been provided');
|
||||
}
|
||||
|
||||
if (dbUpdate(array('state' => 1), 'alerts', '`id` = ? LIMIT 1', array($alert_id))) {
|
||||
$alert = dbFetchRow('SELECT note, info FROM alerts WHERE id=?', [$alert_id]);
|
||||
$note = $alert['note'];
|
||||
$info = json_decode($alert['info'], true);
|
||||
if (!empty($note)) {
|
||||
$note .= PHP_EOL;
|
||||
}
|
||||
$note .= date(Config::get('dateformat.long')) . " - Ack (" . Auth::user()->username . ") {$data['note']}";
|
||||
|
||||
if (dbUpdate(['state' => 1, 'note' => $note], 'alerts', '`id` = ? LIMIT 1', [$alert_id])) {
|
||||
api_success_noresult(200, 'Alert has been unmuted');
|
||||
} else {
|
||||
api_success_noresult(200, 'No alert by that ID');
|
||||
|
@ -306,36 +306,11 @@ var alerts_grid = $("#alerts_' . $unique_id . '").bootgrid({
|
||||
alerts_grid.find(".command-ack-alert").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
var alert_state = $(this).data("alert_state");
|
||||
if (alert_state != 2) {
|
||||
var ack_msg = window.prompt("Enter the reason you are acknowledging this alert:");
|
||||
} else {
|
||||
var ack_msg = "";
|
||||
}
|
||||
if (typeof ack_msg == "string") {
|
||||
var alert_id = $(this).data("alert_id");
|
||||
var state = $(this).data("state");
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "ajax_form.php",
|
||||
dataType: "json",
|
||||
data: { type: "ack-alert", alert_id: alert_id, state: state, ack_msg: ack_msg },
|
||||
success: function (data) {
|
||||
if (data.status == "ok") {
|
||||
toastr.success(data.message);
|
||||
$(".alerts").each(function(index) {
|
||||
var $sortDictionary = $(this).bootgrid("getSortDictionary");
|
||||
$(this).reload;
|
||||
$(this).bootgrid("sort", $sortDictionary);
|
||||
});
|
||||
} else {
|
||||
toastr.error(data.message);
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
toastr.error(data.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
var alert_id = $(this).data(\'alert_id\');
|
||||
$(\'#ack_alert_id\').val(alert_id);
|
||||
$(\'#ack_alert_state\').val(alert_state);
|
||||
$(\'#ack_msg\').val(\'\');
|
||||
$("#alert_ack_modal").modal(\'show\');
|
||||
});
|
||||
alerts_grid.find(".command-alert-note").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
|
@ -28,9 +28,10 @@ use LibreNMS\Config;
|
||||
|
||||
header('Content-type: application/json');
|
||||
|
||||
$alert_id = $vars['alert_id'];
|
||||
$state = $vars['state'];
|
||||
$ack_msg = $vars['ack_msg'];
|
||||
$alert_id = $vars['alert_id'];
|
||||
$state = $vars['state'];
|
||||
$ack_msg = $vars['ack_msg'];
|
||||
$until_clear = $vars['ack_until_clear'];
|
||||
|
||||
$status = 'error';
|
||||
|
||||
@ -49,16 +50,31 @@ if (!is_numeric($alert_id)) {
|
||||
$open = 1;
|
||||
}
|
||||
|
||||
if ($until_clear === 'true') {
|
||||
$until_clear = true;
|
||||
} else {
|
||||
$until_clear = false;
|
||||
}
|
||||
|
||||
$info = json_encode([
|
||||
'until_clear' => $until_clear,
|
||||
]);
|
||||
|
||||
$username = LegacyAuth::user()->username;
|
||||
$data = ['state' => $state, 'open' => $open];
|
||||
$data = [
|
||||
'state' => $state,
|
||||
'open' => $open,
|
||||
'info' => $info,
|
||||
];
|
||||
|
||||
$note = dbFetchCell('SELECT note FROM alerts WHERE id=?', [$alert_id]);
|
||||
if (!empty($note)) {
|
||||
$note .= PHP_EOL;
|
||||
}
|
||||
$data['note'] = $note . date(Config::get('dateformat.long')) . " - $state_descr ($username) $ack_msg";
|
||||
|
||||
if (dbUpdate($data, 'alerts', 'id=?', array($alert_id)) >= 0) {
|
||||
if ($state === 2) {
|
||||
if (dbUpdate($data, 'alerts', 'id=?', [$alert_id]) >= 0) {
|
||||
if (in_array($state, [2, 22])) {
|
||||
$alert_info = dbFetchRow("SELECT `alert_rules`.`name`,`alerts`.`device_id` FROM `alert_rules` LEFT JOIN `alerts` ON `alerts`.`rule_id` = `alert_rules`.`id` WHERE `alerts`.`id` = ?", [$alert_id]);
|
||||
log_event("$username acknowledged alert {$alert_info['name']}", $alert_info['device_id'], 'alert', 2, $alert_id);
|
||||
}
|
||||
|
80
html/includes/modal/alert_ack.inc.php
Normal file
80
html/includes/modal/alert_ack.inc.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Config;
|
||||
|
||||
?>
|
||||
<form class="form-horizontal">
|
||||
<div class="modal fade" id="alert_ack_modal" tabindex="-1" role="dialog" aria-labelledby="alert_notes" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h5 class="modal-title" id="alert_notes">Acknowledge Alert</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class='form-group'>
|
||||
<label for='ack_msg' class='col-sm-4 col-md-3 control-label' title="Add a message to the acknowledgement">(Un)Acknowledgement note: </label>
|
||||
<div class="col-sm-8 col-md-9">
|
||||
<input type='text' id='ack_msg' name='ack_msg' class='form-control' autofocus>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="ack_section">
|
||||
<label for="ack_until_clear" class="col-sm-4 col-md-3 control-label" title="Acknowledge until alert clears">Acknowledge until clear:</label>
|
||||
<div class="col-sm-8 col-md-9">
|
||||
<input type='checkbox' name='ack_until_clear' id='ack_until_clear'>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-4 col-md-offset-3 col-sm-3 col-md-2">
|
||||
<input type="hidden" id="ack_alert_id" name="ack_alert_id" value="">
|
||||
<input type="hidden" id="ack_alert_state" name="ack_alert_state" value="">
|
||||
<button class="btn btn-success" id="ack-alert" name="ack-alert">Ack alert</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
$('#alert_ack_modal').on('show.bs.modal', function () {
|
||||
if ($("#ack_alert_state").val() == 2) {
|
||||
var button_label = 'Un-acknowledge alert';
|
||||
$('#ack_section').hide();
|
||||
} else {
|
||||
var button_label = 'Acknowledge alert';
|
||||
$('#ack_section').show();
|
||||
}
|
||||
document.getElementById('ack-alert').innerText = button_label;
|
||||
$("#ack_until_clear").bootstrapSwitch('state', <?php echo Config::get('alert.ack_until_clear') ? 'true' : 'false'; ?>);
|
||||
});
|
||||
$("#ack-alert").click('', function(event) {
|
||||
event.preventDefault();
|
||||
var ack_alert_id = $("#ack_alert_id").val();
|
||||
var ack_alert_note = $('#ack_msg').val();
|
||||
var ack_alert_state = $("#ack_alert_state").val();
|
||||
var ack_until_clear = $("#ack_until_clear").bootstrapSwitch('state');
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "ajax_form.php",
|
||||
dataType: "json",
|
||||
data: { type: "ack-alert", alert_id: ack_alert_id, state: ack_alert_state, ack_msg: ack_alert_note, ack_until_clear: ack_until_clear },
|
||||
success: function (data) {
|
||||
if (data.status === "ok") {
|
||||
toastr.success(data.message);
|
||||
var $table = $('table.alerts');
|
||||
var sortDictionary = $table.bootgrid("getSortDictionary");
|
||||
$table.bootgrid('reload');
|
||||
$table.bootgrid("sort", sortDictionary);
|
||||
$("#alert_ack_modal").modal('hide');
|
||||
} else {
|
||||
toastr.error(data.message);
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
toastr.error(data.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
@ -124,25 +124,28 @@ $format = $vars['format'];
|
||||
foreach (dbFetchRows($sql, $param) as $alert) {
|
||||
$log = dbFetchCell('SELECT details FROM alert_log WHERE rule_id = ? AND device_id = ? ORDER BY id DESC LIMIT 1', array($alert['rule_id'], $alert['device_id']));
|
||||
$fault_detail = alert_details($log);
|
||||
$info = json_decode($alert['info'], true);
|
||||
|
||||
$alert_to_ack = '<button type="button" class="btn btn-danger command-ack-alert fa fa-eye" aria-hidden="true" title="Mark as acknowledged" data-target="ack-alert" data-state="' . $alert['state'] . '" data-alert_id="' . $alert['id'] . '" data-alert_state="' . $alert['state'] . '" name="ack-alert"></button>';
|
||||
$alert_to_nack = '<button type="button" class="btn btn-primary command-ack-alert fa fa-eye-slash" aria-hidden="true" title="Mark as not acknowledged" data-target="ack-alert" data-state="' . $alert['state'] . '" data-alert_id="' . $alert['id'] . '" data-alert_state="' . $alert['state'] . '" name="ack-alert"></button>';
|
||||
$alert_to_ack = '<button type="button" class="btn btn-danger command-ack-alert fa fa-eye" aria-hidden="true" title="Mark as acknowledged" data-target="ack-alert" data-state="' . $alert['state'] . '" data-alert_id="' . $alert['id'] . '" data-alert_state="' . $alert['state'] . '" name="ack-alert"></button>';
|
||||
$alert_to_nack = '<button type="button" class="btn btn-primary command-ack-alert fa fa-eye-slash" aria-hidden="true" title="Mark as not acknowledged" data-target="ack-alert" data-state="' . $alert['state'] . '" data-alert_id="' . $alert['id'] . '" data-alert_state="' . $alert['state'] . '" name="ack-alert"></button>';
|
||||
$alert_to_unack = '<button type="button" class="btn btn-primary command-ack-alert fa fa-eye" aria-hidden="true" title="Mark as not acknowledged" data-target="ack-alert" data-state="' . $alert['state'] . '" data-alert_id="' . $alert['id'] . '" data-alert_state="' . $alert['state'] . '" name="ack-alert"></button>';
|
||||
|
||||
$ack_ico = $alert_to_ack;
|
||||
|
||||
if ((int)$alert['state'] === 0) {
|
||||
$ico = '';
|
||||
$msg = '';
|
||||
} elseif ((int)$alert['state'] === 1 || (int)$alert['state'] === 3 || (int)$alert['state'] === 4) {
|
||||
$ico = $alert_to_ack;
|
||||
if ((int)$alert['state'] === 3) {
|
||||
$msg = '<i class="fa fa-angle-double-down" style="font-size:20px;" aria-hidden="true" title="Status got worse"></i>';
|
||||
} elseif ((int)$alert['state'] === 4) {
|
||||
$msg = '<i class="fa fa-angle-double-up" style="font-size:20px;" aria-hidden="true" title="Status got better"></i>';
|
||||
}
|
||||
} elseif ((int)$alert['state'] === 2) {
|
||||
$ico = $alert_to_nack;
|
||||
$ack_ico = $alert_to_nack;
|
||||
if ($info['until_clear'] === false) {
|
||||
$ack_ico = $alert_to_unack;
|
||||
} else {
|
||||
$ack_ico = $alert_to_nack;
|
||||
}
|
||||
}
|
||||
|
||||
$severity = $alert['severity'];
|
||||
|
@ -24,6 +24,7 @@ $page_title = 'Alerts';
|
||||
<?php
|
||||
$device['device_id'] = '-1';
|
||||
require_once 'includes/modal/alert_notes.inc.php';
|
||||
require_once 'includes/modal/alert_ack.inc.php';
|
||||
require_once 'includes/common/alerts.inc.php';
|
||||
echo implode('', $common_output);
|
||||
unset($device['device_id']);
|
||||
|
@ -12,5 +12,6 @@
|
||||
* the source code distribution for details.
|
||||
*/
|
||||
require_once 'includes/modal/alert_notes.inc.php';
|
||||
require_once 'includes/modal/alert_ack.inc.php';
|
||||
require_once 'includes/common/alerts.inc.php';
|
||||
echo implode('', $common_output);
|
||||
|
@ -22,6 +22,7 @@ $no_refresh = true;
|
||||
$default_dash = get_user_pref('dashboard', 0);
|
||||
|
||||
require_once 'includes/modal/alert_notes.inc.php';
|
||||
require_once 'includes/modal/alert_ack.inc.php';
|
||||
|
||||
// get all dashboards this user can access and put them into two lists user_dashboards and shared_dashboards
|
||||
$dashboards = get_dashboards();
|
||||
|
@ -329,6 +329,11 @@ $general_conf = array(
|
||||
'descr' => 'Updates to contact email addresses not honored',
|
||||
'type' => 'checkbox',
|
||||
),
|
||||
[
|
||||
'name' => 'alert.ack_until_clear',
|
||||
'descr' => 'Default acknowledge until alert clears option',
|
||||
'type' => 'checkbox',
|
||||
]
|
||||
);
|
||||
|
||||
$mail_conf = array(
|
||||
|
@ -634,44 +634,51 @@ function RunAcks()
|
||||
*/
|
||||
function RunFollowUp()
|
||||
{
|
||||
foreach (loadAlerts('alerts.state != 2 && alerts.state > 0 && alerts.open = 0') as $alert) {
|
||||
$rextra = json_decode($alert['extra'], true);
|
||||
if ($rextra['invert']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($alert['query'])) {
|
||||
$alert['query'] = GenSQL($alert['rule'], $alert['builder']);
|
||||
}
|
||||
$chk = dbFetchRows($alert['query'], array($alert['device_id']));
|
||||
//make sure we can json_encode all the datas later
|
||||
$cnt = count($chk);
|
||||
for ($i = 0; $i < $cnt; $i++) {
|
||||
if (isset($chk[$i]['ip'])) {
|
||||
$chk[$i]['ip'] = inet6_ntop($chk[$i]['ip']);
|
||||
}
|
||||
}
|
||||
$o = sizeof($alert['details']['rule']);
|
||||
$n = sizeof($chk);
|
||||
$ret = 'Alert #'.$alert['id'];
|
||||
$state = 0;
|
||||
if ($n > $o) {
|
||||
$ret .= ' Worsens';
|
||||
$state = 3;
|
||||
$alert['details']['diff'] = array_diff($chk, $alert['details']['rule']);
|
||||
} elseif ($n < $o) {
|
||||
$ret .= ' Betters';
|
||||
$state = 4;
|
||||
$alert['details']['diff'] = array_diff($alert['details']['rule'], $chk);
|
||||
}
|
||||
|
||||
if ($state > 0 && $n > 0) {
|
||||
$alert['details']['rule'] = $chk;
|
||||
if (dbInsert(array('state' => $state, 'device_id' => $alert['device_id'], 'rule_id' => $alert['rule_id'], 'details' => gzcompress(json_encode($alert['details']), 9)), 'alert_log')) {
|
||||
dbUpdate(array('state' => $state, 'open' => 1, 'alerted' => 1), 'alerts', 'rule_id = ? && device_id = ?', array($alert['rule_id'], $alert['device_id']));
|
||||
foreach (loadAlerts('alerts.state > 0 && alerts.open = 0') as $alert) {
|
||||
if ($alert['state'] != 2 || ($alert['info']['until_clear'] === false)) {
|
||||
$rextra = json_decode($alert['extra'], true);
|
||||
if ($rextra['invert']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
echo $ret.' ('.$o.'/'.$n.")\r\n";
|
||||
if (empty($alert['query'])) {
|
||||
$alert['query'] = GenSQL($alert['rule'], $alert['builder']);
|
||||
}
|
||||
$chk = dbFetchRows($alert['query'], array($alert['device_id']));
|
||||
//make sure we can json_encode all the datas later
|
||||
$cnt = count($chk);
|
||||
for ($i = 0; $i < $cnt; $i++) {
|
||||
if (isset($chk[$i]['ip'])) {
|
||||
$chk[$i]['ip'] = inet6_ntop($chk[$i]['ip']);
|
||||
}
|
||||
}
|
||||
$o = sizeof($alert['details']['rule']);
|
||||
$n = sizeof($chk);
|
||||
$ret = 'Alert #' . $alert['id'];
|
||||
$state = 0;
|
||||
if ($n > $o) {
|
||||
$ret .= ' Worsens';
|
||||
$state = 3;
|
||||
$alert['details']['diff'] = array_diff($chk, $alert['details']['rule']);
|
||||
} elseif ($n < $o) {
|
||||
$ret .= ' Betters';
|
||||
$state = 4;
|
||||
$alert['details']['diff'] = array_diff($alert['details']['rule'], $chk);
|
||||
}
|
||||
|
||||
if ($state > 0 && $n > 0) {
|
||||
$alert['details']['rule'] = $chk;
|
||||
if (dbInsert(array(
|
||||
'state' => $state,
|
||||
'device_id' => $alert['device_id'],
|
||||
'rule_id' => $alert['rule_id'],
|
||||
'details' => gzcompress(json_encode($alert['details']), 9)
|
||||
), 'alert_log')) {
|
||||
dbUpdate(array('state' => $state, 'open' => 1, 'alerted' => 1), 'alerts', 'rule_id = ? && device_id = ?', array($alert['rule_id'], $alert['device_id']));
|
||||
}
|
||||
|
||||
echo $ret . ' (' . $o . '/' . $n . ")\r\n";
|
||||
}
|
||||
}
|
||||
}//end foreach
|
||||
}//end RunFollowUp()
|
||||
@ -679,7 +686,7 @@ function RunFollowUp()
|
||||
function loadAlerts($where)
|
||||
{
|
||||
$alerts = [];
|
||||
foreach (dbFetchRows("SELECT alerts.id, alerts.device_id, alerts.rule_id, alerts.state, alerts.note FROM alerts WHERE $where") as $alert_status) {
|
||||
foreach (dbFetchRows("SELECT alerts.id, alerts.device_id, alerts.rule_id, alerts.state, alerts.note, alerts.info FROM alerts WHERE $where") as $alert_status) {
|
||||
$alert = dbFetchRow(
|
||||
'SELECT alert_log.id,alert_log.rule_id,alert_log.device_id,alert_log.state,alert_log.details,alert_log.time_logged,alert_rules.rule,alert_rules.severity,alert_rules.extra,alert_rules.name,alert_rules.builder FROM alert_log,alert_rules WHERE alert_log.rule_id = alert_rules.id && alert_log.device_id = ? && alert_log.rule_id = ? && alert_rules.disabled = 0 ORDER BY alert_log.id DESC LIMIT 1',
|
||||
array($alert_status['device_id'], $alert_status['rule_id'])
|
||||
@ -696,6 +703,7 @@ function loadAlerts($where)
|
||||
if (!empty($alert['details'])) {
|
||||
$alert['details'] = json_decode(gzuncompress($alert['details']), true);
|
||||
}
|
||||
$alert['info'] = json_decode($alert_status['info'], true);
|
||||
$alerts[] = $alert;
|
||||
}
|
||||
}
|
||||
@ -760,7 +768,7 @@ function RunAlerts()
|
||||
}
|
||||
}
|
||||
|
||||
if ($alert['state'] == 1 && !empty($rextra['count']) && ($rextra['count'] == -1 || $alert['details']['count']++ < $rextra['count'])) {
|
||||
if (in_array($alert['state'], [1,3,4]) && !empty($rextra['count']) && ($rextra['count'] == -1 || $alert['details']['count']++ < $rextra['count'])) {
|
||||
if ($alert['details']['count'] < $rextra['count']) {
|
||||
$noacc = true;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ alerts:
|
||||
- { Field: open, Type: int(11), 'Null': false, Extra: '' }
|
||||
- { Field: note, Type: text, 'Null': true, Extra: '' }
|
||||
- { Field: timestamp, Type: timestamp, 'Null': false, Extra: 'on update CURRENT_TIMESTAMP', Default: CURRENT_TIMESTAMP }
|
||||
- { Field: info, Type: text, 'Null': false, Extra: '' }
|
||||
Indexes:
|
||||
PRIMARY: { Name: PRIMARY, Columns: [id], Unique: true, Type: BTREE }
|
||||
unique_alert: { Name: unique_alert, Columns: [device_id, rule_id], Unique: true, Type: BTREE }
|
||||
|
@ -104,6 +104,7 @@ pages:
|
||||
- API/Logs.md
|
||||
- 8. Alerting:
|
||||
- Intro: Alerting/index.md
|
||||
- Alerting/Introduction.md
|
||||
- Alerting/Rules.md
|
||||
- Alerting/Templates.md
|
||||
- Alerting/Transports.md
|
||||
|
2
sql-schema/268.sql
Normal file
2
sql-schema/268.sql
Normal file
@ -0,0 +1,2 @@
|
||||
ALTER TABLE `alerts` ADD `info` TEXT NOT NULL;
|
||||
INSERT INTO `config` (`config_name`, `config_value`, `config_default`, `config_descr`, `config_group`, `config_group_order`, `config_sub_group`, `config_sub_group_order`, `config_hidden`, `config_disabled`) VALUES('alert.ack_until_clear', 'false', 'false', 'Default acknowledge until alert clears', 'alerting', 0, 'general', 0, '0', '0');
|
Loading…
Reference in New Issue
Block a user