diff --git a/doc/Extensions/Graphite.md b/doc/Extensions/Graphite.md new file mode 100644 index 0000000000..f833ed0871 --- /dev/null +++ b/doc/Extensions/Graphite.md @@ -0,0 +1,32 @@ +source: Extensions/Graphite.md +# Enabling support for Graphite. + +This module sends all metrics to a remote graphite service. You need something like Grafana for graphing. + +### What you don't get + - Pretty graphs, this is why at present you need Grafana. You need to build your own graphs within Grafana. + +RRD will continue to function as normal so LibreNMS itself should continue to function as normal. + +### Configuration +```php +$config['graphite']['enable'] = true; +$config['graphite']['host'] = 'your.graphite.server'; +$config['graphite']['port'] = 2003; // this defaults to 2003 and is usually not needed +$config['graphite']['prefix'] = 'your.metric.prefix'; +``` + +Your metric path can be prefixed if required, otherwise the metric path for Graphite will be in the form of +`hostname.measurement.fieldname`, interfaces will be stored as `hostname.ports.ifName.fieldname`. + +The same data then stored within rrd will be sent to Graphite and recorded. You can then create graphs within Grafana +to display the information you need. + +### Graphite Configuration +As LibreNMS updates its metrics every 5 minutes, the following addition to your storage-schemas.conf is suggested. + +``` +[network] +pattern = your\.metric\.prefix\..* +retentions = 5m:30d,15m:90d,1h:1y +``` diff --git a/includes/datastore.inc.php b/includes/datastore.inc.php index 9f4a5518b2..f352fa2b47 100644 --- a/includes/datastore.inc.php +++ b/includes/datastore.inc.php @@ -67,4 +67,5 @@ function data_update($device, $measurement, $tags, $fields) rrdtool_data_update($device, $measurement, $tags, $fields); influx_update($device, $measurement, rrd_array_filter($tags), $fields); + graphite_update($device, $measurement, $tags, $fields); } // data_update diff --git a/includes/defaults.inc.php b/includes/defaults.inc.php index 4162618d4f..9afa7192fe 100644 --- a/includes/defaults.inc.php +++ b/includes/defaults.inc.php @@ -397,7 +397,7 @@ $config['network_map_vis_options'] = '{ "damping": 0.4, "avoidOverlap": 1 }, - + "repulsion": { "centralGravity": 0.2, "springLength": 250, @@ -413,7 +413,7 @@ $config['network_map_vis_options'] = '{ "springConstant": 0.2, "damping": 0.07 }, - + "maxVelocity": 50, "minVelocity": 0.4, "solver": "hierarchicalRepulsion", @@ -905,3 +905,6 @@ $config['influxdb']['verifySSL'] = false; // Xirrus - Disable station/client polling if true as it may take a long time on larger/heavily used APs. $config['xirrus_disable_stations'] = false; + +// Graphite default port +$config['graphite']['port'] = 2003; diff --git a/includes/graphite.inc.php b/includes/graphite.inc.php new file mode 100644 index 0000000000..0d9a71be58 --- /dev/null +++ b/includes/graphite.inc.php @@ -0,0 +1,44 @@ + + * + * 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. + */ + +function graphite_update($device, $measurement, $tags, $fields) +{ + global $graphite, $config; + if ($graphite !== false) { + $timestamp = time(); + $graphite_prefix = $config['graphite']['prefix']; + // metrics will be built as prefix.hostname.measurement.field value timestamp + // metric fields can not contain . as this is used by graphite as a field separator + $hostname = preg_replace('/\./', '_', $device['hostname']); + $measurement = preg_replace(array('/\./', '/\//'), '_', $measurement); + $measurement = preg_replace('/\|/', '.', $measurement); + $measurement_name = preg_replace('/\./', '_', $tags['rrd_name']); + if (is_array($measurement_name)) { + $ms_name = implode(".", $measurement_name); + } else { + $ms_name = $measurement_name; + } + // remove the port-id tags from the metric + if (preg_match('/^port-id\d+/', $ms_name)) { + $ms_name = ""; + } + + foreach ($fields as $k => $v) { + $metric = implode(".", array_filter(array($graphite_prefix, $hostname, $measurement, $ms_name, $k))); + $line = implode(" ", array($metric, $v, $timestamp)); + d_echo("Sending $line\n"); + fwrite($graphite, $line . "\n"); + } + } +} diff --git a/includes/init.php b/includes/init.php index e30d37c089..8ccad05697 100644 --- a/includes/init.php +++ b/includes/init.php @@ -47,6 +47,7 @@ require_once $install_dir . '/includes/common.php'; require $install_dir . '/includes/dbFacile.php'; require $install_dir . '/includes/rrdtool.inc.php'; require $install_dir . '/includes/influxdb.inc.php'; +require $install_dir . '/includes/graphite.inc.php'; require $install_dir . '/includes/datastore.inc.php'; require $install_dir . '/includes/billing.php'; require $install_dir . '/includes/syslog.php'; diff --git a/includes/polling/ports.inc.php b/includes/polling/ports.inc.php index 6c0869a8fc..ca09f54cc5 100644 --- a/includes/polling/ports.inc.php +++ b/includes/polling/ports.inc.php @@ -751,6 +751,7 @@ foreach ($ports as $port) { $fields['ifOutOctets_rate'] = $port['ifOutOctets_rate']; influx_update($device, 'ports', rrd_array_filter($tags), $fields); + graphite_update($device, 'ports|' . $ifName, $tags, $fields); // End Update IF-MIB // Update PAgP diff --git a/poller.php b/poller.php index a20342eda1..5499669a7a 100755 --- a/poller.php +++ b/poller.php @@ -110,12 +110,28 @@ if (isset($options['f'])) { $config['noinfluxdb'] = true; } +if (isset($options['g'])) { + $config['nographite'] = true; +} + if ($config['noinfluxdb'] !== true && $config['influxdb']['enable'] === true) { $influxdb = influxdb_connect(); } else { $influxdb = false; } +if ($config['nographite'] !== true && $config['graphite']['enable'] === true) { + $graphite = fsockopen($config['graphite']['host'], $config['graphite']['port']); + if ($graphite !== false) { + echo "Connection made to {$config['graphite']['host']} for Graphite support\n"; + } else { + echo "Connection to {$config['graphite']['host']} has failed, Graphite support disabled\n"; + $config['nographite'] = true; + } +} else { + $graphite = false; +} + rrdtool_initialize(); echo "Starting polling run:\n\n"; @@ -141,6 +157,10 @@ $poller_end = microtime(true); $poller_run = ($poller_end - $poller_start); $poller_time = substr($poller_run, 0, 5); +if ($graphite !== false) { + fclose($graphite); +} + if ($polled_devices) { dbInsert(array('type' => 'poll', 'doing' => $doing, 'start' => $poller_start, 'duration' => $poller_time, 'devices' => $polled_devices, 'poller' => $config['distributed_poller_name'] ), 'perf_times'); }