2024-11-10 23:49:10 +01:00
|
|
|
"""Utility functions for handling logging tasks.
|
|
|
|
|
|
|
|
Functions:
|
|
|
|
----------
|
|
|
|
- get_logger: Creates and configures a logger with console and optional rotating file logging.
|
|
|
|
|
|
|
|
Example usage:
|
|
|
|
--------------
|
|
|
|
# Logger setup
|
|
|
|
>>> logger = get_logger(__name__, log_file="app.log", logging_level="DEBUG")
|
|
|
|
>>> logger.info("Logging initialized.")
|
|
|
|
|
|
|
|
Notes:
|
|
|
|
------
|
|
|
|
- The logger supports rotating log files to prevent excessive log file size.
|
|
|
|
"""
|
|
|
|
|
2025-01-05 14:41:07 +01:00
|
|
|
import logging as pylogging
|
2024-11-10 23:49:10 +01:00
|
|
|
import os
|
|
|
|
from logging.handlers import RotatingFileHandler
|
|
|
|
from typing import Optional
|
|
|
|
|
2025-01-05 14:41:07 +01:00
|
|
|
from akkudoktoreos.core.logabc import logging_str_to_level
|
|
|
|
|
2024-11-10 23:49:10 +01:00
|
|
|
|
|
|
|
def get_logger(
|
|
|
|
name: str,
|
|
|
|
log_file: Optional[str] = None,
|
2025-01-05 14:41:07 +01:00
|
|
|
logging_level: Optional[str] = None,
|
2024-11-10 23:49:10 +01:00
|
|
|
max_bytes: int = 5000000,
|
|
|
|
backup_count: int = 5,
|
2025-01-05 14:41:07 +01:00
|
|
|
) -> pylogging.Logger:
|
2024-11-10 23:49:10 +01:00
|
|
|
"""Creates and configures a logger with a given name.
|
|
|
|
|
|
|
|
The logger supports logging to both the console and an optional log file. File logging is
|
|
|
|
handled by a rotating file handler to prevent excessive log file size.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
name (str): The name of the logger, typically `__name__` from the calling module.
|
|
|
|
log_file (Optional[str]): Path to the log file for file logging. If None, no file logging is done.
|
|
|
|
logging_level (Optional[str]): Logging level (e.g., "INFO", "DEBUG"). Defaults to "INFO".
|
|
|
|
max_bytes (int): Maximum size in bytes for log file before rotation. Defaults to 5 MB.
|
|
|
|
backup_count (int): Number of backup log files to keep. Defaults to 5.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
logging.Logger: Configured logger instance.
|
|
|
|
|
|
|
|
Example:
|
|
|
|
logger = get_logger(__name__, log_file="app.log", logging_level="DEBUG")
|
|
|
|
logger.info("Application started")
|
|
|
|
"""
|
|
|
|
# Create a logger with the specified name
|
2025-01-05 14:41:07 +01:00
|
|
|
logger = pylogging.getLogger(name)
|
2024-11-10 23:49:10 +01:00
|
|
|
logger.propagate = True
|
2025-02-08 00:45:11 +01:00
|
|
|
# This is already supported by pydantic-settings in LoggingCommonSettings, however in case
|
|
|
|
# loading the config itself fails and to set the level before we load the config, we set it here manually.
|
|
|
|
if logging_level is None and (env_level := os.getenv("EOS_LOGGING__LEVEL")) is not None:
|
|
|
|
logging_level = env_level
|
2025-01-05 14:41:07 +01:00
|
|
|
if logging_level is not None:
|
|
|
|
level = logging_str_to_level(logging_level)
|
|
|
|
logger.setLevel(level)
|
2024-11-10 23:49:10 +01:00
|
|
|
|
|
|
|
# The log message format
|
2025-01-05 14:41:07 +01:00
|
|
|
formatter = pylogging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
2024-11-10 23:49:10 +01:00
|
|
|
|
|
|
|
# Prevent loggers from being added multiple times
|
|
|
|
# There may already be a logger from pytest
|
|
|
|
if not logger.handlers:
|
|
|
|
# Create a console handler with a standard output stream
|
2025-01-05 14:41:07 +01:00
|
|
|
console_handler = pylogging.StreamHandler()
|
|
|
|
if logging_level is not None:
|
|
|
|
console_handler.setLevel(level)
|
2024-11-10 23:49:10 +01:00
|
|
|
console_handler.setFormatter(formatter)
|
|
|
|
|
|
|
|
# Add the console handler to the logger
|
|
|
|
logger.addHandler(console_handler)
|
|
|
|
|
|
|
|
if log_file and len(logger.handlers) < 2: # We assume a console logger to be the first logger
|
|
|
|
# If a log file path is specified, create a rotating file handler
|
|
|
|
|
|
|
|
# Ensure the log directory exists
|
|
|
|
log_dir = os.path.dirname(log_file)
|
|
|
|
if log_dir and not os.path.exists(log_dir):
|
|
|
|
os.makedirs(log_dir)
|
|
|
|
|
|
|
|
# Create a rotating file handler
|
|
|
|
file_handler = RotatingFileHandler(log_file, maxBytes=max_bytes, backupCount=backup_count)
|
2025-01-05 14:41:07 +01:00
|
|
|
if logging_level is not None:
|
|
|
|
file_handler.setLevel(level)
|
2024-11-10 23:49:10 +01:00
|
|
|
file_handler.setFormatter(formatter)
|
|
|
|
|
|
|
|
# Add the file handler to the logger
|
|
|
|
logger.addHandler(file_handler)
|
|
|
|
|
|
|
|
return logger
|