From ebc41ada45388a65458b708b5c51438e32b98cdd Mon Sep 17 00:00:00 2001 From: jokob-sk Date: Mon, 8 Sep 2025 08:11:33 +1000 Subject: [PATCH] logger Signed-off-by: jokob-sk --- server/logger.py | 129 ++++++++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 69 deletions(-) diff --git a/server/logger.py b/server/logger.py index 958fdd4a..b82bca99 100755 --- a/server/logger.py +++ b/server/logger.py @@ -7,7 +7,6 @@ import time import logging # NetAlertX imports - import conf from const import * @@ -39,87 +38,80 @@ debugLevels = [ # use the LOG_LEVEL from the config, may be overridden currentLevel = conf.LOG_LEVEL -# tracking log levels -setLvl = 0 -reqLvl = 0 +#------------------------------------------------------------------------------- +# Queue for log messages +log_queue = queue.Queue(maxsize=1000) # Increase size to handle spikes +log_thread = None # Will hold the thread reference #------------------------------------------------------------------------------- -class Logger: - def __init__(self, LOG_LEVEL): - global currentLevel - - currentLevel = LOG_LEVEL - conf.LOG_LEVEL = currentLevel - - # Automatically set up custom logging handler - self.setup_logging() - - def setup_logging(self): - root_logger = logging.getLogger() - # Clear existing handlers to prevent duplicates - if root_logger.hasHandlers(): - root_logger.handlers.clear() - - # Create the custom handler - my_log_handler = MyLogHandler() - # my_log_handler.setLevel(custom_to_logging_levels.get(currentLevel, logging.NOTSET)) - - # Optional: Add a formatter for consistent log message format - # formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') - formatter = logging.Formatter('%(message)s', datefmt='%H:%M:%S') - my_log_handler.setFormatter(formatter) - - # Attach the handler to the root logger - root_logger.addHandler(my_log_handler) - root_logger.setLevel(custom_to_logging_levels.get(currentLevel, logging.NOTSET)) - -# for python logging +# Custom logging handler class MyLogHandler(logging.Handler): def emit(self, record): log_entry = self.format(record) log_queue.put(log_entry) -def mylog(requestedDebugLevel, n): - global setLvl, reqLvl +#------------------------------------------------------------------------------- +# Logger class +class Logger: + def __init__(self, LOG_LEVEL): + global currentLevel + currentLevel = LOG_LEVEL + conf.LOG_LEVEL = currentLevel - # Get debug urgency/relative weight - for lvl in debugLevels: - if currentLevel == lvl[0]: - setLvl = lvl[1] - if requestedDebugLevel == lvl[0]: - reqLvl = lvl[1] + # Numeric weights + self.setLvl = self._to_num(LOG_LEVEL) + self.reqLvl = None - if reqLvl <= setLvl: - file_print (*n) + # Setup Python logging + self.setup_logging() + + def _to_num(self, level_str): + for lvl in debugLevels: + if level_str == lvl[0]: + return lvl[1] + return None + + def setup_logging(self): + root_logger = logging.getLogger() + if root_logger.hasHandlers(): + root_logger.handlers.clear() + + my_log_handler = MyLogHandler() + formatter = logging.Formatter('%(message)s', datefmt='%H:%M:%S') + my_log_handler.setFormatter(formatter) + + root_logger.addHandler(my_log_handler) + root_logger.setLevel(custom_to_logging_levels.get(currentLevel, logging.NOTSET)) + + def mylog(self, requestedDebugLevel, *args): + self.reqLvl = self._to_num(requestedDebugLevel) + if self.reqLvl is not None and self.reqLvl <= self.setLvl: + file_print(*args) + + def isAbove(self, requestedDebugLevel): + reqLvl = self._to_num(requestedDebugLevel) + return reqLvl is not None and self.setLvl >= reqLvl #------------------------------------------------------------------------------- -# Queue for log messages -log_queue = queue.Queue(maxsize=1000) # Increase size to handle spikes - # Dedicated thread for writing logs -log_thread = None # Will hold the thread reference - def log_writer(): buffer = [] while True: try: - log_entry = log_queue.get(timeout=1) # Wait for 1 second for logs - if log_entry is None: # Graceful exit signal + log_entry = log_queue.get(timeout=1) + if log_entry is None: break buffer.append(log_entry) - if len(buffer) >= 10: # Write in batches of 10 + if len(buffer) >= 10: with open(logPath + "/app.log", 'a') as log_file: log_file.write('\n'.join(buffer) + '\n') buffer.clear() except queue.Empty: - # Flush buffer periodically if no new logs if buffer: with open(logPath + "/app.log", 'a') as log_file: log_file.write('\n'.join(buffer) + '\n') buffer.clear() -#------------------------------------------------------------------------------- -# Function to start the log writer thread if it doesn't exist def start_log_writer_thread(): global log_thread if log_thread is None or not log_thread.is_alive(): @@ -128,40 +120,39 @@ def start_log_writer_thread(): #------------------------------------------------------------------------------- def file_print(*args): - result = timeNowTZ().strftime('%H:%M:%S') + ' ' - - for arg in args: - result += str(arg) + result = timeNowTZ().strftime('%H:%M:%S') + ' ' + for arg in args: + result += str(arg) - logging.log(custom_to_logging_levels.get(currentLevel, logging.NOTSET), result) # Forward to Python's logging system + logging.log(custom_to_logging_levels.get(currentLevel, logging.NOTSET), result) print(result) - # Ensure the log writer thread is running start_log_writer_thread() - #------------------------------------------------------------------------------- def append_file_binary(file_path, input_data): with open(file_path, 'ab') as file: if isinstance(input_data, str): - input_data = input_data.encode('utf-8') # Encode string as bytes + input_data = input_data.encode('utf-8') file.write(input_data) -#------------------------------------------------------------------------------- def logResult(stdout, stderr): if stderr is not None: append_file_binary(logPath + '/stderr.log', stderr) if stdout is not None: append_file_binary(logPath + '/stdout.log', stdout) -#------------------------------------------------------------------------------- def append_line_to_file(pPath, pText): - # append the line using the correct python version if sys.version_info < (3, 0): file = io.open(pPath, mode='a', encoding='utf-8') file.write(pText.decode('unicode_escape')) - file.close() + file.close() else: - file = open(pPath, 'a', encoding='utf-8') + file = open(pPath, 'a', encoding='utf-8') file.write(pText) - file.close() + file.close() + +#------------------------------------------------------------------------------- +# Create default logger instance and backward-compatible global mylog +logger = Logger(conf.LOG_LEVEL) +mylog = logger.mylog