feature: Added new alert rule builder UI and rule mapping UI (#8293)

* feature: Added new alert rule builder UI

* Updated to export sql queries

* More updates

* more changes

* removed debug

* fix scrut

* Updated to include import options + various other fixes

* fix rule

* Populate name from collection rules.

* Fix default rule import
Allow new and old style rules in the collection.
Don't add new yet as I'm not sure GenSQL() is working.

* Fix GenSQL call

* Extract filter building to class so it is nicely contained in one place

* moved schema

* some fixes and tweaks

* travis fixes

* Some more features / updates

* Fix up my mistakes when adding default rules

* Use a modal for new alert (Incomplete)
Larger dialog!!
Remove page loading stuff.

Working:
Loading rules, resetting dialog, importing from collection.

Not working yet:
select width
device limited rule access? don't know what this is...

Lots of unused stuff to delete...

* reload "table" after save

* fixed editing rule

* Auto select2 width

* Reload window on save

* Restore per-device alert. Remove debug.

* Small cleanups. Rule Name first.

* Restore button to button type. Rename schema.

* Fixes: wrong command to reload window, remove extra attributes, rule is never passed

* Fixed old rule editing

* some small updates for old imports

* travis update to use trusty

* maybe travis fix

* Ability to set alert rule mappings on the rule edit screen

* pip installs one line, no quiet for deploy

* update schema def

* Fix style and some copyright headers

* fix docs missing file

* Allow new versions of snmpsim and libraries

* Parser WIP

* Fix default rules insert

* reorganize

* Legacy import first draft done

* Implement saving
Skip translation to sql for now

* Working on glues

* small rule collection fix

* Working on glues

* Working on glues

* Docs updates + small UI changes

* Parser WIP

* reorganize

* Legacy import first draft done

* Implement saving
Skip translation to sql for now

* Working on glues

* Working on glues

* Working on glues

* Add table mapping, should move to it's own class

* WIP

* Glue working!!

* Extract Schema class

* Some final touches.
revert alerts_rules.json for now.

* Finish up initial implementation
Needs more tests

* Fix a few places

* small doc updates

* Fix finding tables in grouped rules.

* remove unused code

* code format fixes

* Some quick tests for Schema
Simplified output for findRelationshipPath. Always includes start and target in the result.
This simplifies a lot of code in QueryBuilderParser.php
This also always loads the target table data now (which we want)

* Make bill_id the PRIMARY index for the bills table

* Load macros from a json file in misc instead of the database.

* Fix whitespace and wrong key for collection.

* Handle IN properly when generating SQL

* Fix glue (devices.device_id = ports.port_id) is incorrect :D
Show ALL tables we can resolve relationships for in the query builder filter.

* Remove all macros from the database
Remove insert statements, leave updates to update user's existing rules.
This commit is contained in:
Neil Lathwood
2018-03-14 20:25:19 +00:00
committed by GitHub
parent ba4c86f4c0
commit 03076c4025
67 changed files with 2263 additions and 1107 deletions

View File

@@ -1,5 +1,7 @@
<?php
use LibreNMS\Alerting\QueryBuilderParser;
$no_refresh = true;
?>
@@ -23,27 +25,27 @@ if (isset($_POST['create-default'])) {
'interval' => 300,
);
require_once '../includes/alerts.inc.php';
foreach ($default_rules as $add_rule) {
$extra = $default_extra;
if (isset($add_rule['extra'])) {
$extra = array_replace($extra, json_decode($add_rule['extra'], true));
}
$qb = QueryBuilderParser::fromOld($add_rule['rule']);
$insert = array(
'device_id' => -1,
'rule' => $add_rule['rule'],
'query' => GenSQL($add_rule['rule']),
'severity' => 'critical',
'extra' => json_encode($extra),
'disabled' => 0,
'name' => $add_rule['name']
'rule' => '',
'builder' => json_encode($qb),
'query' => $qb->toSql(),
'severity' => 'critical',
'extra' => json_encode($extra),
'disabled' => 0,
'name' => $add_rule['name']
);
dbInsert($insert, 'alert_rules');
}
}//end if
unset($qb);
}
require_once 'includes/modal/new_alert_rule.inc.php';
require_once 'includes/modal/delete_alert_rule.inc.php';
@@ -67,11 +69,11 @@ echo '<div class="table-responsive">
<th>Status</th>
<th>Extra</th>
<th>Enabled</th>
<th>Action</th>
<th style="width:86px;">Action</th>
</tr>';
echo '<td colspan="7">';
if ($_SESSION['userlevel'] >= '10') {
if (is_admin()) {
echo '<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#create-alert" data-device_id="'.$device['device_id'].'"><i class="fa fa-plus"></i> Create new alert rule</button>';
echo '<i> - OR - </i>';
echo '<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#search_rule_modal" data-device_id="'.$device['device_id'].'"><i class="fa fa-plus"></i> Create rule from collection</button>';
@@ -98,26 +100,24 @@ foreach ($result_options as $option) {
echo '</select></td>';
$count_query = 'SELECT COUNT(*)';
$full_query = 'SELECT *';
$sql = '';
$param = array();
$query = 'FROM alert_rules';
$where = '';
$param = [];
if (isset($device['device_id']) && $device['device_id'] > 0) {
$sql = 'WHERE (device_id=? OR device_id="-1")';
$param = array($device['device_id']);
$query .= ' LEFT JOIN alert_device_map ON alert_rules.id=alert_device_map.rule_id';
$where = 'WHERE (device_id=? OR device_id IS NULL)';
$param[] = $device['device_id'];
}
$query = " FROM alert_rules $sql";
$count_query = $count_query.$query;
$count = dbFetchCell($count_query, $param);
if (!isset($_POST['page_number']) && $_POST['page_number'] < 1) {
$page_number = 1;
} else {
$count = dbFetchCell("SELECT COUNT(*) $query $where", $param);
if (isset($_POST['page_number']) && $_POST['page_number'] > 0 && $_POST['page_number'] <= $count) {
$page_number = $_POST['page_number'];
} else {
$page_number = 1;
}
$start = (($page_number - 1) * $results);
$full_query = $full_query.$query." ORDER BY id ASC LIMIT $start,$results";
$start = (($page_number - 1) * $results);
$full_query = "SELECT alert_rules.* $query $where ORDER BY alert_rules.id ASC LIMIT $start,$results";
foreach (dbFetchRows($full_query, $param) as $rule) {
$sub = dbFetchRows('SELECT * FROM alerts WHERE rule_id = ? ORDER BY `state` DESC, `id` DESC LIMIT 1', array($rule['id']));
@@ -149,20 +149,38 @@ foreach (dbFetchRows($full_query, $param) as $rule) {
}
$rule_extra = json_decode($rule['extra'], true);
if ($rule['device_id'] == ':-1' || $rule['device_id'] == '-1') {
$popover_msg = 'Global alert rule';
$device_count = dbFetchCell('SELECT COUNT(*) FROM alert_device_map WHERE rule_id=?', [$rule['id']]);
$group_count = dbFetchCell('SELECT COUNT(*) FROM alert_group_map WHERE rule_id=?', [$rule['id']]);
if ($device_count && $group_count) {
$popover_msg = 'Restricted rule';
$icon_indicator = 'fa fa-connectdevelop fa-fw text-primary';
} elseif ($device_count) {
$popover_msg = 'Device restricted rule';
$icon_indicator = 'fa fa-server fa-fw text-primary';
} elseif ($group_count) {
$popover_msg = 'Group restricted rule';
$icon_indicator = 'fa fa-th fa-fw text-primary';
} else {
$popover_msg = 'Device specific rule';
$popover_msg = 'Global alert rule';
$icon_indicator = 'fa fa-globe fa-fw text-success';
}
echo "<tr class='".$extra."' id='row_".$rule['id']."'>";
echo '<td><i>#'.((int) $rule['id']).'</i></td>';
echo "<td><i>#".((int) $rule['id'])."</i><br /><i class=\"$icon_indicator\"></i></td>";
echo '<td>'.$rule['name'].'</td>';
echo "<td class='col-sm-4'>";
if ($rule_extra['invert'] === true) {
echo '<strong><em>Inverted</em></strong> ';
}
echo '<i>'.htmlentities($rule['rule']).'</i></td>';
if (empty($rule['builder'])) {
$rule_display = $rule['rule'];
} else {
$rule_display = QueryBuilderParser::fromJson($rule['builder'])->toSql(false);
}
echo '<i>'.htmlentities($rule_display).'</i></td>';
echo '<td>'.$rule['severity'].'</td>';
echo "<td><span id='alert-rule-".$rule['id']."' class='fa fa-fw fa-2x fa-".$ico.' text-'.$col."'></span> ";
if ($rule_extra['mute'] === true) {
@@ -171,15 +189,15 @@ foreach (dbFetchRows($full_query, $param) as $rule) {
echo '<td><small>Max: '.$rule_extra['count'].'<br />Delay: '.$rule_extra['delay'].'<br />Interval: '.$rule_extra['interval'].'</small></td>';
echo '<td>';
if ($_SESSION['userlevel'] >= '10') {
if (is_admin()) {
echo "<input id='".$rule['id']."' type='checkbox' name='alert-rule' data-orig_class='".$orig_class."' data-orig_colour='".$orig_col."' data-orig_state='".$orig_ico."' data-alert_id='".$rule['id']."' ".$alert_checked." data-size='small' data-content='".$popover_msg."' data-toggle='modal'>";
}
echo '</td>';
echo '<td>';
if ($_SESSION['userlevel'] >= '10') {
if (is_admin()) {
echo "<div class='btn-group btn-group-sm' role='group'>";
echo "<button type='button' class='btn btn-primary' data-toggle='modal' data-target='#create-alert' data-device_id='".$rule['device_id']."' data-alert_id='".$rule['id']."' name='edit-alert-rule' data-content='".$popover_msg."' data-container='body'><i class='fa fa-lg fa-pencil' aria-hidden='true'></i></button> ";
echo "<button type='button' class='btn btn-primary' data-toggle='modal' data-target='#create-alert' data-rule_id='".$rule['id']."' name='edit-alert-rule' data-content='".$popover_msg."' data-container='body'><i class='fa fa-lg fa-pencil' aria-hidden='true'></i></button> ";
echo "<button type='button' class='btn btn-danger' aria-label='Delete' data-toggle='modal' data-target='#confirm-delete' data-alert_id='".$rule['id']."' name='delete-alert-rule' data-content='".$popover_msg."' data-container='body'><i class='fa fa-lg fa-trash' aria-hidden='true'></i></button>";
}
@@ -295,11 +313,4 @@ function changePage(page,e) {
$('#result_form').submit();
}
function newRule(data, e) {
$('#template_id').val(data.value);
$('#create-alert').modal({
show: true
});
}
</script>