Merge pull request #1665 from laf/issue-381

Simple graylog integration
This commit is contained in:
Daniel Preussker
2015-08-18 17:07:21 +00:00
9 changed files with 248 additions and 3 deletions

17
doc/Extensions/Graylog.md Normal file
View File

@@ -0,0 +1,17 @@
# Graylog integration
We have simple integration for Graylog, you will be able to view any logs from within LibreNMS that have been parsed by the syslog input from within
Graylog itself. This includes logs from devices which aren't in LibreNMS still, you can also see logs for a sepcific device under the logs section
for the device.
Graylog itself isn't included within LibreNMS, you will need to install this separately either on the same infrastructure as LibreNMS or as a totally
standalone appliance.
Config is simple, here's an example:
```php
$config['graylog']['server'] = 'http://127.0.0.1';
$config['graylog']['port'] = 12900;
$config['graylog']['username'] = 'admin';
$config['graylog']['password'] = 'admin';
```

View File

@@ -33,6 +33,8 @@ if ($type == 'placeholder') {
}
elseif (is_file('includes/common/'.$type.'.inc.php')) {
$results_limit = 10;
$no_form = true;
include 'includes/common/'.$type.'.inc.php';
$output = implode('', $common_output);
$status = 'ok';

View File

@@ -0,0 +1,125 @@
<?php
/*
* LibreNMS
*
* Copyright (c) 2014 Neil Lathwood <https://github.com/laf/ http://www.lathwood.co.uk/fa>
*
* 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. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/
if (empty($results_limit)) {
$results_limit = 25;
}
$tmp_output = '<h3>Graylog</h3>
<div class="table-responsive">
<table id="graylog" class="table table-hover table-condensed graylog">
<thead>
<tr>
<th data-column-id="timestamp">Timestamp</th>
<th data-column-id="source">Source</th>
<th data-column-id="message">Message</th>
<th data-column-id="facility" data-visible="false">Facility</th>
<th data-column-id="level" data-visible="false">Level</th>
</tr>
</thead>
</table>
</div>
<script>
searchbar = "<div id=\"{{ctx.id}}\" class=\"{{css.header}}\"><div class=\"row\">"+
"<div class=\"col-sm-8\"><form method=\"post\" action=\"\" class=\"form-inline\">"+
"Filter: "+
';
if (!empty($filter_device)) {
$tmp_output .= '
"<input type=\"hidden\" name=\"hostname\" id=\"hostname\" value=\"'. $filter_device .'\">"+
';
}
else {
$tmp_output .= '
"<div class=\"form-group\"><select name=\"hostname\" id=\"hostname\" class=\"form-control input-sm\">"+
"<option value=\"\">All devices</option>"+
';
if (is_admin() === true || is_read() === true) {
$results = dbFetchRows("SELECT `hostname` FROM `devices` GROUP BY `hostname` ORDER BY `hostname`");
}
else {
$results = dbFetchRows("SELECT `D`.`hostname` FROM `devices` AS `D`, `devices_perms` AS `P` WHERE `P`.`user_id` = ? AND `P`.`device_id` = `D`.`device_id` GROUP BY `hostname` ORDER BY `hostname`", array($_SESSION['user_id']));
}
foreach ($results as $data) {
$tmp_output .= '"<option value=\"'.$data['hostname'].'\""+';
if ($data['hostname'] == $vars['hostname']) {
$tmp_output .= '"selected"+';
}
$tmp_output .= '">'.$data['hostname'].'</option>"+';
}
$tmp_output .= '
"</select>&nbsp;</div>"+
';
}
if (empty($filter_device)) {
$filter_device = mres($_POST['hostname']);
}
$tmp_output .= '
"<div class=\"form-group\"><select name=\"range\" class=\"form-group input-sm\">"+
"<option value=\"300\">Search last 5 minutes</option>"+
"<option value=\"900\">Search last 15 minutes</option>"+
"<option value=\"1800\">Search last 30 minutes</option>"+
"<option value=\"3600\">Search last 1 hour</option>"+
"<option value=\"7200\">Search last 2 hours</option>"+
"<option value=\"28800\">Search last 8 hours</option>"+
"<option value=\"86400\">Search last 1 day</option>"+
"<option value=\"172800\">Search last 2 days</option>"+
"<option value=\"432000\">Search last 5 days</option>"+
"<option value=\"604800\">Search last 7 days</option>"+
"<option value=\"1209600\">Search last 14 days</option>"+
"<option value=\"2592000\">Search last 30 days</option>"+
"<option value=\"0\">Search all time</option>"+
"</select>&nbsp;</div>"+
"<button type=\"submit\" class=\"btn btn-success btn-sm\">Filter</button>&nbsp;"+
"</form></div>"+
"<div class=\"col-sm-4 actionBar\"><p class=\"{{css.search}}\"></p><p class=\"{{css.actions}}\"></p></div></div></div>"
var graylog_grid = $("#graylog").bootgrid({
ajax: true,
rowCount: ['. $results_limit .', 25,50,100,250,-1],
';
if ($no_form !== true) {
$tmp_output .= '
templates: {
header: searchbar
},
';
}
$tmp_output .= '
post: function ()
{
return {
id: "graylog",
hostname: "' . $filter_device . '",
range: "' . mres($_POST['range']) . '"
};
},
url: "/ajax_table.php",
});
</script>
';
$common_output[] = $tmp_output;

View File

@@ -77,9 +77,17 @@ if ($_SESSION['userlevel'] >= '10') {
</li>
<li role="presentation" class="divider"></li>
<li><a href="<?php echo(generate_url(array('page'=>'eventlog'))); ?>"><i class="fa fa-book fa-fw fa-lg"></i> Eventlog</a></li>
<?php if (isset($config['enable_syslog']) && $config['enable_syslog']) {
echo(' <li><a href="'.generate_url(array('page'=>'syslog')).'"><i class="fa fa-book fa-fw fa-lg"></i> Syslog</a></li>');
} ?>
<?php
if (isset($config['enable_syslog']) && $config['enable_syslog']) {
echo ' <li><a href="'.generate_url(array('page'=>'syslog')).'"><i class="fa fa-book fa-fw fa-lg"></i> Syslog</a></li>';
}
if (isset($config['graylog']['server']) && isset($config['graylog']['port'])) {
echo ' <li><a href="'.generate_url(array('page'=>'graylog')).'"><i class="fa fa-book fa-fw fa-lg"></i> Graylog</a></li>';
}
?>
<li><a href="<?php echo(generate_url(array('page'=>'inventory'))); ?>"><i class="fa fa-cube fa-fw fa-lg"></i> Inventory</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation" class="dropdown-header"> Search</li>

View File

@@ -0,0 +1,71 @@
<?php
/*
* LibreNMS
*
* Copyright (c) 2014 Neil Lathwood <https://github.com/laf/ http://www.lathwood.co.uk/fa>
*
* 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. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/
$filter_hostname = mres($_POST['hostname']);
$filter_range = mres($_POST['range']);
if (isset($searchPhrase) && !empty($searchPhrase)) {
$query = 'message:"'.$searchPhrase.'"';
}
else {
$query = '*';
}
if (isset($current)) {
$offset = ($current * $rowCount) - ($rowCount);
$limit = $rowCount;
}
if ($rowCount != -1) {
$extra_query = "&limit=$limit&offset=$offset";
}
if (!empty($filter_hostname)) {
if (!empty($query)) {
$query .= ' && ';
}
$ip = gethostbyname($filter_hostname);
$query .= 'source:"'.$filter_hostname.'" || source:"'.$ip.'"';
}
$graylog_url = $config['graylog']['server'] . ':' . $config['graylog']['port'] . '/search/universal/relative?query=' . urlencode($query) . '&range='. $filter_range . $extra_query;
$context = stream_context_create(array(
'http' => array(
'header' => "Authorization: Basic " . base64_encode($config['graylog']['username'].':'.$config['graylog']['password']) . "\r\n" .
"Accept: application/json",
)
));
$messages = json_decode(file_get_contents($graylog_url, false, $context),true);
foreach ($messages['messages'] as $message) {
$response[] = array(
'timestamp' => $message['message']['timestamp'],
'source' => '<a href="'.generate_url(array('page'=>'device', 'device'=>$message['message']['source'])).'">'.$message['message']['source'].'</a>',
'message' => $message['message']['message'],
'facility' => $message['message']['facility'],
'level' => $message['message']['level'],
);
}
if (empty($messages['total_results'])) {
$total = 0;
}
else {
$total = $messages['total_results'];
}
$output = array('current'=>$current,'rowCount'=>$rowCount,'rows'=>$response,'total'=>$total);
echo _json_encode($output);

View File

@@ -30,9 +30,21 @@ if (isset($config['enable_syslog']) && $config['enable_syslog'] == 1) {
}
}
if (isset($config['graylog']['server']) && isset($config['graylog']['port'])) {
echo ' | ';
if ($vars['section'] == 'graylog') {
echo '<span class="pagemenu-selected">';
}
echo generate_link('Graylog', $vars, array('section' => 'graylog'));
if ($vars['section'] == 'graylog') {
echo '</span>';
}
}
switch ($vars['section']) {
case 'syslog':
case 'eventlog':
case 'graylog':
include 'pages/device/logs/'.$vars['section'].'.inc.php';
break;

View File

@@ -0,0 +1,5 @@
<?php
$filter_device = $device['hostname'];
require_once 'includes/common/graylog.inc.php';
echo implode('',$common_output);

View File

@@ -0,0 +1,4 @@
<?php
require_once 'includes/common/graylog.inc.php';
echo implode('',$common_output);

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

@@ -0,0 +1 @@
INSERT INTO `widgets` (`widget_title`, `widget`, `base_dimensions`) VALUES ('Graylog', 'graylog', '9,7');