From f4ed623c76e491a792bd335df243c2640af7e383 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Sun, 5 Feb 2023 11:17:09 -0700 Subject: [PATCH] logging_handler.py: Add additional --- resources/logging_handler.py | 72 +++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/resources/logging_handler.py b/resources/logging_handler.py index 7991ee6cc..6d21c7d12 100644 --- a/resources/logging_handler.py +++ b/resources/logging_handler.py @@ -5,22 +5,42 @@ from pathlib import Path class InitializeLoggingSupport: + """ + Initialize logging framework for program + Primary responsibilities: + - Determine where to store log file + - Clean log file if it's near the max file size + - Initialize logging framework configuration + - Implement custom traceback handler + - Implement error handling for file write + + Usage: + >>> from resources.logging_handler import InitializeLoggingSupport + >>> InitializeLoggingSupport() + + """ def __init__(self) -> None: - self.log_filename: str = "OpenCore-Patcher.log" - + self.log_filename: str = "OpenCore-Patcher.log" self.log_filepath: Path = None + self.original_excepthook: sys = sys.excepthook + self.original_thread_excepthook: threading = threading.excepthook + self.max_file_size: int = 1024 * 1024 * 10 # 10 MB self.file_size_redline: int = 1024 * 1024 * 9 # 9 MB, when to start cleaning log file self._initialize_logging_path() self._clean_log_file() - self._initialize_logging_configuration() + self._attempt_initialize_logging_configuration() self._implement_custom_traceback_handler() + def __del__(self): + self._restore_original_excepthook() + + def _initialize_logging_path(self): """ Initialize logging framework storage path @@ -28,11 +48,12 @@ class InitializeLoggingSupport: self.log_filepath = Path(f"~/Library/Logs/{self.log_filename}").expanduser() - if self.log_filepath.parent.exists(): - return + if not self.log_filepath.parent.exists(): + # Likely in an installer environment, store in /Users/Shared + self.log_filepath = Path("/Users/Shared") / self.log_filename - # Likely in an installer environment, store in /Users/Shared - self.log_filepath = Path("/Users/Shared") / self.log_filename + print("- Initializing logging framework...") + print(f" - Log file: {self.log_filepath}") def _clean_log_file(self): @@ -50,14 +71,17 @@ class InitializeLoggingSupport: # Check if backup log file exists backup_log_filepath = self.log_filepath.with_suffix(".old.log") - if backup_log_filepath.exists(): - backup_log_filepath.unlink() + try: + if backup_log_filepath.exists(): + backup_log_filepath.unlink() - # Rename current log file to backup log file - self.log_filepath.rename(backup_log_filepath) + # Rename current log file to backup log file + self.log_filepath.rename(backup_log_filepath) + except Exception as e: + print(f"- Failed to clean log file: {e}") - def _initialize_logging_configuration(self): + def _initialize_logging_configuration(self, log_to_file: bool = True): """ Initialize logging framework configuration @@ -70,13 +94,27 @@ class InitializeLoggingSupport: format="%(asctime)s - %(filename)s (%(lineno)d): %(message)s", handlers=[ logging.StreamHandler(), - logging.FileHandler(self.log_filepath), + logging.FileHandler(self.log_filepath) if log_to_file is True else logging.NullHandler() ], ) logging.getLogger().setLevel(logging.INFO) logging.getLogger().handlers[0].setFormatter(logging.Formatter("%(message)s")) logging.getLogger().handlers[1].maxBytes = self.max_file_size + def _attempt_initialize_logging_configuration(self): + """ + Attempt to initialize logging framework configuration + + If we fail to initialize the logging framework, we will disable logging to file + """ + + try: + self._initialize_logging_configuration() + except Exception as e: + print(f"- Failed to initialize logging framework: {e}") + print("- Retrying without logging to file...") + self._initialize_logging_configuration(log_to_file=False) + def _implement_custom_traceback_handler(self): """ @@ -97,3 +135,11 @@ class InitializeLoggingSupport: sys.excepthook = custom_excepthook threading.excepthook = custom_thread_excepthook + + def _restore_original_excepthook(self): + """ + Restore original traceback handlers + """ + + sys.excepthook = self.original_excepthook + threading.excepthook = self.original_thread_excepthook