Spaces:
Sleeping
Sleeping
| import functools | |
| import logging | |
| import sys | |
| import os | |
| from dotenv import load_dotenv | |
| from uvicorn.logging import ColourizedFormatter | |
| from typing import Any, Callable | |
| load_dotenv() | |
| LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper() | |
| # Mapping of string levels to logging constants | |
| LOG_LEVEL_MAPPING = { | |
| "DEBUG": logging.DEBUG, | |
| "INFO": logging.INFO, | |
| "WARNING": logging.WARNING, | |
| "ERROR": logging.ERROR, | |
| "CRITICAL": logging.CRITICAL, | |
| } | |
| # Set the actual logging level | |
| LOG_LEVEL = LOG_LEVEL_MAPPING.get(LOG_LEVEL, logging.INFO) # Default to INFO if invalid | |
| # Custom colorized formatter to apply colors specifically to log levels | |
| class CustomColourizedFormatter(ColourizedFormatter): | |
| def format(self, record: logging.LogRecord) -> str: | |
| # Define color mappings for different log levels | |
| level_color_map = { | |
| "DEBUG": "\033[34m", # Blue | |
| "INFO": "\033[32m", # Green | |
| "WARNING": "\033[33m", # Yellow | |
| "ERROR": "\033[31m", # Red | |
| "CRITICAL": "\033[41m", # Red background | |
| } | |
| # Reset color | |
| reset = "\033[0m" | |
| # Apply color to the log level name | |
| record.levelname = ( | |
| f"{level_color_map.get(record.levelname, '')}{record.levelname}{reset}" | |
| ) | |
| # Format the log message using the parent class's format method | |
| return super().format(record) | |
| def get_logger(name: str) -> logging.Logger: | |
| """Creates a logger object that reads its log level from .env. | |
| Args: | |
| name (str): name given to the logger | |
| Returns: | |
| logging.Logger: logger object to be used for logging | |
| """ | |
| # Create logger | |
| logger = logging.getLogger(name) | |
| logger.setLevel(LOG_LEVEL) # Set level based on .env file | |
| # Prevent adding multiple handlers if already exists | |
| if not logger.hasHandlers(): | |
| # Create console handler | |
| ch = logging.StreamHandler(sys.stdout) | |
| ch.setLevel(LOG_LEVEL) # Set handler level | |
| # Create a custom formatter with colored log levels | |
| formatter = CustomColourizedFormatter( | |
| "{asctime} | {levelname:<8} | {message}", | |
| style="{", | |
| datefmt="%Y-%m-%d %H:%M:%S", | |
| use_colors=True, | |
| ) | |
| # Add formatter to the handler | |
| ch.setFormatter(formatter) | |
| # Add handler to the logger | |
| logger.addHandler(ch) | |
| return logger | |
| # Logger decorator implementation | |
| def log_function_call(logger: logging.Logger) -> Callable: | |
| """A decorator that logs the function calls and results. | |
| Args: | |
| logger (logging.Logger): The logger instance to use for logging. | |
| Returns: | |
| Callable: A wrapper function that logs the execution details. | |
| """ | |
| def decorator(func: Callable) -> Callable: | |
| def wrapper(*args, **kwargs) -> Any: | |
| # Log the function call with arguments | |
| logger.debug( | |
| f"Calling {func.__name__} with args: {args} and kwargs: {kwargs}" | |
| ) | |
| result = func(*args, **kwargs) | |
| # Log the function result | |
| logger.debug(f"{func.__name__} returned {result}") | |
| return result | |
| return wrapper | |
| return decorator | |
| logger = logging.getLogger(__name__) | |