136 lines
5.1 KiB
Python
136 lines
5.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
SPDX-FileCopyrightText: 2023-2025 PeppermintOS Team
|
|
(peppermintosteam@proton.me)
|
|
|
|
SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
This module sets up the logging system used throughout the PeppermintOS Builder project.
|
|
It provides functionalities to record messages at different severity levels (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
|
both to the console (with colors for better visualization) and to a rotating log file.
|
|
|
|
The main objective of this module is to provide a centralized and configurable way to track the execution
|
|
of the builder, facilitating debugging and monitoring of the ISO building process.
|
|
|
|
Credits:
|
|
- PeppermintOS Team (peppermintosteam@proton.me) - Development and maintenance of the project.
|
|
|
|
License:
|
|
This code is distributed under the GNU General Public License version 3 or later (GPL-3.0-or-later).
|
|
For more details, please refer to the LICENSE file included in the project or visit:
|
|
https://www.gnu.org/licenses/gpl-3.0.html
|
|
"""
|
|
|
|
import logging
|
|
from logging.handlers import RotatingFileHandler
|
|
import sys
|
|
import os
|
|
from pathlib import Path
|
|
|
|
# Define color codes as constants for readability and maintainability
|
|
COLOR_DEBUG = '\033[94m' # Blue
|
|
COLOR_INFO = '\033[92m' # Green
|
|
COLOR_WARNING = '\033[93m' # Yellow
|
|
COLOR_ERROR = '\033[91m' # Red
|
|
COLOR_CRITICAL = '\033[95m' # Magenta
|
|
COLOR_RESET = '\033[0m'
|
|
|
|
def supports_color():
|
|
"""Check if the system supports color output in the terminal."""
|
|
return hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
|
|
|
|
class ColorFormatter(logging.Formatter):
|
|
"""A custom log formatter that adds colors to messages based on the severity level."""
|
|
|
|
level_colors = {
|
|
logging.DEBUG: COLOR_DEBUG,
|
|
logging.INFO: COLOR_INFO,
|
|
logging.WARNING: COLOR_WARNING,
|
|
logging.ERROR: COLOR_ERROR,
|
|
logging.CRITICAL: COLOR_CRITICAL,
|
|
}
|
|
|
|
def __init__(self, fmt=None, datefmt=None, style='%'):
|
|
"""
|
|
Initializes the color formatter.
|
|
|
|
Args:
|
|
fmt (str, optional): Format string for the log message. Defaults to None.
|
|
datefmt (str, optional): Format string for the date and time. Defaults to None.
|
|
style (str, optional): Formatting style ('%', '{' or '$'). Defaults to '%'.
|
|
"""
|
|
super().__init__(fmt=fmt, datefmt=datefmt, style=style)
|
|
|
|
def format(self, record):
|
|
"""
|
|
Formats a log record, adding colors if the terminal supports it.
|
|
|
|
Args:
|
|
record (logging.LogRecord): The log record to be formatted.
|
|
|
|
Returns:
|
|
str: The formatted log message.
|
|
"""
|
|
message = super().format(record)
|
|
if supports_color():
|
|
color = self.level_colors.get(record.levelno, COLOR_RESET)
|
|
message = f"{color}{message}{COLOR_RESET}"
|
|
return message
|
|
|
|
|
|
def setup_logger(builder, log_filename='builder.log', log_level=logging.DEBUG):
|
|
"""
|
|
Sets up the logger for the builder with the following features:
|
|
- Logger name based on the 'builder' argument.
|
|
- Specified logging level.
|
|
- Handler for the console (StreamHandler) with colored formatting.
|
|
- Handler for a rotating log file (RotatingFileHandler) without colored formatting.
|
|
- The log file is stored in "~/logs/".
|
|
|
|
Args:
|
|
builder (str): The name of the logger (usually the module or component name).
|
|
log_filename (str, optional): The name of the log file. Defaults to 'builder.log'.
|
|
log_level (int, optional): The logging level to be used (e.g., logging.DEBUG, logging.INFO). Defaults to logging.DEBUG.
|
|
|
|
Returns:
|
|
logging.Logger: The configured logger object.
|
|
"""
|
|
logger = logging.getLogger(builder)
|
|
logger.setLevel(log_level)
|
|
|
|
# Basic format for the file logger, customized formatting for the console logger
|
|
file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
console_formatter = ColorFormatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
|
|
# Configuration for the console handler
|
|
console_handler = logging.StreamHandler()
|
|
console_handler.setLevel(log_level)
|
|
console_handler.setFormatter(console_formatter)
|
|
|
|
# Configuration for the rotating file handler
|
|
log_file = Path(os.path.expanduser("~")) / 'logs' / log_filename
|
|
log_dir = log_file.parent
|
|
log_dir.mkdir(parents=True, exist_ok=True) # Ensure the log directory exists
|
|
|
|
file_handler = RotatingFileHandler(
|
|
log_file, maxBytes=1024 * 1024, backupCount=5, encoding='utf-8')
|
|
file_handler.setLevel(log_level)
|
|
file_handler.setFormatter(file_formatter)
|
|
|
|
# Add the handlers to the logger
|
|
logger.addHandler(console_handler)
|
|
logger.addHandler(file_handler)
|
|
|
|
return logger
|
|
|
|
|
|
# Determine the log level from the environment variable or use the default (DEBUG)
|
|
log_level_str = os.environ.get("PEPPERMINT_BUILDER_LOG_LEVEL", "DEBUG").upper()
|
|
try:
|
|
log_level = getattr(logging, log_level_str)
|
|
except AttributeError:
|
|
log_level = logging.DEBUG
|
|
print(f"Invalid log level '{log_level_str}' in environment variable. Using DEBUG.")
|
|
|
|
# Variables Arguments used for the logger setUp for all files.
|
|
builder_logger = setup_logger('builder', 'builder.log', log_level) |