Skip to content

Instantly share code, notes, and snippets.

@jakob1379
Last active October 22, 2024 08:05
Show Gist options
  • Select an option

  • Save jakob1379/25939ebe487653c8f949bcacaa536c7d to your computer and use it in GitHub Desktop.

Select an option

Save jakob1379/25939ebe487653c8f949bcacaa536c7d to your computer and use it in GitHub Desktop.
Simple setup for beautiful logging using Rich
import logging
import os
from logging.handlers import RotatingFileHandler
from typing import Literal
from rich.logging import RichHandler
def setup_logging(
log_file: str = None,
log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = None,
log_max_size: int = None,
) -> None:
"""
Configures logging for console and file outputs with different handlers and formats.
Args:
log_file (str): The file path to store log outputs. Defaults to environment variable LOG_FILE or "application.log".
log_level (Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]): The log level for both console and file handlers. Defaults to environment variable LOG_LEVEL or "DEBUG".
log_max_size (int): Maximum size of the log file before it gets rotated. Defaults to environment variable LOG_MAX_SIZE or 5 MB.
"""
# Set log_file, log_level, and log_max_size from environment variables if not provided
log_file = log_file or os.environ.get("LOG_FILE", "application.log")
log_max_size = log_max_size or int(os.environ.get("LOG_MAX_SIZE", 5 * 1024 * 1024))
log_level = log_level or os.environ.get("LOG_LEVEL", "DEBUG").upper()
log_level_numeric = getattr(logging, log_level, logging.DEBUG)
# Root logger configuration
logger = logging.getLogger()
logger.setLevel(log_level_numeric)
# Rich Handler for console with timestamp
console_handler = RichHandler(rich_tracebacks=True, show_path=False)
console_handler.setLevel(log_level_numeric)
console_handler.setFormatter(
logging.Formatter(fmt="[%(asctime)s] %(message)s", datefmt="%m/%d/%y %H:%M:%S")
)
logger.addHandler(console_handler)
# File handler configuration (with rotation)
file_formatter = logging.Formatter(
"%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] - %(message)s"
)
file_handler = RotatingFileHandler(log_file, maxBytes=log_max_size, backupCount=5)
file_handler.setLevel(log_level_numeric)
file_handler.setFormatter(file_formatter)
logger.addHandler(file_handler)
if __name__ == "__main__":
# Test logging configuration with different levels
setup_logging()
logging.debug("This is a debug message.")
logging.info("This is an info message.")
logging.warning("This is a warning message.")
logging.error("This is an error message.")
logging.critical("This is a critical message.")
@jakob1379
Copy link
Author

jakob1379 commented Oct 22, 2024

Debugging from stdout will look like this:
image

whilst the file output will be as expected:

❯ cat application.log
2024-10-22 10:03:54,513 [DEBUG] [setup_logging.py:54] - This is a debug message.
2024-10-22 10:03:54,521 [INFO] [setup_logging.py:55] - This is an info message.
2024-10-22 10:03:54,523 [WARNING] [setup_logging.py:56] - This is a warning message.
2024-10-22 10:03:54,525 [ERROR] [setup_logging.py:57] - This is an error message.
2024-10-22 10:03:54,527 [CRITICAL] [setup_logging.py:58] - This is a critical message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment