import importlib.machinery
import configparser
+
class PythonCharts(object):
- def __init__(self,interval=1,modules=[],modules_path='../python.d/',modules_configs='../conf.d/'):
+
+ def __init__(self,
+ interval=1,
+ modules=[],
+ modules_path='../python.d/',
+ modules_configs='../conf.d/'):
self.interval = interval
# check if plugin directory exists
if not os.path.isdir(modules_path):
- debug("cannot find charts directory ",modules_path)
+ debug("cannot find charts directory ", modules_path)
sys.exit(1)
- self.configs=modules_configs
-
+ self.configs = modules_configs
+
self.modules = []
if len(modules) > 0:
for m in modules:
- self.modules.append(self.import_plugin(modules_path+m+".chart.py"))
+ self.modules.append(
+ self.import_plugin(
+ modules_path + m + ".chart.py"))
else:
self.load_modules(modules_path)
if len(self.modules) == 0:
- debug("cannot find charts directory",modules_path)
-# sys.stdout.write("DISABLE")
+ debug("cannot find modules directory", modules_path)
+ # sys.stdout.write("DISABLE\n")
sys.exit(1)
self.load_configs()
- # set last execution dict
+ # set last execution and execution frequency dict
self.timetable = {}
- t = time.time()
+ #last_exec = time.time()
+ last_exec = 0
for m in self.modules:
- self.timetable[m.__name__] = t
+ try:
+ interval = m.update_every
+ except AttributeError:
+ interval = self.interval
+ self.timetable[m.__name__] = [last_exec, int(interval)]
- def import_plugin(self,path,name=None):
+ def import_plugin(self, path, name=None):
if name is None:
name = path.split('/')[-1]
if name[-9:] != ".chart.py":
- return None
- name=name[:-9]
+ return None
+ name = name[:-9]
try:
- return importlib.machinery.SourceFileLoader(name,path).load_module()
- except FileNotFoundError:
+ return importlib.machinery.SourceFileLoader(name, path).load_module()
+ except Exception as e:
+ debug(str(e))
return None
- def load_modules(self,path):
+ def load_modules(self, path):
names = os.listdir(path)
for mod in names:
- m = self.import_plugin(path+mod)
+ m = self.import_plugin(path + mod)
if m is not None:
- debug("loading chart: '"+path+mod+"'")
+ debug("loading chart: '" + path + mod + "'")
self.modules.append(m)
def load_configs(self):
for m in self.modules:
- if os.path.isfile(self.configs+m.__name__+".conf"):
- debug("loading chart options: '"+self.configs+m.__name__+".conf'")
- for k,v in read_config(self.configs+m.__name__+".conf").items():
- setattr(m,k,v)
+ configfile = self.configs + m.__name__ + ".conf"
+ if os.path.isfile(configfile):
+ debug("loading chart options: '" + configfile + "'")
+ for k, v in read_config(configfile).items():
+ setattr(m, k, v)
else:
- debug(m.__name__+": configuration file '"+self.configs+m.__name__+".conf' not found. Using defaults.")
+ debug(
+ m.__name__ +
+ ": configuration file '" +
+ configfile +
+ "' not found. Using defaults.")
- def disable_module(self,mod,reason=None):
+ def disable_module(self, mod, reason=None):
self.modules.remove(mod)
del self.timetable[mod.__name__]
if reason is None:
return
elif reason[:3] == "no ":
- debug("chart '"+ mod.__name__,"' does not seem to have "+reason[3:]+"() function. Disabling it.")
+ debug(
+ "chart '" +
+ mod.__name__,
+ "' does not seem to have " +
+ reason[3:] +
+ "() function. Disabling it.")
elif reason[:7] == "failed ":
- debug("chart '"+mod.__name__+reason[3:]+"() function. reports failure.")
+ debug(
+ "chart '" +
+ mod.__name__ +
+ reason[3:] +
+ "() function. reports failure.")
elif reason[:13] == "configuration":
- debug(mod.__name__,"configuration file '"+self.configs+mod.__name__+".conf' not found. Using defaults.")
+ debug(
+ mod.__name__,
+ "configuration file '" +
+ self.configs +
+ mod.__name__ +
+ ".conf' not found. Using defaults.")
elif reason[:11] == "misbehaving":
- debug(mod.__name__,"is misbeaving. Disabling it")
- #sys.stdout.write('DISABLE')
-
+ debug(mod.__name__, "is misbeaving. Disabling it")
+ # sys.stdout.write('DISABLE')
def check(self):
for mod in self.modules:
try:
if not mod.check():
- self.disable_module(mod,"failed check")
+ self.disable_module(mod, "failed check")
except AttributeError:
- self.disable_module(mod,"no check")
+ self.disable_module(mod, "no check")
except UnboundLocalError:
- self.disable_module(mod,"misbehaving")
+ self.disable_module(mod, "misbehaving")
def create(self):
for mod in self.modules:
try:
if not mod.create():
- self.disable_module(mod,"failed create")
+ self.disable_module(mod, "failed create")
else:
- chart=mod.__name__
- sys.stdout.write("CHART netdata.plugin_pythond_"+chart+" '' 'Execution time for "+chart+" plugin' 'milliseconds / run' python.d netdata.plugin_python area 145000 "+str(self.interval)+'\n')
- sys.stdout.write("DIMENSION run_time 'run time' absolute 1 1\n\n")
+ chart = mod.__name__
+ # sys.stdout.write("CHART netdata.plugin_pythond_"+chart+" '' 'Execution time for "+chart+" plugin' 'milliseconds / run' python.d netdata.plugin_python area 145000 "+str(self.interval)+'\n')
+ sys.stdout.write(
+ "CHART netdata.plugin_pythond_" +
+ chart +
+ " '' 'Execution time for " +
+ chart +
+ " plugin' 'milliseconds / run' python.d netdata.plugin_python area 145000 " +
+ str(self.timetable[mod.__name__][1]) +
+ '\n')
+ sys.stdout.write(
+ "DIMENSION run_time 'run time' absolute 1 1\n\n")
sys.stdout.flush()
except AttributeError:
- self.disable_module(mod,"no create")
+ self.disable_module(mod, "no create")
except UnboundLocalError:
- self.disable_module(mod,"misbehaving")
+ self.disable_module(mod, "misbehaving")
- def update_module(self,mod):
+ def update_module(self, mod):
t1 = time.time()
+ # check if it is time to execute module update() function
+ if (t1 - self.timetable[mod.__name__][0]) < self.timetable[mod.__name__][1]:
+ return
try:
-# t=int((t1- self.timetable[mod.__name__]) * 1000)
-# if t == 0: t=""
- t = "" #FIXME
+ # t=int((t1- self.timetable[mod.__name__][0]) * 1000)
+ # if t == 0: t=""
+ t = "" # FIXME
if not mod.update(t):
-# if not mod.update(int((t1- self.timetable[mod.__name__]) * 1000)):
+ # if not mod.update(int((t1- self.timetable[mod.__name__][0]) *
+ # 1000)):
self.disable_module(mod, "update failed")
return
except AttributeError:
self.disable_module(mod, "no update")
return
except UnboundLocalError:
- self.disable_module(mod,"misbehaving")
+ self.disable_module(mod, "misbehaving")
return
t2 = time.time()
-# dt = int((t2 - self.timetable[mod.__name__]) * 1000)
+# dt = int((t2 - self.timetable[mod.__name__][0]) * 1000)
# if dt == 0: dt=""
- dt="" #FIXME
- sys.stdout.write("BEGIN netdata.plugin_pythond_"+mod.__name__+" "+str(dt)+'\n')
- sys.stdout.write("SET run_time = "+str(int((t2 - t1)*1000))+'\n')
+ # dt="" #FIXME
+ #sys.stdout.write("BEGIN netdata.plugin_pythond_"+mod.__name__+" "+str(dt)+'\n')
+ sys.stdout.write("BEGIN netdata.plugin_pythond_" + mod.__name__ + "\n")
+ sys.stdout.write("SET run_time = " + str(int((t2 - t1) * 1000)) + '\n')
sys.stdout.write("END\n")
sys.stdout.flush()
- self.timetable[mod.__name__] = t1
+ self.timetable[mod.__name__][0] = t1
def update(self):
while True:
t_begin = time.time()
for mod in self.modules:
self.update_module(mod)
- time.sleep(self.interval - (time.time()-t_begin))
-
+ time.sleep((self.interval - (time.time() - t_begin)) / 2)
+
def read_config(path):
- #TODO make it bulletproof
+ # TODO make it bulletproof
config = configparser.ConfigParser()
config_str = ""
try:
with open(path, 'r', encoding="utf_8") as f:
config_str = '[config]\n' + f.read()
except IsADirectoryError:
- debug(str(path),"is a directory")
+ debug(str(path), "is a directory")
return
config.read_string(config_str)
return dict(config.items('config'))
+
def debug(*args):
if not DEBUG_FLAG:
return
- sys.stderr.write(PROGRAM+":")
+ sys.stderr.write(PROGRAM + ":")
for i in args:
- sys.stderr.write(" "+str(i))
+ sys.stderr.write(" " + str(i))
sys.stderr.write("\n")
sys.stderr.flush()
-def parse_cmdline(directory,*commands):
+
+def parse_cmdline(directory, *commands):
global DEBUG_FLAG, PROGRAM
- DEBUG_FLAG=False
+ DEBUG_FLAG = False
mods = []
for cmd in commands[1:]:
if cmd == "check":
pass
elif cmd == "debug" or cmd == "all":
- DEBUG_FLAG=True
+ DEBUG_FLAG = True
# redirect stderr to stdout?
- elif os.path.isfile(directory+cmd+".chart.py") or os.path.isfile(directory+cmd):
- DEBUG_FLAG=True
- mods.append(cmd.replace(".chart.py",""))
+ elif os.path.isfile(directory + cmd + ".chart.py") or os.path.isfile(directory + cmd):
+ DEBUG_FLAG = True
+ mods.append(cmd.replace(".chart.py", ""))
PROGRAM = commands[0].split('/')[-1].split('.plugin')[0]
- debug("started from",commands[0],"with options:",*commands[1:])
+ debug("started from", commands[0], "with options:", *commands[1:])
return mods
-#if __name__ == '__main__':
+
+# if __name__ == '__main__':
def run():
# parse env variables
# https://github.com/firehol/netdata/wiki/External-Plugins#environment-variables
- main_dir = os.getenv('NETDATA_PLUGINS_DIR',os.path.abspath(__file__).strip("python.d.plugin.py"))
- config_dir = os.getenv('NETDATA_CONFIG_DIR',"/etc/netdata/")
+ main_dir = os.getenv('NETDATA_PLUGINS_DIR',
+ os.path.abspath(__file__).strip("python.d.plugin.py"))
+ config_dir = os.getenv('NETDATA_CONFIG_DIR', "/etc/netdata/")
# logs_dir = os.getenv('NETDATA_LOGS_DIR',None) #TODO logging?
- interval = int(os.getenv('NETDATA_UPDATE_EVERY',1))
+ interval = int(os.getenv('NETDATA_UPDATE_EVERY', 1))
# read configuration file
if config_dir[-1] != '/':
if str(conf['enable']) == "no":
debug("disabled in configuration file")
sys.exit(1)
- except (KeyError,TypeError): pass
- try: modules_conf = conf['plugins_config_dir']
- except (KeyError,TypeError): modules_conf = config_dir # default configuration directory
- try: modules_dir = conf['plugins_dir']
- except (KeyError,TypeError): modules_dir = main_dir.replace("plugins.d","python.d")
- try: interval = int(conf['interval'])
- except (KeyError,TypeError): pass # default interval
+ except (KeyError, TypeError):
+ pass
+ try:
+ modules_conf = conf['plugins_config_dir']
+ except (KeyError, TypeError):
+ modules_conf = config_dir # default configuration directory
+ try:
+ modules_dir = conf['plugins_dir']
+ except (KeyError, TypeError):
+ modules_dir = main_dir.replace("plugins.d", "python.d")
+ try:
+ interval = int(conf['interval'])
+ except (KeyError, TypeError):
+ pass # default interval
global DEBUG_FLAG
- try: DEBUG_FLAG = bool(conf['debug'])
- except (KeyError,TypeError): pass
+ try:
+ DEBUG_FLAG = bool(conf['debug'])
+ except (KeyError, TypeError):
+ pass
except FileNotFoundError:
modules_conf = config_dir
- modules_dir = main_dir.replace("plugins.d","python.d")
+ modules_dir = main_dir.replace("plugins.d", "python.d")
# directories should end with '/'
- if modules_dir[-1] != '/': modules_dir+="/"
- if modules_conf[-1] != '/': modules_conf+="/"
+ if modules_dir[-1] != '/':
+ modules_dir += "/"
+ if modules_conf[-1] != '/':
+ modules_conf += "/"
# parse passed command line arguments
- modules = parse_cmdline(modules_dir,*sys.argv)
+ modules = parse_cmdline(modules_dir, *sys.argv)
# run plugins
- charts = PythonCharts(interval,modules,modules_dir,modules_conf)
+ charts = PythonCharts(interval, modules, modules_dir, modules_conf)
charts.check()
charts.create()
charts.update()