configfile = CONFIG_DIR + "python.d.conf"
msg.PROGRAM = PROGRAM
msg.info("reading configuration file:", configfile)
- log_counter = 200
+ log_throttle = 200
log_interval = 3600
conf = read_config(configfile)
except (KeyError, TypeError):
pass
try:
- log_counter = conf['logs_per_interval']
+ log_throttle = conf['logs_per_interval']
except (KeyError, TypeError):
pass
try:
# parse passed command line arguments
modules = parse_cmdline(MODULES_DIR, *sys.argv)
msg.DEBUG_FLAG = DEBUG_FLAG
- msg.LOG_COUNTER = log_counter
+ msg.LOG_THROTTLE = log_throttle
msg.LOG_INTERVAL = log_interval
+ msg.LOG_COUNTER = 0
+ msg.LOG_NEXT_CHECK = 0
msg.info("MODULES_DIR='" + MODULES_DIR +
"', CONFIG_DIR='" + CONFIG_DIR +
"', UPDATE_EVERY=" + str(BASE_CONFIG['update_every']) +
t_start = time.time()
timetable = self.timetable
chart_name = self.chart_name
+
# check if it is time to execute job update() function
if timetable['next'] > t_start:
self.debug(chart_name, "will be run in", str(int((timetable['next'] - t_start) * 1000)), "ms")
"ready to run, after", str(int((t_start - timetable['last']) * 1000)),
"ms (update_every:", str(timetable['freq'] * 1000),
"ms, latency:", str(int((t_start - timetable['next']) * 1000)), "ms")
+
if self.__first_run:
since_last = 0
+
if not self.update(since_last):
self.error("update function failed.")
return False
+
t_end = time.time()
self.timetable['next'] = t_end - (t_end % timetable['freq']) + timetable['freq']
+
# draw performance graph
run_time = str(int((t_end - t_start) * 1000))
# noinspection SqlNoDataSourceInspection
print("BEGIN netdata.plugin_pythond_%s %s\nSET run_time = %s\nEND\n" %
(self.chart_name, str(since_last), run_time))
- # sys.stdout.write("BEGIN netdata.plugin_pythond_%s %s\nSET run_time = %s\nEND\n" %
- # (self.chart_name, str(since_last), run_time))
self.debug(chart_name, "updated in", str(run_time), "ms")
self.timetable['last'] = t_start
:return: None
"""
self.timetable['last'] = time.time()
+ self.debug("starting data collection - update frequency: " + str(self.update_every) + ", retries allowed: " + str(self.retries))
while True: # run forever, unless something is wrong
try:
status = self._run_once()
except Exception as e:
- self.error("Something wrong: ", str(e))
+ self.alert("internal error - aborting data collection: " + str(e))
return
+
if status: # handle retries if update failed
time.sleep(self.timetable['next'] - time.time())
self.retries_left = self.retries
else:
self.retries_left -= 1
if self.retries_left <= 0:
- self.error("no more retries. Exiting")
+ self.alert("failed to collect data - no more retries allowed - aborting data collection")
return
else:
+ self.error("failed to collect data. " + str(self.retries_left) + " retries left.")
time.sleep(self.timetable['freq'])
# --- CHART ---
"""
msg.error(self.chart_name, *params)
+ def alert(self, *params):
+ """
+ Show error message on stderr
+ """
+ msg.alert(self.chart_name, *params)
+
def debug(self, *params):
"""
Show debug message on stderr
self.__empty_request = "".encode()
SimpleService.__init__(self, configuration=configuration, name=name)
- def _socketerror(self, msg=None):
+ def _socketerror(self, message=None):
if self.unix_socket is not None:
- self.error("unix socket '" + self.unix_socket + "':", msg)
+ self.error("unix socket '" + self.unix_socket + "':", message)
else:
if self.__socket_config is not None:
af, socktype, proto, canonname, sa = self.__socket_config
- self.error("socket to '" + str(sa[0]) + "' port " + str(sa[1]) + ":", msg)
+ self.error("socket to '" + str(sa[0]) + "' port " + str(sa[1]) + ":", message)
else:
- self.error("unknown socket:", msg)
+ self.error("unknown socket:", message)
def _connect2socket(self, res=None):
"""
try:
self.log_path = str(self.configuration['path'])
except (KeyError, TypeError):
- self.error("No path to log specified. Using: '" + self.log_path + "'")
+ self.info("No path to log specified. Using: '" + self.log_path + "'")
if os.access(self.log_path, os.R_OK):
return True
try:
self.command = str(self.configuration['command'])
except (KeyError, TypeError):
- self.error("No command specified. Using: '" + self.command + "'")
+ self.info("No command specified. Using: '" + self.command + "'")
command = self.command.split(' ')
for arg in command[1:]:
if any(st in arg for st in self.bad_substrings):
self.error("Bad command argument:" + " ".join(self.command[1:]))
return False
+
# test command and search for it in /usr/sbin or /sbin when failed
base = command[0].split('/')[-1]
if self._get_raw_data() is None:
command[0] = prefix + base
if os.path.isfile(command[0]):
break
+
self.command = command
if self._get_data() is None or len(self._get_data()) == 0:
self.error("Command", self.command, "returned no data")
return False
+
return True
DEBUG_FLAG = False
PROGRAM = ""
-LOG_COUNTER = 2
-LOG_INTERVAL = 5
-NEXT_CHECK = 0
+LOG_COUNTER = 0
+LOG_THROTTLE = 10000 # has to be too big during init
+LOG_INTERVAL = 1 # has to be too low during init
+LOG_NEXT_CHECK = 0
WRITE = sys.stderr.write
FLUSH = sys.stderr.flush
:param msg_type: str
"""
global LOG_COUNTER
- if not DEBUG_FLAG:
- LOG_COUNTER -= 1
+ global LOG_THROTTLE
+ global LOG_INTERVAL
+ global LOG_NEXT_CHECK
now = time()
- if LOG_COUNTER >= 0:
+
+ if not DEBUG_FLAG:
+ LOG_COUNTER += 1
+
+ # WRITE("COUNTER " + str(LOG_COUNTER) + " THROTTLE " + str(LOG_THROTTLE) + " INTERVAL " + str(LOG_INTERVAL) + " NOW " + str(now) + " NEXT " + str(LOG_NEXT_CHECK) + "\n")
+
+ if LOG_COUNTER <= LOG_THROTTLE or msg_type == "FATAL" or msg_type == "ALERT":
timestamp = strftime('%Y-%m-%d %X')
msg = "%s: %s %s: %s" % (timestamp, PROGRAM, str(msg_type), " ".join(args))
WRITE(msg + "\n")
FLUSH()
+ elif LOG_COUNTER == LOG_THROTTLE + 1:
+ timestamp = strftime('%Y-%m-%d %X')
+ msg = "%s: python.d.plugin: throttling further log messages for %s seconds" % (timestamp, str(int(LOG_NEXT_CHECK + 0.5) - int(now)))
+ WRITE(msg + "\n")
+ FLUSH()
- global NEXT_CHECK
- if NEXT_CHECK <= now:
- NEXT_CHECK = now - (now % LOG_INTERVAL) + LOG_INTERVAL
- if LOG_COUNTER < 0:
+ if LOG_NEXT_CHECK <= now:
+ if LOG_COUNTER >= LOG_THROTTLE:
timestamp = strftime('%Y-%m-%d %X')
- msg = "%s: python.d.plugin: Prevented %s log messages from displaying" % (timestamp, str(0 - LOG_COUNTER))
+ msg = "%s: python.d.plugin: Prevented %s log messages from displaying" % (timestamp, str(LOG_COUNTER - LOG_THROTTLE))
WRITE(msg + "\n")
FLUSH()
+ LOG_NEXT_CHECK = now - (now % LOG_INTERVAL) + LOG_INTERVAL
+ LOG_COUNTER = 0
+
def debug(*args):
log_msg("ERROR", *args)
+def alert(*args):
+ """
+ Print message on stderr.
+ """
+ log_msg("ALERT", *args)
+
+
def info(*args):
"""
Print message on stderr.
# using sys.stdout causes IOError: Broken Pipe
print('DISABLE')
# sys.stdout.write('DISABLE\n')
- sys.exit(1)
\ No newline at end of file
+ sys.exit(1)