Source code for labscheduler.logging_manager
"""
Configuration of the logging behavior. I used AI to create parts of this code.
"""
import logging
from datetime import datetime
from pathlib import Path
_log_format = "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"
_console_format = "%(levelname)s:%(message)s"
default_session_name = f"session_{datetime.today().ctime()}"
default_session_name = default_session_name.replace(" ", "_").replace(":", "_")
level_name = {
logging.DEBUG: "DEBUG",
logging.INFO: "INFO",
logging.WARNING: "WARNING",
logging.ERROR: "ERROR",
logging.CRITICAL: "CRITICAL",
}
def get_file_handler(handler_name: str, level: int):
file_handler = logging.FileHandler(handler_name)
file_handler.setLevel(level)
file_handler.setFormatter(logging.Formatter(_log_format))
return file_handler
def get_stream_handler(level: int):
stream_handler = logging.StreamHandler()
stream_handler.setLevel(level)
stream_handler.setFormatter(logging.Formatter(_console_format))
return stream_handler
[docs]
def get_standard_logger(session_name: str = default_session_name, stream_level: int = logging.INFO):
"""
Returns a custom logger named 'Scheduler logger' with separate file and console handlers.
This logger is independent of the root logger so that calls like logging.warning() do not use these settings.
"""
# Create a dedicated logger
logger = logging.getLogger("Scheduler logger")
logger.setLevel(logging.DEBUG)
logger.propagate = False # prevent log messages from being passed to the root logger
# Clear any existing handlers (if reconfiguring)
if logger.hasHandlers():
logger.handlers.clear()
# Create a session-specific directory for log files
base_path = Path(__file__).resolve().parent / "logs"
session_path = base_path / session_name
# Create the session_path directory if it doesn't exist
try:
session_path.mkdir(parents=True, exist_ok=True)
except OSError:
logger.exception("Could not create log directory. Logs may not be saved.")
# Set up file handlers for each logging level
for level, name in level_name.items():
file_name = session_path / f"{session_name}_{name}.log"
logger.addHandler(get_file_handler(file_name.as_posix(), level))
# Add stream (console) handler with the desired level and format
logger.addHandler(get_stream_handler(stream_level))
return logger
# Create a module-level logger that can be imported as StandardLogger
scheduler_logger = get_standard_logger()
# Optionally, define __all__ to restrict module exports
__all__ = ["get_standard_logger", "scheduler_logger"]
if __name__ == "__main__":
test_logger = scheduler_logger
test_logger.debug("Hello World")
test_logger.info("the end is near")
test_logger.warning("please prepare for the end!")
test_logger.exception("Goodbye cruel world :-(")