Source code for algomancy_utils.logger

"""
Simple logging module for tracking and displaying messages with different statuses.

The logger is used to report messages and provide a structured way to log events and errors in the application.
Logging output is shown in the standard admin page. To access the logger during algorithm execution,
use the `get_logger` function from the `algomancy_utils` module.

EXAMPLE:
    >>> from algomancy_utils import Logger
    >>> logger: Logger = Logger()
    ...
    >>> logger.log("This is a test message")
    >>> logger.success("This is a test message")
    >>> logger.warning("This is a test message")
"""

import datetime
import traceback
from enum import StrEnum, auto
from typing import List, Optional


[docs] class MessageStatus(StrEnum): """ Enum representing the status of a log message. """ #: Informational message INFO = auto() #: Successful operation message SUCCESS = auto() #: Warning message for potential issues WARNING = auto() #: Error message for failed operations ERROR = auto()
[docs] class Message: """ Representation of a single log message with metadata and formatting. Args: message: The text content of the message. status: The severity or type of the message. Defaults to MessageStatus.INFO. """ RESET = "\033[0m" GREEN = "\033[92m" ORANGE = "\033[93m" RED = "\033[91m" def __init__( self, message: str, status: MessageStatus = MessageStatus.INFO ) -> None: self.message = message self.status = status self.timestamp = datetime.datetime.now() def __str__(self): """ Returns a formatted string representation of the message with its timestamp and status. """ return f"[{self.timestamp.isoformat()}] {self.status.name.rjust(7)}: {self.message}"
[docs] def print(self): """ Prints the formatted message to the console with ANSI color codes based on its status. """ match self.status: case MessageStatus.INFO: print(f"{self.RESET}{self.__str__()}") case MessageStatus.SUCCESS: print(f"{self.GREEN}{self.__str__()}") case MessageStatus.WARNING: print(f"{self.ORANGE}{self.__str__()}") case MessageStatus.ERROR: print(f"{self.RED}{self.__str__()}") case _: print(f"{self.__str__()}")
class Singleton(object): _instance = None def __new__(cls, *args, **kwargs): if not isinstance(cls._instance, cls): cls._instance = object.__new__(cls, *args, **kwargs) return cls._instance
[docs] class Logger(Singleton): """ A logger that stores and manages a collection of log messages. """ def __init__(self) -> None: self._logs: List[Message] = [] self.latest_log: Optional[Message] = None self._print_to_console = True
[docs] def toggle_print_to_console(self, value: bool = None) -> None: """ Toggles or sets whether log messages should be printed to the console. Args: value: Optional boolean to explicitly set the console printing state. If None, the state is toggled. """ if not value: value = not self._print_to_console self._print_to_console = value
[docs] def log(self, message: str, status: MessageStatus = MessageStatus.INFO) -> None: """ Adds a new log message and prints it to the console if enabled. Args: message: The message text to log. status: The status/type of the message. Defaults to MessageStatus.INFO. """ self._logs.append(Message(message=message, status=status)) self.latest_log = self._logs[-1] if self._print_to_console: self.latest_log.print()
[docs] def success(self, message: str): """ Logs a success message. """ self.log(message, status=MessageStatus.SUCCESS)
[docs] def warning(self, message: str): """ Logs a warning message. """ self.log(message, status=MessageStatus.WARNING)
[docs] def error(self, message: str): """ Logs an error message. """ self.log(message, status=MessageStatus.ERROR)
[docs] def get_logs(self, status_filter: Optional[MessageStatus] = None) -> List[Message]: """ Retrieves all stored logs, optionally filtered by status. Args: status_filter: Optional status to filter logs by. Returns: A list of Message objects. """ if status_filter: return [log for log in self._logs if log.status == status_filter] return list(self._logs)
[docs] def clear(self) -> None: """ Removes all stored logs. """ self._logs.clear()
[docs] def log_traceback(self, e: Exception): """ Logs the traceback of a given exception as error messages. Args: e: The exception to log the traceback for. """ self.error(f"An error occurred: {e.__class__.__name__}: {e}") for msg in traceback.format_tb(e.__traceback__): self.error(msg)