import asyncio import logging import logging.handlers from queue import SimpleQueue import sys import arrow from typing_extensions import Self class MyFormatter(logging.Formatter): """Format time the way it SHOULD be done.""" def __init__(self, color: bool = True, ascii_only: bool = False): # fmt = formatter_message(fmt, use_color) logging.Formatter.__init__(self, "") self.color = color self.ascii_only = ascii_only def format(self, record: logging.LogRecord): message = record.msg if len(record.args) > 0: message = record.msg % record.args created = arrow.get(record.created).to("America/Chicago") name = record.name if len(name) > 25: name = name[:24] + "\u2026" pathname = record.pathname if len(pathname) > 15: pathname = "\u2026" + pathname[-14:] msg = ( f"{created:YYYY-MM-DD HH:mm:ss.SSSSSS Z} " f"{pathname:15s}:{record.lineno:<4d} " f"[{name:^25s}] {record.levelname:8s} {message:s}" ) return msg def formatTime(self, record: logging.LogRecord, datefmt=None): """Format the timestamp.""" created = arrow.get(record.created) return created.format("YYYY-MM-DD HH:mm:ss.SSSSSS Z") class LocalQueueHandler(logging.handlers.QueueHandler): def emit(self: Self, record: logging.LogRecord) -> None: # Removed the call to self.prepare(), handle task cancellation try: self.enqueue(record) except asyncio.CancelledError: raise except Exception: self.handleError(record) def setup_logging() -> None: """Set up logging.""" queue = SimpleQueue() handler = LocalQueueHandler(queue) formatter = MyFormatter() console = logging.StreamHandler(stream=sys.stderr) console.setFormatter(formatter) console.setLevel(logging.DEBUG) root = logging.getLogger() for h in root.handlers[:]: root.removeHandler(h) h.close() root.addHandler(handler) root.setLevel(logging.DEBUG) listener = logging.handlers.QueueListener( queue, console, respect_handler_level=True ) listener.start() logging.getLogger("asyncio").setLevel(logging.INFO) logging.getLogger("PIL.Image").setLevel(logging.INFO) logging.getLogger("PIL.PngImagePlugin").setLevel(logging.INFO) logging.getLogger("websockets.client").setLevel(logging.INFO)