Skip to content

Commit

Permalink
Merge pull request #863 from f0o/alert_macros
Browse files Browse the repository at this point in the history
Alerting-Update
  • Loading branch information
laf committed Apr 27, 2015
2 parents 67e49df + 332a8b0 commit bcf3c5c
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 21 deletions.
4 changes: 2 additions & 2 deletions alerts.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ function ExtTransports($obj) {
global $config;
$tmp = false; //To keep scrutinizer from naging because it doesnt understand eval
foreach( $config['alert']['transports'] as $transport=>$opts ) {
if( file_exists($config['install_dir']."/includes/alerts/transport.".$transport.".php") ) {
if( ($opts === true || !empty($opts)) && file_exists($config['install_dir']."/includes/alerts/transport.".$transport.".php") ) {
echo $transport." => ";
eval('$tmp = function($obj,$opts) { global $config; '.file_get_contents($config['install_dir']."/includes/alerts/transport.".$transport.".php").' };');
$tmp = $tmp($obj,$opts);
Expand Down Expand Up @@ -292,7 +292,7 @@ function DescribeAlert($alert) {
$i++;
$obj['faults'][$i] = $incident;
foreach( $incident as $k=>$v ) {
if( !empty($v) && $k != 'device_id' && (stristr($k,'id') || stristr($k,'desc')) && substr_count($k,'_') <= 1 ) {
if( !empty($v) && $k != 'device_id' && (stristr($k,'id') || stristr($k,'desc') || stristr($k,'msg')) && substr_count($k,'_') <= 1 ) {
$obj['faults'][$i]['string'] .= $k.' => '.$v."; ";
}
}
Expand Down
111 changes: 111 additions & 0 deletions doc/Extensions/Alerting.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ Table of Content:
- [Ports](#entity-ports)
- [Processors](#entity-processors)
- [Storage](#entity-storage)
- [Macros](#macros)
- [Device](#macros-device)
- [Port](#macros-port)
- [Time](#macros-time)


# <a name="about">About</a>

Expand Down Expand Up @@ -316,3 +321,109 @@ __processors.processor_descr__ = The description of the processor.
__storage.storage_descr__ = The description of the storage.

__storage.storage_perc__ = The usage of the storage as a percentage.

# <a name="macros">Macros</a>

Macros are shorthands to either portion of rules or pure SQL enhanced with placeholders.
You can define your own macros in your `config.php`.

Example macro-implementation of Debian-Devices
```php
$config['alert']['macros']['rule']['is_debian'] = '%devices.features ~ "@debian@"';
```
And in the Rule:
```
... && %macros.is_debian = "1" && ...
```

This Example-macro is a Boolean-macro, it applies a form of filter to the set of results defined by the rule.
All macros that are not unary should return Boolean.

You can only apply _Equal_ or _Not-Equal_ Operations on Bollean-macros where `True` is represented by `"1"` and `False` by `"0"`.


## <a name="macros-device">Device</a> (Boolean)

Entity: `%macros.device`

Description: Only select devices that aren't deleted, ignored or disabled.

Source: `(%devices.disabled = "0" && %devices.ignore = "0")`

### <a name="macros-device-up">Device is up</a> (Boolean)

Entity: `%macros.device_up`

Description: Only select devices that are up.

Implies: %macros.device

Source: `(%devices.status = "1" && %macros.device)`

### <a name="macros-device-down">Device is down</a> (Boolean)

Entity: `%macros.device_down`

Description: Only select devices that are down.

Implies: %macros.device

Source: `(%devices.status = "0" && %macros.device)`

## <a name="macros-port">Port</a> (Boolean)

Entity: `%macros.port`

Description: Only select ports that aren't deleted, ignored or disabled.

Source: `(%ports.deleted = "0" && %ports.ignore = "0" && %ports.disabled = "0")`

### <a name="macros-port-up">Port is up</a> (Boolean)

Entity: `%macros.port_up`

Description: Only select ports that are up and also should be up.

Implies: %macros.port

Source: `(%ports.ifOperStatus = "up" && %ports.ifAdminStatus = "up" && %macros.port)`

### <a name="macros-port-down">Port is down</a> (Boolean)

Entity: `%macros.port_down`

Description: Only select ports that are down.

Implies: %macros.port

Source: `(%ports.ifOperStatus = "down" && %ports.ifAdminStatus != "down" && %macros.port)`

### <a name="macros-port-usage-perc">Port-Usage in Percent</a> (Decimal)

Entity: `%macros.port_usage_perc`

Description: Return port-usage in percent.

Source: `((%ports.ifInOctets_rate*8)/%ports.ifSpeed)*100`

## <a name="macros-time">Time</a>

### <a name="macros-time-now">Now</a> (Datetime)

Entity: `%macros.now`

Description: Alias of MySQL's NOW()

Source: `NOW()`

### <a name="macros-time-past-Nm">Past N Minutes</a> (Datetime)

Entity: `%macros.past_$m`

Description: Returns a MySQL Timestamp dated `$` Minutes in the past. `$` can only be a supported Resolution.

Example: `%macros.past_5m` is Last 5 Minutes.

Resolution: 5,10,15,30,60

Source: `DATE_SUB(NOW(),INTERVAL $ MINUTE)`
15 changes: 11 additions & 4 deletions html/ajax_rulesuggest.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,16 @@ function levsort($base, $obj) {
$chk = $memcache->get('rule-suggest_'.$term[0]);
}
if( !(sizeof($chk) > 0) || $chk === false ) {
$tmp = dbFetchRows('SHOW COLUMNS FROM '.$term[0]);
foreach( $tmp as $tst ) {
if( isset($tst['Field']) ) {
$chk[] = $term[0].'.'.$tst['Field'];
if( $term[0] == "macros" ) {
foreach( $config['alert']['macros']['rule'] as $macro=>$v ) {
$chk[] = "macros.".$macro;
}
} else {
$tmp = dbFetchRows('SHOW COLUMNS FROM '.$term[0]);
foreach( $tmp as $tst ) {
if( isset($tst['Field']) ) {
$chk[] = $term[0].'.'.$tst['Field'];
}
}
}
}
Expand All @@ -84,6 +90,7 @@ function levsort($base, $obj) {
foreach( $tmp as $tst ) {
$chk[] = $tst['TABLE_NAME'].'.';
}
$chk[] = 'macros.';
}
}
if( sizeof($chk) > 0 ) {
Expand Down
6 changes: 6 additions & 0 deletions html/forms/delete-device-group.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
exit;
} else {
if(dbDelete('device_groups', "`id` = ?", array($_POST['group_id']))) {
if( dbFetchCell('SELECT COUNT(id) FROM alert_map WHERE target = ?',array('g'.$_POST['group_id'])) >= 1 ) {
foreach( dbFetchRows('SELECT id FROM alert_map WHERE target = ?',array('g'.$_POST['group_id'])) as $map ) {
$_POST['map_id'] = $map['id'];
include('forms/delete-alert-map.inc.php');
}
}
echo('group has been deleted.');
exit;
} else {
Expand Down
10 changes: 6 additions & 4 deletions html/includes/modal/new_alert_rule.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -245,11 +245,13 @@
strategy: 'array',
tagFieldName: 'rules[]'
});
if(entity.indexOf("%") >= 0) {
$('#response').data('tagmanager').populate([ entity+' '+condition+' '+value+' '+glue ]);
} else {
$('#response').data('tagmanager').populate([ '%'+entity+' '+condition+' "'+value+'" '+glue ]);
if(value.indexOf("%") < 0) {
value = '"'+value+'"';
}
if(entity.indexOf("%") < 0) {
entity = '%'+entity;
}
$('#response').data('tagmanager').populate([ entity+' '+condition+' '+value+' '+glue ]);
}
});

Expand Down
10 changes: 5 additions & 5 deletions html/includes/print-alert-rules.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
<?php

if(isset($_POST['create-default'])) {
$default_rules[] = array('device_id' => '-1', 'rule' => '%devices.status != "1" && %devices.disabled = "0" && %devices.ignore = "0"', 'severity' => 'critical', 'extra' => '{"mute":false,"count":"-1","delay":"300"}', 'disabled' => 0, 'name' => 'Devices up/down');
$default_rules[] = array('device_id' => '-1', 'rule' => '%devices.uptime < "300" && %devices.disabled = "0" && %devices.ignore = "0"', 'severity' => 'critical', 'extra' => '{"mute":false,"count":"1","delay":"300"}', 'disabled' => 0, 'name' => 'Device rebooted');
$default_rules[] = array('device_id' => '-1', 'rule' => '%bgpPeers.bgpPeerState != "established"', 'severity' => 'critical', 'extra' => '{"mute":false,"count":"1","delay":"300"}', 'disabled' => 0, 'name' => 'BGP Session down');
$default_rules[] = array('device_id' => '-1', 'rule' => '%macros.device_down = "1"', 'severity' => 'critical', 'extra' => '{"mute":false,"count":"-1","delay":"300"}', 'disabled' => 0, 'name' => 'Devices up/down');
$default_rules[] = array('device_id' => '-1', 'rule' => '%devices.uptime < "300" && %macros.device = "1"', 'severity' => 'critical', 'extra' => '{"mute":false,"count":"1","delay":"300"}', 'disabled' => 0, 'name' => 'Device rebooted');
$default_rules[] = array('device_id' => '-1', 'rule' => '%bgpPeers.bgpPeerState != "established" && %macros.device_up = "1"', 'severity' => 'critical', 'extra' => '{"mute":false,"count":"1","delay":"300"}', 'disabled' => 0, 'name' => 'BGP Session down');
$default_rules[] = array('device_id' => '-1', 'rule' => '%bgpPeers.bgpPeerFsmEstablishedTime < "300" && %bgpPeers.bgpPeerState = "established"', 'severity' => 'critical', 'extra' => '{"mute":false,"count":"1","delay":"300"}', 'disabled' => 0, 'name' => 'BGP Session establised');
$default_rules[] = array('device_id' => '-1', 'rule' => '%ports.ifOperStatus != "up" && %ports.ifAdminStatus = "up" && %ports.deleted = "0" && %ports.ignore = "0" && %ports.disabled = "0"', 'severity' => 'critical', 'extra' => '{"mute":false,"count":"1","delay":"300"}', 'disabled' => 0, 'name' => 'Port status up/down');
$default_rules[] = array('device_id' => '-1', 'rule' => '((%ports.ifInOctets_rate*8)/%ports.ifSpeed)*100 >= 80', 'severity' => 'critical', 'extra' => '{"mute":false,"count":"-1","delay":"300"}', 'disabled' => 0, 'name' => 'Port utilisation over threshold');
$default_rules[] = array('device_id' => '-1', 'rule' => '%macros.port_down = "1"', 'severity' => 'critical', 'extra' => '{"mute":false,"count":"1","delay":"300"}', 'disabled' => 0, 'name' => 'Port status up/down');
$default_rules[] = array('device_id' => '-1', 'rule' => '%macros.port_usage_perc >= "80"', 'severity' => 'critical', 'extra' => '{"mute":false,"count":"-1","delay":"300"}', 'disabled' => 0, 'name' => 'Port utilisation over threshold');
$default_rules[] = array('device_id' => '-1', 'rule' => '%sensors.sensor_current > %sensors.sensor_limit', 'severity' => 'critical', 'extra' => '{"mute":false,"count":"-1","delay":"300"}', 'disabled' => 0, 'name' => 'Sensor over limit');
$default_rules[] = array('device_id' => '-1', 'rule' => '%sensors.sensor_current < %sensors.sensor_limit_low', 'severity' => 'critical', 'extra' => '{"mute":false,"count":"-1","delay":"300"}', 'disabled' => 0, 'name' => 'Sensor under limit');
foreach( $default_rules as $add_rule ) {
Expand Down
1 change: 1 addition & 0 deletions html/includes/print-graph-alerts.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
*/
$pagetitle[] = "Alert Stats";

$sql = "";
if (isset($device['device_id']) && $device['device_id'] > 0) {
$sql = " AND alert_log.device_id=?";
$param = array(
Expand Down
6 changes: 3 additions & 3 deletions html/includes/table/alerts.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@
$fault_detail .= $tmp;
} else {
foreach ($tmp_alerts as $k=>$v) {
if (!empty($v) && $k != 'device_id' && (stristr($k,'id') || stristr($k,'desc')) && substr_count($k,'_') <= 1) {
if (!empty($v) && $k != 'device_id' && (stristr($k,'id') || stristr($k,'desc') || stristr($k,'msg')) && substr_count($k,'_') <= 1) {
$fault_detail .= "$k => '$v', ";
}
$fault_detail = rtrim($fault_detail,", ");
}
$fault_detail = rtrim($fault_detail,", ");
}
$fault_detail .= "<br>";
}
Expand Down Expand Up @@ -97,7 +97,7 @@
if ($_SESSION['userlevel'] >= '10') {
$ack_ico = 'volume-up';
$ack_col = 'success';
if(in_array($alert['state'],array(2,3,4))) {
if($alert['state'] == 2) {
$ack_ico = 'volume-off';
$ack_col = 'danger';
}
Expand Down
33 changes: 30 additions & 3 deletions includes/alerts.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,13 @@
/**
* Generate SQL from Rule
* @param string $rule Rule to generate SQL for
* @return string
* @return string|boolean
*/
function GenSQL($rule) {
$rule = RunMacros($rule);
if( empty($rule) ) {
return false;
}
$tmp = explode(" ",$rule);
$tables = array();
foreach( $tmp as $opt ) {
Expand All @@ -55,6 +59,29 @@ function GenSQL($rule) {
return $sql;
}

/**
* Process Macros
* @param string $rule Rule to process
* @return string|boolean
*/
function RunMacros($rule,$x=1) {
global $config;
krsort($config['alert']['macros']['rule']);
foreach( $config['alert']['macros']['rule'] as $macro=>$value ) {
if( !strstr($macro," ") ) {
$rule = str_replace('%macros.'.$macro,$value,$rule);
}
}
if( strstr($rule,"%macros") ) {
if( ++$x < 30 ) {
$rule = RunMacros($rule,$x);
} else {
return false;
}
}
return $rule;
}

/**
* Get Alert-Rules for Devices
* @param int $device Device-ID
Expand Down Expand Up @@ -158,8 +185,8 @@ function GetContacts($results) {
if( sizeof($results) == 0 ) {
return array();
}
if( $config['alerts']['email']['default_only'] ) {
return array($config['alerts']['email']['default'] => 'NOC');
if( $config['alert']['default_only'] == true || $config['alerts']['email']['default_only'] == true ) {
return array(''.($config['alert']['default_mail'] ? $config['alert']['default_mail'] : $config['alerts']['email']['default']) => 'NOC');
}
$users = get_userlist();
$contacts = array();
Expand Down
38 changes: 38 additions & 0 deletions includes/defaults.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,44 @@

// Alerting Settings

$config['alert'] = array(
'macros' => array( //Macros:
'rule' => array( // For Rules
//Time Macros
'now' => 'NOW()',
'past_5m' => 'DATE_SUB(NOW(),INTERVAL 5 MINUTE)',
'past_10m' => 'DATE_SUB(NOW(),INTERVAL 10 MINUTE)',
'past_15m' => 'DATE_SUB(NOW(),INTERVAL 15 MINUTE)',
'past_30m' => 'DATE_SUB(NOW(),INTERVAL 30 MINUTE)',
'past_60m' => 'DATE_SUB(NOW(),INTERVAL 60 MINUTE)',

//Device Macros
'device' => '(%devices.disabled = "0" && %devices.ignore = "0")',
'device_up' => '(%devices.status = "1" && %macros.device)',
'device_down' => '(%devices.status = "0" && %macros.device)',

//Port Macros
'port' => '(%ports.deleted = "0" && %ports.ignore = "0" && %ports.disabled = "0")',
'port_up' => '(%ports.ifOperStatus = "up" && %ports.ifAdminStatus = "up" && %macros.port)',
'port_down' => '(%ports.ifOperStatus = "down" && %ports.ifAdminStatus != "down" && %macros.port)',
'port_usage_perc' => '((%ports.ifInOctets_rate*8)/%ports.ifSpeed)*100',

//Misc Macros
),
),
'transports' => array( //Transports:
'dummy' => false, // Dummy alerting (debug)
'mail' => false, // E-Mail alerting
'irc' => false, // IRC Alerting
),
'globals' => false, //Issue to global-read users
'admins' => false, //Issue to administrators
'default_only' => false, //Only issue to default
'default_mail' => '', //Default email
);

//Legacy options

$config['alerts']['email']['default'] = NULL; // Default alert recipient
$config['alerts']['email']['default_only'] = FALSE; // Only use default recipient
$config['alerts']['email']['enable'] = TRUE; // Enable email alerts
Expand Down

0 comments on commit bcf3c5c

Please sign in to comment.