Spaces:
Sleeping
Sleeping
File size: 3,309 Bytes
bb1c643 b43bf80 bb1c643 b43bf80 bb1c643 b43bf80 bb1c643 b43bf80 bb1c643 b43bf80 bb1c643 b43bf80 bb1c643 b43bf80 bb1c643 b43bf80 bb1c643 b43bf80 bb1c643 b43bf80 bb1c643 b43bf80 bb1c643 b43bf80 bb1c643 b43bf80 bb1c643 b43bf80 bb1c643 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
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:
@functools.wraps(func)
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__)
|