feature: Added syslog alert transport (#6246)

* Add syslog alert transport and docs

* Remove redundant priority variable

* Log syslog transport events as critical
This commit is contained in:
pblasquez
2017-03-23 01:46:28 -07:00
committed by Neil Lathwood
parent 359d5004f2
commit c2cdf14223
4 changed files with 171 additions and 2 deletions

View File

@@ -31,6 +31,7 @@ Table of Content:
- [Microsoft Teams](#transports-msteams)
- [Cisco Spark](#transports-ciscospark)
- [SMSEagle](#transports-smseagle)
- [Syslog](#transports-syslog)
- [Entities](#entities)
- [Devices](#entity-devices)
- [BGP Peers](#entity-bgppeers)
@@ -628,7 +629,7 @@ SMSEagle is a hardware SMS Gateway that can be used via their HTTP-API using a U
Please consult their documentation at [www.smseagle.eu](http://www.smseagle.eu)
Destination numbers are one per line, with no spaces. They can be in either local or international dialling format.
~~
~
```php
$config['alert']['transports']['smseagle']['url'] = 'ip.add.re.ss';
$config['alert']['transports']['smseagle']['user'] = 'smseagle_user';
@@ -636,7 +637,22 @@ $config['alert']['transports']['smseagle']['token'] = 'smseagle_user_password';
$config['alert']['transports']['smseagle']['to'][] = '+3534567890';
$config['alert']['transports']['smseagle']['to'][] = '0834567891';
```
~~
~
## <a name="transports-syslog">Syslog</a>
You can have LibreNMS emit alerts as syslogs complying with RFC 3164.
More information on RFC 3164 can be found here: https://tools.ietf.org/html/rfc3164
Example output: `<26> Mar 22 00:59:03 librenms.host.net librenms[233]: [Critical] network.device.net: Port Down - port_id => 98939; ifDescr => xe-1/1/0;`
Each fault will be sent as a separate syslog.
~
```php
$config['alert']['transports']['syslog']['syslog_host'] = '127.0.0.1';
$config['alert']['transports']['syslog']['syslog_port'] = 514;
$config['alert']['transports']['syslog']['syslog_facility'] = 3;
```
~
# <a name="entities">Entities

View File

@@ -1302,6 +1302,48 @@ echo '
<textarea class="form-control" name="global-config-textarea" id="smseagle_to" placeholder="Enter mobile phone numbers, one per line" data-config_id="'.$smseagle_url['config_id'].'" data-type="smseagle">'.$upd_mobiles.'</textarea>
<span class="form-control-feedback">
<i class="fa" aria-hidden="true"></i>
</span>
</div>
</div>
</div>
</div>
</div>';
$syslog_host = get_config_by_name('alert.transports.syslog.syslog_host');
$syslog_port = get_config_by_name('alert.transports.syslog.syslog_port');
$syslog_facility = get_config_by_name('alert.transports.syslog.syslog_facility');
echo '
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#syslog_transport_expand"><i class="fa fa-caret-down"></i> Syslog transport</a> <button name="test-alert" id="test-alert" type="button" data-transport="syslog" class="btn btn-primary btn-xs pull-right">Test transport</button>
</h4>
</div>
<div id="syslog_transport_expand" class="panel-collapse collapse">
<div class="panel-body">
<div class="form-group has-feedback">
<label for="syslog_host" class="col-sm-4 control-label">Syslog Host </label>
<div class="col-sm-4">
<input id="syslog_host" class="form-control" type="text" name="global-config-input" value="'.$syslog_host['config_value'].'" data-config_id="'.$syslog_host['config_id'].'">
<span class="form-control-feedback">
<i class="fa" aria-hidden="true"></i>
</span>
</div>
</div>
<div class="form-group has-feedback">
<label for="syslog_port" class="col-sm-4 control-label">Syslog Port </label>
<div class="col-sm-4">
<input id="syslog_port" class="form-control" type="text" name="global-config-input" value="'.$syslog_port['config_value'].'" data-config_id="'.$syslog_port['config_id'].'">
<span class="form-control-feedback">
<i class="fa" aria-hidden="true"></i>
</span>
</div>
</div>
<div class="form-group has-feedback">
<label for="syslog_facility" class="col-sm-4 control-label">Syslog Facility </label>
<div class="col-sm-4">
<input id="syslog_facility" class="form-control" type="text" name="global-config-input" value="'.$syslog_facility['config_value'].'" data-config_id="'.$syslog_facility['config_id'].'">
<span class="form-control-feedback">
<i class="fa" aria-hidden="true"></i>
</span>
</div>
</div>

View File

@@ -0,0 +1,110 @@
/* LibreNMS
*
* Copyright (C) 2017 Paul Blasquez <pblasquez@gmail.com>
* 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 3 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
$syslog_host = '127.0.0.1';
$syslog_port = 514;
$state = "Unknown";
$facility = 24; // Default facility is 3 * 8 (daemon)
$severity = 6; // Default severity is 6 (Informational)
$sev_txt = "OK";
$device = device_by_id_cache($obj['device_id']); // for event logging
if (!empty($opts['syslog_facility']) && preg_match("/^\d+$/", $opts['syslog_facility'])) {
$facility = (int)$opts['syslog_facility'] * 8;
} else {
log_event("Syslog facility is not an integer: " . $opts['syslog_facility'], $device, 'poller', 5);
}
if (!empty($opts['syslog_host'])) {
if (preg_match("/[a-zA-Z]/", $opts['syslog_host'])) {
$syslog_host = gethostbyname($opts['syslog_host']);
if ($syslog_host === $opts['syslog_host']) {
log_event("Alphanumeric hostname found but does not resolve to an IP.", $device, 'poller', 5);
return false;
}
} elseif (filter_var($opts['syslog_host'], FILTER_VALIDATE_IP)) {
$syslog_host = $opts['syslog_host'];
} else {
log_event("Syslog host is not a valid IP: " . $opts['syslog_host'], $device, 'poller', 5);
return false;
}
} else {
log_event("Syslog host is empty.", $device, 'poller');
}
if (!empty($opts['syslog_port']) && preg_match("/^\d+$/", $opts['syslog_port'])) {
$syslog_port = $opts['syslog_port'];
} else {
log_event("Syslog port is not an integer.", $device, 'poller', 5);
}
switch( $obj['severity'] ) {
case "critical":
$severity = 2;
$sev_txt = "Critical";
break;
case "warning":
$severity = 4;
$sev_txt = "Warning";
break;
}
switch( $obj['state'] ) {
case 0:
$state = "OK";
$severity = 6;
break;
case 1:
$state = $sev_txt;
break;
case 2:
$state = "Acknowledged";
$severity = 6;
break;
}
$priority = $facility + $severity;
$syslog_prefix = '<'
. $priority
. '> '
. date('M d H:i:s ')
. gethostname()
. ' librenms'
. '['
. $obj['device_id']
. ']: '
. $obj['hostname']
. ': ['
. $state
. '] '
. $obj['name']
;
if (($socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === false) {
log_event("socket_create() failed: reason: " . socket_strerror(socket_last_error()), $device, 'poller', 5);
return false;
} else {
if( !empty( $obj['faults'] ) ) {
foreach($obj['faults'] as $k => $v) {
$syslog_msg = $syslog_prefix . ' - ' . $v['string'];
socket_sendto($socket, $syslog_msg, strlen($syslog_msg), 0, $syslog_host, $syslog_port);
}
} else {
$syslog_msg = $syslog_prefix;
socket_sendto($socket, $syslog_msg, strlen($syslog_msg), 0, $syslog_host, $syslog_port);
}
socket_close($socket);
}
return true;

1
sql-schema/182.sql Normal file
View File

@@ -0,0 +1 @@
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.transports.syslog.syslog_host','','','Syslog Host','alerting',0,'transports',0,'0','0'),('alert.transports.syslog.syslog_port','','','Syslog Port','alerting',0,'transports',0,'0','0'),('alert.transports.syslog.syslog_facility','','','Syslog Facility','alerting',0,'transports',0,'0','0');