--- /dev/null
+#!/usr/bin/python
+###############################################################################
+# #
+# collecty - A system statistics collection daemon for IPFire #
+# Copyright (C) 2012 IPFire development team #
+# #
+# 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/>. #
+# #
+###############################################################################
+
+import collecty
+
+client = collecty.CollectyClient()
+
+for type in ("cpu", "entropy", "memory", "loadavg"):
+ for interval in ("day", "week", "year"):
+ client.graph(type, "%s-%s.png" % (type, interval), interval)
# #
###############################################################################
-import signal
-import time
-
-import ConfigParser as configparser
-
-import plugins
-
-from i18n import _
-
# Initialize logging.
import logging
log = logging.getLogger("collecty")
formatter = logging.Formatter("%(asctime)s | %(name)-20s - %(levelname)-6s | %(message)s")
handler.setFormatter(formatter)
-class ConfigError(Exception):
- pass
-
-class Collecty(object):
- # The default interval, when all data is written to disk.
- SUBMIT_INTERVAL = 300
-
- def __init__(self):
- self.config = configparser.ConfigParser()
- self.instances = []
-
- # Indicates whether this process should be running or not.
- self.running = True
- self.timer = plugins.Timer(self.SUBMIT_INTERVAL, heartbeat=2)
-
- # Add all automatic plugins.
- self.add_autocreate_plugins()
-
- log.info(_("Collecty successfully initialized."))
-
- def add_autocreate_plugins(self):
- for plugin in plugins.registered_plugins:
- if not hasattr(plugin, "autocreate"):
- continue
-
- ret = plugin.autocreate(self)
- if not ret:
- continue
-
- if not type(ret) == type([]):
- ret = [ret,]
-
- log.debug(_("Plugin '%(name)s' registered %(number)s instance(s).") % \
- { "name" : plugin.name, "number" : len(ret) })
-
- self.instances += ret
-
- def read_config(self, config):
- self.config.read(config)
-
- for section in self.config.sections():
- try:
- plugin = self.config.get(section, "plugin")
- plugin = plugins.find(plugin)
- except configparser.NoOptionError:
- raise ConfigError, "Syntax error in configuration: plugin option is missing."
- except:
- raise Exception, "Plugin configuration error: Maybe plugin wasn't found? %s" % plugin
-
- kwargs = {}
- for (key, value) in self.config.items(section):
- if key == "plugin":
- continue
-
- kwargs[key] = value
- kwargs["file"] = section
-
- i = plugin(self, **kwargs)
- self.instances.append(i)
-
- def run(self):
- # Register signal handlers.
- self.register_signal_handler()
-
- # Start all plugin instances.
- for i in self.instances:
- i.start()
-
- # Regularly submit all data to disk.
- while self.running:
- if self.timer.wait():
- self.submit_all()
-
- # Wait until all instances are finished.
- while self.instances:
- for instance in self.instances[:]:
- if not instance.isAlive():
- log.debug(_("%s is not alive anymore. Removing.") % instance)
- self.instances.remove(instance)
-
- # Wait a bit.
- time.sleep(0.1)
-
- log.debug(_("No thread running. Exiting main thread."))
-
- def submit_all(self):
- """
- Submit all data right now.
- """
- log.debug(_("Submitting all data in memory"))
- for i in self.instances:
- i._submit()
-
- # Schedule the next submit.
- self.timer.reset()
-
- def shutdown(self):
- log.debug(_("Received shutdown signal"))
-
- self.running = False
- if self.timer:
- self.timer.cancel()
-
- # Propagating shutdown to all threads.
- for i in self.instances:
- i.shutdown()
-
- def register_signal_handler(self):
- for s in (signal.SIGTERM, signal.SIGINT, signal.SIGUSR1):
- log.debug(_("Registering signal %d") % s)
-
- signal.signal(s, self.signal_handler)
-
- def signal_handler(self, sig, *args, **kwargs):
- log.info(_("Caught signal %d") % sig)
-
- if sig in (signal.SIGTERM, signal.SIGINT):
- # Shutdown this application.
- self.shutdown()
-
- elif sig == signal.SIGUSR1:
- # Submit all data.
- self.submit_all()
+from client import CollectyClient
+from daemon import Collecty
--- /dev/null
+#!/usr/bin/python
+###############################################################################
+# #
+# collecty - A system statistics collection daemon for IPFire #
+# Copyright (C) 2012 IPFire development team #
+# #
+# 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/>. #
+# #
+###############################################################################
+
+import daemon
+
+import logging
+log = logging.getLogger("collectly.client")
+
+class CollectyClient(object):
+ def __init__(self, **settings):
+ self.collecty = daemon.Collecty(**settings)
+
+ @property
+ def instances(self):
+ return self.collecty.instances
+
+ def get_instance_by_id(self, id):
+ for instance in self.instances:
+ if not instance.id == id:
+ continue
+
+ return instance
+
+ def graph(self, id, filename, interval=None, **kwargs):
+ instance = self.get_instance_by_id(id)
+ assert instance, "Could not find instance: %s" % id
+
+ instance.graph(filename, interval=interval, **kwargs)
# #
###############################################################################
+from i18n import _
+
DATABASE_DIR = "/var/lib/collecty"
+
+GRAPH_DEFAULT_ARGUMENTS = [
+ # Always generate graphs in PNG format.
+ "--imgformat", "PNG",
+
+ # Disable the border around the image.
+ "--border", "0",
+
+ # Let's width and height define the size of
+ # the entire image.
+ "--full-size-mode",
+
+ # Gives the curves a more organic look.
+ "--slope-mode",
+
+ # Show nicer labels.
+ "--dynamic-labels",
+
+ # Brand all generated graphs.
+ "--watermark", _("Created by collecty"),
+]
+
+GRAPH_DEFAULT_WIDTH = 768
+GRAPH_DEFAULT_HEIGHT = 480
--- /dev/null
+#!/usr/bin/python
+###############################################################################
+# #
+# collecty - A system statistics collection daemon for IPFire #
+# Copyright (C) 2012 IPFire development team #
+# #
+# 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/>. #
+# #
+###############################################################################
+
+import signal
+
+import ConfigParser as configparser
+
+import plugins
+
+from constants import *
+from i18n import _
+
+import logging
+log = logging.getLogger("collecty")
+
+class Collecty(object):
+ # The default interval, when all data is written to disk.
+ SUBMIT_INTERVAL = 300
+
+ def __init__(self, debug=False):
+ self.config = configparser.ConfigParser()
+ self.instances = []
+
+ # Indicates whether this process should be running or not.
+ self.running = True
+ self.timer = plugins.Timer(self.SUBMIT_INTERVAL, heartbeat=2)
+
+ # Add all automatic plugins.
+ self.add_autocreate_plugins()
+
+ log.info(_("Collecty successfully initialized."))
+
+ def add_autocreate_plugins(self):
+ for plugin in plugins.registered_plugins:
+ if not hasattr(plugin, "autocreate"):
+ continue
+
+ ret = plugin.autocreate(self)
+ if not ret:
+ continue
+
+ if not type(ret) == type([]):
+ ret = [ret,]
+
+ log.debug(_("Plugin '%(name)s' registered %(number)s instance(s).") % \
+ { "name" : plugin.name, "number" : len(ret) })
+
+ self.instances += ret
+
+ def read_config(self, config):
+ self.config.read(config)
+
+ for section in self.config.sections():
+ try:
+ plugin = self.config.get(section, "plugin")
+ plugin = plugins.find(plugin)
+ except configparser.NoOptionError:
+ raise ConfigError, "Syntax error in configuration: plugin option is missing."
+ except:
+ raise Exception, "Plugin configuration error: Maybe plugin wasn't found? %s" % plugin
+
+ kwargs = {}
+ for (key, value) in self.config.items(section):
+ if key == "plugin":
+ continue
+
+ kwargs[key] = value
+ kwargs["file"] = section
+
+ i = plugin(self, **kwargs)
+ self.instances.append(i)
+
+ def run(self):
+ # Register signal handlers.
+ self.register_signal_handler()
+
+ # Start all plugin instances.
+ for i in self.instances:
+ i.start()
+
+ # Regularly submit all data to disk.
+ while self.running:
+ if self.timer.wait():
+ self.submit_all()
+
+ # Wait until all instances are finished.
+ while self.instances:
+ for instance in self.instances[:]:
+ if not instance.isAlive():
+ log.debug(_("%s is not alive anymore. Removing.") % instance)
+ self.instances.remove(instance)
+
+ # Wait a bit.
+ time.sleep(0.1)
+
+ log.debug(_("No thread running. Exiting main thread."))
+
+ def submit_all(self):
+ """
+ Submit all data right now.
+ """
+ log.debug(_("Submitting all data in memory"))
+ for i in self.instances:
+ i._submit()
+
+ # Schedule the next submit.
+ self.timer.reset()
+
+ def shutdown(self):
+ log.debug(_("Received shutdown signal"))
+
+ self.running = False
+ if self.timer:
+ self.timer.cancel()
+
+ # Propagating shutdown to all threads.
+ for i in self.instances:
+ i.shutdown()
+
+ def register_signal_handler(self):
+ for s in (signal.SIGTERM, signal.SIGINT, signal.SIGUSR1):
+ log.debug(_("Registering signal %d") % s)
+
+ signal.signal(s, self.signal_handler)
+
+ def signal_handler(self, sig, *args, **kwargs):
+ log.info(_("Caught signal %d") % sig)
+
+ if sig in (signal.SIGTERM, signal.SIGINT):
+ # Shutdown this application.
+ self.shutdown()
+
+ elif sig == signal.SIGUSR1:
+ # Submit all data.
+ self.submit_all()
+
+ @property
+ def graph_default_arguments(self):
+ return GRAPH_DEFAULT_ARGUMENTS
--- /dev/null
+#!/usr/bin/python
+###############################################################################
+# #
+# collecty - A system statistics collection daemon for IPFire #
+# Copyright (C) 2012 IPFire development team #
+# #
+# 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/>. #
+# #
+###############################################################################
+
+class CollectyError(Exception):
+ pass
+
+class ConfigError(CollectyError):
+ pass
# The schema of the RRD database.
rrd_schema = None
+ # Instructions how to create the graph.
+ rrd_graph = None
+
+ # Extra arguments passed to rrdgraph.
+ rrd_graph_args = []
+
# The default interval of this plugin.
default_interval = 60
def __str__(self):
return "Plugin %s %s" % (self.name, self.file)
+ @property
+ def id(self):
+ """
+ A unique ID of the plugin instance.
+ """
+ return self.name
+
@property
def interval(self):
"""
"""
return int(time.time())
- def graph(self, file, interval=None):
- args = [ "--imgformat", "PNG",
- "-w", "580", # Width of the graph
- "-h", "240", # Height of the graph
- "--interlaced", "--slope-mode", ]
+ def graph(self, file, interval=None,
+ width=GRAPH_DEFAULT_WIDTH, height=GRAPH_DEFAULT_HEIGHT):
+
+ args = [
+ "--width", "%d" % width,
+ "--height", "%d" % height,
+ ]
+ args += self.collecty.graph_default_arguments
+ args += self.rrd_graph_args
- intervals = { None : "-3h",
- "hour" : "-1h",
- "day" : "-25h",
- "week" : "-360h" }
+ intervals = {
+ None : "-3h",
+ "hour" : "-1h",
+ "day" : "-25h",
+ "week" : "-360h",
+ "year" : "-365d",
+ }
args.append("--start")
if intervals.has_key(interval):
args.append(interval)
info = { "file" : self.file }
- for item in self._graph:
+ for item in self.rrd_graph:
try:
args.append(item % info)
except TypeError:
args.append(item)
- rrdtool.graph(file, *args)
+ rrdtool.graph(file, *args)
"RRA:AVERAGE:0.5:60:8760",
]
- _graph = [ "DEF:user=%(file)s:user:AVERAGE",
- "DEF:nice=%(file)s:nice:AVERAGE",
- "DEF:sys=%(file)s:sys:AVERAGE",
- "DEF:idle=%(file)s:idle:AVERAGE",
- "DEF:wait=%(file)s:wait:AVERAGE",
- "DEF:interrupt=%(file)s:interrupt:AVERAGE",
- "AREA:user#ff0000:%-15s" % _("User"),
- "VDEF:usermin=user,MINIMUM",
- "VDEF:usermax=user,MAXIMUM",
- "VDEF:useravg=user,AVERAGE",
- "GPRINT:usermax:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:usermin:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:useravg:%12s\:" % _("Average") + " %6.2lf\\n",
- "STACK:nice#ff3300:%-15s" % _("Nice"),
- "VDEF:nicemin=nice,MINIMUM",
- "VDEF:nicemax=nice,MAXIMUM",
- "VDEF:niceavg=nice,AVERAGE",
- "GPRINT:nicemax:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:nicemin:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:niceavg:%12s\:" % _("Average") + " %6.2lf\\n",
- "STACK:sys#ff6600:%-15s" % _("System"),
- "VDEF:sysmin=sys,MINIMUM",
- "VDEF:sysmax=sys,MAXIMUM",
- "VDEF:sysavg=sys,AVERAGE",
- "GPRINT:sysmax:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:sysmin:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:sysavg:%12s\:" % _("Average") + " %6.2lf\\n",
- "STACK:wait#ff9900:%-15s" % _("Wait"),
- "VDEF:waitmin=wait,MINIMUM",
- "VDEF:waitmax=wait,MAXIMUM",
- "VDEF:waitavg=wait,AVERAGE",
- "GPRINT:waitmax:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:waitmin:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:waitavg:%12s\:" % _("Average") + " %6.2lf\\n",
- "STACK:interrupt#ffcc00:%-15s" % _("Interrupt"),
- "VDEF:interruptmin=interrupt,MINIMUM",
- "VDEF:interruptmax=interrupt,MAXIMUM",
- "VDEF:interruptavg=interrupt,AVERAGE",
- "GPRINT:interruptmax:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:interruptmin:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:interruptavg:%12s\:" % _("Average") + " %6.2lf\\n",
- "STACK:idle#ffff00:%-15s" % _("Idle"),
- "VDEF:idlemin=idle,MINIMUM",
- "VDEF:idlemax=idle,MAXIMUM",
- "VDEF:idleavg=idle,AVERAGE",
- "GPRINT:idlemax:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:idlemin:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:idleavg:%12s\:" % _("Average") + " %6.2lf\\n", ]
+ rrd_graph = [
+ "DEF:user=%(file)s:user:AVERAGE",
+ "DEF:nice=%(file)s:nice:AVERAGE",
+ "DEF:sys=%(file)s:sys:AVERAGE",
+ "DEF:idle=%(file)s:idle:AVERAGE",
+ "DEF:wait=%(file)s:wait:AVERAGE",
+ "DEF:irq=%(file)s:irq:AVERAGE",
+ "DEF:sirq=%(file)s:sirq:AVERAGE",
+
+ "AREA:user#90EE90:%-15s" % _("User"),
+ "VDEF:usermin=user,MINIMUM",
+ "VDEF:usermax=user,MAXIMUM",
+ "VDEF:useravg=user,AVERAGE",
+ "GPRINT:usermax:%12s\:" % _("Maximum") + " %6.2lf" ,
+ "GPRINT:usermin:%12s\:" % _("Minimum") + " %6.2lf",
+ "GPRINT:useravg:%12s\:" % _("Average") + " %6.2lf\\n",
+
+ "STACK:nice#4169E1:%-15s" % _("Nice"),
+ "VDEF:nicemin=nice,MINIMUM",
+ "VDEF:nicemax=nice,MAXIMUM",
+ "VDEF:niceavg=nice,AVERAGE",
+ "GPRINT:nicemax:%12s\:" % _("Maximum") + " %6.2lf" ,
+ "GPRINT:nicemin:%12s\:" % _("Minimum") + " %6.2lf",
+ "GPRINT:niceavg:%12s\:" % _("Average") + " %6.2lf\\n",
+
+ "STACK:sys#DC143C:%-15s" % _("System"),
+ "VDEF:sysmin=sys,MINIMUM",
+ "VDEF:sysmax=sys,MAXIMUM",
+ "VDEF:sysavg=sys,AVERAGE",
+ "GPRINT:sysmax:%12s\:" % _("Maximum") + " %6.2lf" ,
+ "GPRINT:sysmin:%12s\:" % _("Minimum") + " %6.2lf",
+ "GPRINT:sysavg:%12s\:" % _("Average") + " %6.2lf\\n",
+
+ "STACK:wait#483D8B:%-15s" % _("Wait"),
+ "VDEF:waitmin=wait,MINIMUM",
+ "VDEF:waitmax=wait,MAXIMUM",
+ "VDEF:waitavg=wait,AVERAGE",
+ "GPRINT:waitmax:%12s\:" % _("Maximum") + " %6.2lf" ,
+ "GPRINT:waitmin:%12s\:" % _("Minimum") + " %6.2lf",
+ "GPRINT:waitavg:%12s\:" % _("Average") + " %6.2lf\\n",
+
+ "STACK:irq#DAA520:%-15s" % _("Interrupt"),
+ "VDEF:irqmin=irq,MINIMUM",
+ "VDEF:irqmax=irq,MAXIMUM",
+ "VDEF:irqavg=irq,AVERAGE",
+ "GPRINT:irqmax:%12s\:" % _("Maximum") + " %6.2lf" ,
+ "GPRINT:irqmin:%12s\:" % _("Minimum") + " %6.2lf",
+ "GPRINT:irqavg:%12s\:" % _("Average") + " %6.2lf\\n",
+
+ "STACK:sirq#FFD700:%-15s" % _("Soft interrupt"),
+ "VDEF:sirqmin=sirq,MINIMUM",
+ "VDEF:sirqmax=sirq,MAXIMUM",
+ "VDEF:sirqavg=sirq,AVERAGE",
+ "GPRINT:sirqmax:%12s\:" % _("Maximum") + " %6.2lf" ,
+ "GPRINT:sirqmin:%12s\:" % _("Minimum") + " %6.2lf",
+ "GPRINT:sirqavg:%12s\:" % _("Average") + " %6.2lf\\n",
+
+# "STACK:idle#ffff00:%-15s" % _("Idle"),
+# "VDEF:idlemin=idle,MINIMUM",
+# "VDEF:idlemax=idle,MAXIMUM",
+# "VDEF:idleavg=idle,AVERAGE",
+# "GPRINT:idlemax:%12s\:" % _("Maximum") + " %6.2lf" ,
+# "GPRINT:idlemin:%12s\:" % _("Minimum") + " %6.2lf",
+# "GPRINT:idleavg:%12s\:" % _("Average") + " %6.2lf\\n",
+ ]
+
+ rrd_graph_args = [
+ "--title", _("CPU usage"),
+ "--vertical-label", _("Percent"),
+
+ # This can never be more than 100 percent.
+ #"--lower-limit", "0", "--upper-limit", "100",
+ ]
@classmethod
def autocreate(cls, collecty, **kwargs):
import base
+from ..i18n import _
+
ENTROPY_FILE = "/proc/sys/kernel/random/entropy_avail"
class PluginEntropy(base.Plugin):
"RRA:AVERAGE:0.5:60:8760",
]
+ rrd_graph = [
+ "DEF:entropy=%(file)s:entropy:AVERAGE",
+ "CDEF:entropytrend=entropy,43200,TREND",
+
+ "LINE3:entropy#ff0000:%-15s" % _("Available entropy"),
+ "VDEF:entrmin=entropy,MINIMUM",
+ "VDEF:entrmax=entropy,MAXIMUM",
+ "VDEF:entravg=entropy,AVERAGE",
+ "GPRINT:entrmax:%12s\:" % _("Maximum") + " %5.0lf",
+ "GPRINT:entrmin:%12s\:" % _("Minimum") + " %5.0lf",
+ "GPRINT:entravg:%12s\:" % _("Average") + " %5.0lf\\n",
+
+ "LINE3:entropytrend#000000",
+ ]
+ rrd_graph_args = [
+ "--title", _("Available entropy"),
+ "--vertical-label", _("Bits"),
+
+ "--lower-limit", "0", "--rigid",
+ ]
+
@classmethod
def autocreate(cls, collecty, **kwargs):
if not os.path.exists(ENTROPY_FILE):
"RRA:AVERAGE:0.5:60:8760",
]
- _graph = [ "DEF:load1=%(file)s:load1:AVERAGE",
- "DEF:load5=%(file)s:load5:AVERAGE",
- "DEF:load15=%(file)s:load15:AVERAGE",
- "AREA:load1#ff0000:%s" % _("Load average 1m"),
- "VDEF:load1min=load1,MINIMUM",
- "VDEF:load1max=load1,MAXIMUM",
- "VDEF:load1avg=load1,AVERAGE",
- "GPRINT:load1max:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:load1min:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:load1avg:%12s\:" % _("Average") + " %6.2lf\\n",
- "AREA:load5#ff9900:%s" % _("Load average 5m"),
- "VDEF:load5min=load5,MINIMUM",
- "VDEF:load5max=load5,MAXIMUM",
- "VDEF:load5avg=load5,AVERAGE",
- "GPRINT:load5max:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:load5min:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:load5avg:%12s\:" % _("Average") + " %6.2lf\\n",
- "AREA:load15#ffff00:%s" % _("Load average 15m"),
- "VDEF:load15min=load15,MINIMUM",
- "VDEF:load15max=load15,MAXIMUM",
- "VDEF:load15avg=load15,AVERAGE",
- "GPRINT:load15max:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:load15min:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:load15avg:%12s\:" % _("Average") + " %6.2lf\\n",
- "LINE:load5#dd8800",
- "LINE:load1#dd0000", ]
+ rrd_graph = [
+ "DEF:load1=%(file)s:load1:AVERAGE",
+ "DEF:load5=%(file)s:load5:AVERAGE",
+ "DEF:load15=%(file)s:load15:AVERAGE",
+
+ "AREA:load1#ff0000:%s" % _("Load average 1m"),
+ "VDEF:load1min=load1,MINIMUM",
+ "VDEF:load1max=load1,MAXIMUM",
+ "VDEF:load1avg=load1,AVERAGE",
+ "GPRINT:load1max:%12s\:" % _("Maximum") + " %6.2lf",
+ "GPRINT:load1min:%12s\:" % _("Minimum") + " %6.2lf",
+ "GPRINT:load1avg:%12s\:" % _("Average") + " %6.2lf\\n",
+
+ "AREA:load5#ff9900:%s" % _("Load average 5m"),
+ "VDEF:load5min=load5,MINIMUM",
+ "VDEF:load5max=load5,MAXIMUM",
+ "VDEF:load5avg=load5,AVERAGE",
+ "GPRINT:load5max:%12s\:" % _("Maximum") + " %6.2lf",
+ "GPRINT:load5min:%12s\:" % _("Minimum") + " %6.2lf",
+ "GPRINT:load5avg:%12s\:" % _("Average") + " %6.2lf\\n",
+
+ "AREA:load15#ffff00:%s" % _("Load average 15m"),
+ "VDEF:load15min=load15,MINIMUM",
+ "VDEF:load15max=load15,MAXIMUM",
+ "VDEF:load15avg=load15,AVERAGE",
+ "GPRINT:load15max:%12s\:" % _("Maximum") + " %6.2lf",
+ "GPRINT:load15min:%12s\:" % _("Minimum") + " %6.2lf",
+ "GPRINT:load15avg:%12s\:" % _("Average") + " %6.2lf\\n",
+
+ "LINE:load5#dd8800",
+ "LINE:load1#dd0000",
+ ]
+ rrd_graph_args = [
+ "--title", _("Load average"),
+ "--vertical-label", _("Load"),
+
+ "--lower-limit", "0", "--rigid",
+ ]
@classmethod
def autocreate(cls, collecty, **kwargs):
"RRA:AVERAGE:0.5:60:8760",
]
- _graph = [ "DEF:used=%(file)s:used:AVERAGE",
- "DEF:cached=%(file)s:cached:AVERAGE",
- "DEF:buffered=%(file)s:buffered:AVERAGE",
- "DEF:free=%(file)s:free:AVERAGE",
- "DEF:swap=%(file)s:swap:AVERAGE",
- "AREA:used#0000ee:%-15s" % _("Used memory"),
- "VDEF:usedmin=used,MINIMUM",
- "VDEF:usedmax=used,MAXIMUM",
- "VDEF:usedavg=used,AVERAGE",
- "GPRINT:usedmax:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:usedmin:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:usedavg:%12s\:" % _("Average") + " %6.2lf\\n",
- "STACK:cached#0099ee:%-15s" % _("Cached data"),
- "VDEF:cachedmin=cached,MINIMUM",
- "VDEF:cachedmax=cached,MAXIMUM",
- "VDEF:cachedavg=cached,AVERAGE",
- "GPRINT:cachedmax:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:cachedmin:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:cachedavg:%12s\:" % _("Average") + " %6.2lf\\n",
- "STACK:buffered#4499ff:%-15s" % _("Buffered data"),
- "VDEF:bufferedmin=buffered,MINIMUM",
- "VDEF:bufferedmax=buffered,MAXIMUM",
- "VDEF:bufferedavg=buffered,AVERAGE",
- "GPRINT:bufferedmax:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:bufferedmin:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:bufferedavg:%12s\:" % _("Average") + " %6.2lf\\n",
- "STACK:free#7799ff:%-15s" % _("Free memory"),
- "VDEF:freemin=free,MINIMUM",
- "VDEF:freemax=free,MAXIMUM",
- "VDEF:freeavg=free,AVERAGE",
- "GPRINT:freemax:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:freemin:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:freeavg:%12s\:" % _("Average") + " %6.2lf\\n",
- "LINE3:swap#ff0000:%-15s" % _("Used Swap space"),
- "VDEF:swapmin=swap,MINIMUM",
- "VDEF:swapmax=swap,MAXIMUM",
- "VDEF:swapavg=swap,AVERAGE",
- "GPRINT:swapmax:%12s\:" % _("Maximum") + " %6.2lf" ,
- "GPRINT:swapmin:%12s\:" % _("Minimum") + " %6.2lf",
- "GPRINT:swapavg:%12s\:" % _("Average") + " %6.2lf\\n", ]
+ rrd_graph = [
+ "DEF:used=%(file)s:used:AVERAGE",
+ "DEF:cached=%(file)s:cached:AVERAGE",
+ "DEF:buffered=%(file)s:buffered:AVERAGE",
+ "DEF:free=%(file)s:free:AVERAGE",
+ "DEF:swap=%(file)s:swap:AVERAGE",
+
+ "AREA:used#90EE90:%-15s" % _("Used memory"),
+ "VDEF:usedmin=used,MINIMUM",
+ "VDEF:usedmax=used,MAXIMUM",
+ "VDEF:usedavg=used,AVERAGE",
+ "GPRINT:usedmax:%12s\:" % _("Maximum") + " %6.2lf" ,
+ "GPRINT:usedmin:%12s\:" % _("Minimum") + " %6.2lf",
+ "GPRINT:usedavg:%12s\:" % _("Average") + " %6.2lf\\n",
+
+ "STACK:buffered#4169E1:%-15s" % _("Buffered data"),
+ "VDEF:bufferedmin=buffered,MINIMUM",
+ "VDEF:bufferedmax=buffered,MAXIMUM",
+ "VDEF:bufferedavg=buffered,AVERAGE",
+ "GPRINT:bufferedmax:%12s\:" % _("Maximum") + " %6.2lf" ,
+ "GPRINT:bufferedmin:%12s\:" % _("Minimum") + " %6.2lf",
+ "GPRINT:bufferedavg:%12s\:" % _("Average") + " %6.2lf\\n",
+
+ "STACK:cached#FFD700:%-15s" % _("Cached data"),
+ "VDEF:cachedmin=cached,MINIMUM",
+ "VDEF:cachedmax=cached,MAXIMUM",
+ "VDEF:cachedavg=cached,AVERAGE",
+ "GPRINT:cachedmax:%12s\:" % _("Maximum") + " %6.2lf" ,
+ "GPRINT:cachedmin:%12s\:" % _("Minimum") + " %6.2lf",
+ "GPRINT:cachedavg:%12s\:" % _("Average") + " %6.2lf\\n",
+
+# "STACK:free#7799ff:%-15s" % _("Free memory"),
+# "VDEF:freemin=free,MINIMUM",
+# "VDEF:freemax=free,MAXIMUM",
+# "VDEF:freeavg=free,AVERAGE",
+# "GPRINT:freemax:%12s\:" % _("Maximum") + " %6.2lf" ,
+# "GPRINT:freemin:%12s\:" % _("Minimum") + " %6.2lf",
+# "GPRINT:freeavg:%12s\:" % _("Average") + " %6.2lf\\n",
+
+ "LINE3:swap#ff0000:%-15s" % _("Used Swap space"),
+ "VDEF:swapmin=swap,MINIMUM",
+ "VDEF:swapmax=swap,MAXIMUM",
+ "VDEF:swapavg=swap,AVERAGE",
+ "GPRINT:swapmax:%12s\:" % _("Maximum") + " %6.2lf" ,
+ "GPRINT:swapmin:%12s\:" % _("Minimum") + " %6.2lf",
+ "GPRINT:swapavg:%12s\:" % _("Average") + " %6.2lf\\n",
+ ]
+ rrd_graph_args = [
+ "--title", _("Memory Usage"),
+ "--vertical-label", _("Percent"),
+
+ # Limit y axis.
+ "--upper-limit", "100",
+ "--lower-limit", "0",
+ "--rigid",
+ ]
@classmethod
def autocreate(cls, collecty, **kwargs):
# Initialize the settings for this Collecty instance.
settings = {
- debug : options.debug,
+ "debug" : options.debug,
}
# Initialize the application.
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-08-08 08:55+0000\n"
+"POT-Creation-Date: 2012-08-25 11:22+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
-#: collecty/__init__.py:61
+#. Brand all generated graphs.
+#: collecty/constants.py:44
+msgid "Created by collecty"
+msgstr ""
+
+#: collecty/daemon.py:49
msgid "Collecty successfully initialized."
msgstr ""
-#: collecty/__init__.py:75
+#: collecty/daemon.py:63
#, python-format
msgid "Plugin '%(name)s' registered %(number)s instance(s)."
msgstr ""
-#: collecty/__init__.py:120
+#: collecty/daemon.py:108
#, python-format
msgid "%s is not alive anymore. Removing."
msgstr ""
-#: collecty/__init__.py:126
+#: collecty/daemon.py:114
msgid "No thread running. Exiting main thread."
msgstr ""
-#: collecty/__init__.py:132
+#: collecty/daemon.py:120
msgid "Submitting all data in memory"
msgstr ""
-#: collecty/__init__.py:140
+#: collecty/daemon.py:128
msgid "Received shutdown signal"
msgstr ""
-#: collecty/__init__.py:152
+#: collecty/daemon.py:140
#, python-format
msgid "Registering signal %d"
msgstr ""
-#: collecty/__init__.py:157
+#: collecty/daemon.py:145
#, python-format
msgid "Caught signal %d"
msgstr ""
-#: collecty/plugins/base.py:99
+#: collecty/plugins/base.py:105
msgid "Successfully initialized."
msgstr ""
-#: collecty/plugins/base.py:139
+#: collecty/plugins/base.py:152
#, python-format
msgid "Created RRD file %s."
msgstr ""
-#: collecty/plugins/base.py:166
+#: collecty/plugins/base.py:179
#, python-format
msgid "Submitting data to database. %d entries."
msgstr ""
-#: collecty/plugins/base.py:179
+#: collecty/plugins/base.py:192
msgid "Unhandled exception in read()!"
msgstr ""
-#: collecty/plugins/base.py:190
+#: collecty/plugins/base.py:203
msgid "Unhandled exception in submit()!"
msgstr ""
-#: collecty/plugins/base.py:193
+#: collecty/plugins/base.py:206
msgid "Started."
msgstr ""
-#: collecty/plugins/base.py:201
+#: collecty/plugins/base.py:214
msgid "Collecting..."
msgstr ""
-#: collecty/plugins/base.py:205
+#: collecty/plugins/base.py:218
msgid "Stopped."
msgstr ""
-#: collecty/plugins/base.py:208
+#: collecty/plugins/base.py:221
msgid "Received shutdown signal."
msgstr ""
-#: collecty/plugins/cpu.py:52
+#: collecty/plugins/cpu.py:55
msgid "User"
msgstr ""
-#: collecty/plugins/cpu.py:56 collecty/plugins/cpu.py:63
-#: collecty/plugins/cpu.py:70 collecty/plugins/cpu.py:77
-#: collecty/plugins/cpu.py:84 collecty/plugins/cpu.py:91
-#: collecty/plugins/loadavg.py:49 collecty/plugins/loadavg.py:56
-#: collecty/plugins/loadavg.py:63 collecty/plugins/memory.py:53
-#: collecty/plugins/memory.py:60 collecty/plugins/memory.py:67
-#: collecty/plugins/memory.py:74 collecty/plugins/memory.py:81
+#: collecty/plugins/cpu.py:59 collecty/plugins/cpu.py:67
+#: collecty/plugins/cpu.py:75 collecty/plugins/cpu.py:83
+#: collecty/plugins/cpu.py:91 collecty/plugins/cpu.py:99
+#: collecty/plugins/entropy.py:50 collecty/plugins/loadavg.py:51
+#: collecty/plugins/loadavg.py:59 collecty/plugins/loadavg.py:67
+#: collecty/plugins/memory.py:55 collecty/plugins/memory.py:63
+#: collecty/plugins/memory.py:71 collecty/plugins/memory.py:87
msgid "Maximum"
msgstr ""
-#: collecty/plugins/cpu.py:57 collecty/plugins/cpu.py:64
-#: collecty/plugins/cpu.py:71 collecty/plugins/cpu.py:78
-#: collecty/plugins/cpu.py:85 collecty/plugins/cpu.py:92
-#: collecty/plugins/loadavg.py:50 collecty/plugins/loadavg.py:57
-#: collecty/plugins/loadavg.py:64 collecty/plugins/memory.py:54
-#: collecty/plugins/memory.py:61 collecty/plugins/memory.py:68
-#: collecty/plugins/memory.py:75 collecty/plugins/memory.py:82
+#: collecty/plugins/cpu.py:60 collecty/plugins/cpu.py:68
+#: collecty/plugins/cpu.py:76 collecty/plugins/cpu.py:84
+#: collecty/plugins/cpu.py:92 collecty/plugins/cpu.py:100
+#: collecty/plugins/entropy.py:51 collecty/plugins/loadavg.py:52
+#: collecty/plugins/loadavg.py:60 collecty/plugins/loadavg.py:68
+#: collecty/plugins/memory.py:56 collecty/plugins/memory.py:64
+#: collecty/plugins/memory.py:72 collecty/plugins/memory.py:88
msgid "Minimum"
msgstr ""
-#: collecty/plugins/cpu.py:58 collecty/plugins/cpu.py:65
-#: collecty/plugins/cpu.py:72 collecty/plugins/cpu.py:79
-#: collecty/plugins/cpu.py:86 collecty/plugins/cpu.py:93
-#: collecty/plugins/loadavg.py:51 collecty/plugins/loadavg.py:58
-#: collecty/plugins/loadavg.py:65 collecty/plugins/memory.py:55
-#: collecty/plugins/memory.py:62 collecty/plugins/memory.py:69
-#: collecty/plugins/memory.py:76 collecty/plugins/memory.py:83
+#: collecty/plugins/cpu.py:61 collecty/plugins/cpu.py:69
+#: collecty/plugins/cpu.py:77 collecty/plugins/cpu.py:85
+#: collecty/plugins/cpu.py:93 collecty/plugins/cpu.py:101
+#: collecty/plugins/entropy.py:52 collecty/plugins/loadavg.py:53
+#: collecty/plugins/loadavg.py:61 collecty/plugins/loadavg.py:69
+#: collecty/plugins/memory.py:57 collecty/plugins/memory.py:65
+#: collecty/plugins/memory.py:73 collecty/plugins/memory.py:89
msgid "Average"
msgstr ""
-#: collecty/plugins/cpu.py:59
+#: collecty/plugins/cpu.py:63
msgid "Nice"
msgstr ""
-#: collecty/plugins/cpu.py:66
+#: collecty/plugins/cpu.py:71
msgid "System"
msgstr ""
-#: collecty/plugins/cpu.py:73
+#: collecty/plugins/cpu.py:79
msgid "Wait"
msgstr ""
-#: collecty/plugins/cpu.py:80
+#: collecty/plugins/cpu.py:87
msgid "Interrupt"
msgstr ""
-#: collecty/plugins/cpu.py:87
-msgid "Idle"
+#: collecty/plugins/cpu.py:95
+msgid "Soft interrupt"
+msgstr ""
+
+#: collecty/plugins/cpu.py:113
+msgid "CPU usage"
+msgstr ""
+
+#: collecty/plugins/cpu.py:114 collecty/plugins/memory.py:93
+msgid "Percent"
+msgstr ""
+
+#: collecty/plugins/entropy.py:46 collecty/plugins/entropy.py:57
+msgid "Available entropy"
+msgstr ""
+
+#: collecty/plugins/entropy.py:58
+msgid "Bits"
msgstr ""
-#: collecty/plugins/entropy.py:43
+#: collecty/plugins/entropy.py:66
msgid "Entropy kernel interface does not exist."
msgstr ""
-#: collecty/plugins/loadavg.py:45
+#: collecty/plugins/loadavg.py:47
msgid "Load average 1m"
msgstr ""
-#: collecty/plugins/loadavg.py:52
+#: collecty/plugins/loadavg.py:55
msgid "Load average 5m"
msgstr ""
-#: collecty/plugins/loadavg.py:59
+#: collecty/plugins/loadavg.py:63
msgid "Load average 15m"
msgstr ""
-#: collecty/plugins/memory.py:49
-msgid "Used memory"
+#: collecty/plugins/loadavg.py:75
+msgid "Load average"
msgstr ""
-#: collecty/plugins/memory.py:56
-msgid "Cached data"
+#: collecty/plugins/loadavg.py:76
+msgid "Load"
msgstr ""
-#: collecty/plugins/memory.py:63
+#: collecty/plugins/memory.py:51
+msgid "Used memory"
+msgstr ""
+
+#: collecty/plugins/memory.py:59
msgid "Buffered data"
msgstr ""
-#: collecty/plugins/memory.py:70
-msgid "Free memory"
+#: collecty/plugins/memory.py:67
+msgid "Cached data"
msgstr ""
-#: collecty/plugins/memory.py:77
+#. "STACK:free#7799ff:%-15s" % _("Free memory"),
+#. "VDEF:freemin=free,MINIMUM",
+#. "VDEF:freemax=free,MAXIMUM",
+#. "VDEF:freeavg=free,AVERAGE",
+#. "GPRINT:freemax:%12s\:" % _("Maximum") + " %6.2lf" ,
+#. "GPRINT:freemin:%12s\:" % _("Minimum") + " %6.2lf",
+#. "GPRINT:freeavg:%12s\:" % _("Average") + " %6.2lf\\n",
+#: collecty/plugins/memory.py:83
msgid "Used Swap space"
msgstr ""
+
+#: collecty/plugins/memory.py:92
+msgid "Memory Usage"
+msgstr ""