mirror of
https://github.com/nicolargo/glances.git
synced 2024-12-27 19:25:27 +03:00
Merge branch 'feature/issue455' into develop
Conflicts: NEWS
This commit is contained in:
commit
f042b46042
2
NEWS
2
NEWS
@ -5,6 +5,8 @@ Glances Version 2.x
|
||||
Version 2.X
|
||||
===========
|
||||
|
||||
* Add a new InfluxDB export module (--export-influxdb) (issue #455)
|
||||
* Refactor export module (CSV export option is now --export-csv). It is now possible to export stats from the Glances client (issue #463)
|
||||
* The Web inteface is now based on BootStarp / RWD grid (issue #417, #366 and #461) Thanks to Nicolas Hart @nclsHart
|
||||
* Add the RAID plugins (issue #447)
|
||||
|
||||
|
@ -143,3 +143,10 @@ server_3_alias=Another PC on my network
|
||||
server_3_port=61209
|
||||
server_4_name=pasbon
|
||||
server_4_port=61237
|
||||
|
||||
[influxdb]
|
||||
host=localhost
|
||||
port=8086
|
||||
user=root
|
||||
password=root
|
||||
db=glances
|
||||
|
@ -143,3 +143,10 @@ mem_critical=90
|
||||
#server_3_port=61209
|
||||
#server_4_name=pasbon
|
||||
#server_4_port=61237
|
||||
|
||||
[influxdb]
|
||||
host=localhost
|
||||
port=8086
|
||||
user=root
|
||||
password=root
|
||||
db=glances
|
||||
|
@ -136,7 +136,7 @@ class GlancesClient(object):
|
||||
|
||||
if self.get_mode() == 'glances' and version.split('.')[0] == client_version.split('.')[0]:
|
||||
# Init stats
|
||||
self.stats = GlancesStatsClient()
|
||||
self.stats = GlancesStatsClient(config=self.config, args=self.args)
|
||||
self.stats.set_plugins(json.loads(self.client.getAllPlugins()))
|
||||
logger.debug(
|
||||
"Client version: %s / Server version: %s" % (version, client_version))
|
||||
@ -153,7 +153,7 @@ class GlancesClient(object):
|
||||
from glances.core.glances_stats import GlancesStatsClientSNMP
|
||||
|
||||
# Init stats
|
||||
self.stats = GlancesStatsClientSNMP(args=self.args)
|
||||
self.stats = GlancesStatsClientSNMP(config=self.config, args=self.args)
|
||||
|
||||
if not self.stats.check_snmp():
|
||||
self.log_and_exit("Connection to SNMP server failed")
|
||||
@ -234,6 +234,9 @@ class GlancesClient(object):
|
||||
cs_status=cs_status,
|
||||
return_to_browser=self.return_to_browser)
|
||||
|
||||
# Export stats using export modules
|
||||
self.stats.export(self.stats)
|
||||
|
||||
return self.get_mode()
|
||||
|
||||
def end(self):
|
||||
|
@ -94,6 +94,8 @@ class GlancesMain(object):
|
||||
# Export modules feature
|
||||
parser.add_argument('--export-csv', default=None,
|
||||
dest='export_csv', help=_('export stats to a CSV file'))
|
||||
parser.add_argument('--export-influxdb', action='store_true', default=False,
|
||||
dest='export_influxdb', help=_('export stats to an InfluxDB server'))
|
||||
# Client/Server option
|
||||
parser.add_argument('-c', '--client', dest='client',
|
||||
help=_('connect to a Glances server by IPv4/IPv6 address or hostname'))
|
||||
|
@ -118,14 +118,15 @@ class GlancesStats(object):
|
||||
item.endswith(".py") and
|
||||
item != (header + "export.py") and
|
||||
item != (header + "history.py") and
|
||||
args_var['export_' + export_name] is not None):
|
||||
args_var['export_' + export_name] is not None and
|
||||
args_var['export_' + export_name] is not False):
|
||||
# Import the export module
|
||||
export_module = __import__(os.path.basename(item)[:-3])
|
||||
# Add the export to the dictionary
|
||||
# The key is the module name
|
||||
# for example, the file glances_xxx.py
|
||||
# generate self._exports_list["xxx"] = ...
|
||||
self._exports[export_name] = export_module.Export(args=args)
|
||||
self._exports[export_name] = export_module.Export(args=args, config=self.config)
|
||||
# Log plugins list
|
||||
logger.debug("Available exports modules list: {0}".format(self.getAllExports()))
|
||||
return True
|
||||
@ -251,11 +252,22 @@ class GlancesStatsClient(GlancesStats):
|
||||
|
||||
"""This class stores, updates and gives stats for the client."""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the GlancesStatsClient class."""
|
||||
# Init the plugin list dict
|
||||
self._plugins = collections.defaultdict(dict)
|
||||
|
||||
# Init the configuration
|
||||
self.config = config
|
||||
|
||||
# Init the arguments
|
||||
self.args = args
|
||||
|
||||
# Init the export modules list dict
|
||||
self._exports = collections.defaultdict(dict)
|
||||
# Load the plugins
|
||||
self.load_exports(args=args)
|
||||
|
||||
def set_plugins(self, input_plugins):
|
||||
"""Set the plugin list according to the Glances server."""
|
||||
header = "glances_"
|
||||
@ -292,6 +304,11 @@ class GlancesStatsClientSNMP(GlancesStats):
|
||||
# Load plugins
|
||||
self.load_plugins(args=self.args)
|
||||
|
||||
# Init the export modules list dict
|
||||
self._exports = collections.defaultdict(dict)
|
||||
# Load the plugins
|
||||
self.load_exports(args=args)
|
||||
|
||||
def check_snmp(self):
|
||||
"""Chek if SNMP is available on the server."""
|
||||
# Import the SNMP client class
|
||||
|
@ -28,18 +28,14 @@ from glances.core.glances_globals import is_py3
|
||||
from glances.core.glances_logging import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
|
||||
# List of stats enabled in the CSV output
|
||||
# !!! TODO: should be configurable from the conf file
|
||||
csv_stats_list = ['cpu', 'load', 'mem', 'memswap', 'network', 'diskio', 'fs']
|
||||
|
||||
|
||||
class Export(GlancesExport):
|
||||
|
||||
"""This class manages the CSV export module."""
|
||||
|
||||
def __init__(self, args=None):
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the CSV export IF."""
|
||||
GlancesExport.__init__(self, args=args)
|
||||
GlancesExport.__init__(self, config=config, args=args)
|
||||
|
||||
# CSV file name
|
||||
self.csv_filename = args.export_csv
|
||||
@ -61,6 +57,7 @@ class Export(GlancesExport):
|
||||
|
||||
def exit(self):
|
||||
"""Close the CSV file."""
|
||||
logger.debug("Finalise export interface %s" % self.export_name)
|
||||
self.csv_file.close()
|
||||
|
||||
def update(self, stats):
|
||||
@ -75,7 +72,7 @@ class Export(GlancesExport):
|
||||
# Loop over available plugin
|
||||
i = 0
|
||||
for plugin in plugins:
|
||||
if plugin in csv_stats_list:
|
||||
if plugin in self.plugins_to_export():
|
||||
if type(all_stats[i]) is list:
|
||||
for item in all_stats[i]:
|
||||
# First line: header
|
||||
|
@ -34,11 +34,20 @@ class GlancesExport(object):
|
||||
|
||||
"""Main class for Glances' export IF."""
|
||||
|
||||
def __init__(self, args=None):
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the export class."""
|
||||
# Export name (= module name without glances_)
|
||||
self.export_name = self.__class__.__module__[len('glances_'):]
|
||||
logger.debug("Init export interface %s" % self.export_name)
|
||||
|
||||
# Init the args
|
||||
# Init the config & args
|
||||
self.config = config
|
||||
self.args = args
|
||||
|
||||
def exit(self):
|
||||
"""Close the export module."""
|
||||
logger.debug("Finalise export interface %s" % self.export_name)
|
||||
|
||||
def plugins_to_export(self):
|
||||
"""Return the list of plugins to export"""
|
||||
return ['cpu', 'load', 'mem', 'memswap', 'network', 'diskio', 'fs', 'processcount']
|
||||
|
135
glances/exports/glances_influxdb.py
Normal file
135
glances/exports/glances_influxdb.py
Normal file
@ -0,0 +1,135 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
# Copyright (C) 2014 Nicolargo <nicolas@nicolargo.com>
|
||||
#
|
||||
# Glances is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Glances 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""InfluxDB interface class."""
|
||||
|
||||
# Import sys libs
|
||||
from influxdb import InfluxDBClient, client
|
||||
import sys
|
||||
|
||||
# Import Glances lib
|
||||
from glances.core.glances_globals import is_py3
|
||||
from glances.core.glances_logging import logger
|
||||
from ConfigParser import NoSectionError, NoOptionError
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
|
||||
|
||||
class Export(GlancesExport):
|
||||
|
||||
"""This class manages the InfluxDB export module."""
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the CSV export IF."""
|
||||
GlancesExport.__init__(self, config=config, args=args)
|
||||
|
||||
# Load the InfluxDB configuration file
|
||||
self.influxdb_host = None
|
||||
self.influxdb_port = None
|
||||
self.influxdb_user = None
|
||||
self.influxdb_password = None
|
||||
self.influxdb_db = None
|
||||
self.export_enable = self.load_conf()
|
||||
if not self.export_enable:
|
||||
sys.exit(2)
|
||||
|
||||
# Init the InfluxDB client
|
||||
self.client = self.init()
|
||||
|
||||
def load_conf(self, section="influxdb"):
|
||||
"""Load the InfluxDb configuration in the Glances configuration file"""
|
||||
if self.config is None:
|
||||
return False
|
||||
try:
|
||||
self.influxdb_host = self.config.get_raw_option(section, "host")
|
||||
self.influxdb_port = self.config.get_raw_option(section, "port")
|
||||
self.influxdb_user = self.config.get_raw_option(section, "user")
|
||||
self.influxdb_password = self.config.get_raw_option(section, "password")
|
||||
self.influxdb_db = self.config.get_raw_option(section, "db")
|
||||
except NoSectionError:
|
||||
logger.critical("No InfluxDB configuration found")
|
||||
return False
|
||||
except NoOptionError as e:
|
||||
logger.critical("Error in the InfluxDB configuration (%s)" % e)
|
||||
return False
|
||||
else:
|
||||
logger.debug("Load InfluxDB from the Glances configuration file")
|
||||
return True
|
||||
|
||||
def init(self):
|
||||
"""Init the connection to the InfluxDB server"""
|
||||
if not self.export_enable:
|
||||
return None
|
||||
db = InfluxDBClient(self.influxdb_host,
|
||||
self.influxdb_port,
|
||||
self.influxdb_user,
|
||||
self.influxdb_password,
|
||||
self.influxdb_db)
|
||||
try:
|
||||
get_all_db = db.get_database_list()[0].values()
|
||||
except client.InfluxDBClientError as e:
|
||||
logger.critical("Can not connect to InfluxDB database '%s' (%s)" % (self.influxdb_db, e))
|
||||
sys.exit(2)
|
||||
|
||||
if self.influxdb_db in get_all_db:
|
||||
logger.info(
|
||||
"Stats will be exported to InfluxDB server: {0}".format(db._baseurl))
|
||||
else:
|
||||
logger.critical("InfluxDB database '%s' did not exist. Please create it" % self.influxdb_db)
|
||||
sys.exit(2)
|
||||
return db
|
||||
|
||||
def update(self, stats):
|
||||
"""Update stats to the InfluxDB server."""
|
||||
if not self.export_enable:
|
||||
return False
|
||||
|
||||
# Get the stats
|
||||
all_stats = stats.getAll()
|
||||
plugins = stats.getAllPlugins()
|
||||
|
||||
# Loop over available plugin
|
||||
i = 0
|
||||
for plugin in plugins:
|
||||
if plugin in self.plugins_to_export():
|
||||
if type(all_stats[i]) is list:
|
||||
for item in all_stats[i]:
|
||||
export_names = map(
|
||||
lambda x: item[item['key']] + '_' + x, item.keys())
|
||||
export_values = item.values()
|
||||
self.write_to_influxdb(plugin, export_names, export_values)
|
||||
elif type(all_stats[i]) is dict:
|
||||
export_names = all_stats[i].keys()
|
||||
export_values = all_stats[i].values()
|
||||
self.write_to_influxdb(plugin, export_names, export_values)
|
||||
i += 1
|
||||
|
||||
return True
|
||||
|
||||
def write_to_influxdb(self, name, columns, points):
|
||||
"""Write the points to the InfluxDB server"""
|
||||
data = [
|
||||
{
|
||||
"name": name,
|
||||
"columns": columns,
|
||||
"points": [points]
|
||||
}]
|
||||
try:
|
||||
self.client.write_points(data)
|
||||
except Exception as e:
|
||||
logger.critical("Can not export stats to InfluxDB (%s)" % e)
|
Loading…
Reference in New Issue
Block a user