Spaces:
Running
on
Zero
Running
on
Zero
import logging | |
from functools import wraps | |
from threading import Lock | |
class Logger: | |
_instances = {} | |
_lock = Lock() | |
def __new__(cls, name="root"): | |
with cls._lock: | |
if name not in cls._instances: | |
instance = super().__new__(cls) | |
instance._init(name) | |
cls._instances[name] = instance | |
return cls._instances[name] | |
def _init(self, name): | |
self.logger = logging.getLogger(name) | |
self.logger.setLevel(logging.DEBUG) | |
self.logger.propagate = False | |
console_handler = logging.StreamHandler() | |
console_handler.setLevel(logging.INFO) | |
file_handler = logging.FileHandler("app.log") | |
file_handler.setLevel(logging.DEBUG) | |
formatter = logging.Formatter( | |
"%(asctime)s [%(threadName)s] %(levelname)-5s %(name)s - %(message)s", | |
datefmt="%Y-%m-%d %H:%M:%S", # no milliseconds | |
) | |
console_handler.setFormatter(formatter) | |
file_handler.setFormatter(formatter) | |
self.logger.addHandler(console_handler) | |
self.logger.addHandler(file_handler) | |
def _log(self, level, message): | |
log_message = f"{message}".strip() | |
self.logger.log(level, log_message) | |
def debug(self, message, **kwargs): | |
self._log(logging.DEBUG, message, **kwargs) | |
def info(self, message, **kwargs): | |
self._log(logging.INFO, message, **kwargs) | |
def warning(self, message, **kwargs): | |
self._log(logging.WARNING, message, **kwargs) | |
def error(self, message, **kwargs): | |
self._log(logging.ERROR, message, **kwargs) | |
def critical(self, message, **kwargs): | |
self._log(logging.CRITICAL, message, **kwargs) | |
# decorator for logging function calls | |
def log_fn(name=None): | |
def decorator(fn): | |
def wrapper(*args, **kwargs): | |
log = Logger(name or fn.__name__) | |
log.info("begin") | |
result = fn(*args, **kwargs) | |
log.info("end") | |
return result | |
return wrapper | |
return decorator | |