Skip to content

日志

get_logger(logger_name=None, level=logging.DEBUG, **kwargs)

Get a configured logger instance.

Creates or retrieves a logger by name and sets it up with file and stream handlers. Accepts both string and integer log levels.

Parameters:

Name Type Description Default
level

Logging level (int or str, default: DEBUG)

DEBUG
logger_name str | None

Name of the logger (default: 'default')

None
args

Additional arguments passed to setup_logger

required
kwargs

Additional keyword arguments passed to setup_logger

{}

Returns:

Type Description
Logger

Configured logger instance

Source code in aloha/logger/logger.py
def get_logger(logger_name: str | None = None, level=logging.DEBUG, **kwargs) -> logging.Logger:
    """
    Get a configured logger instance.

    Creates or retrieves a logger by name and sets it up with file and stream handlers.
    Accepts both string and integer log levels.

    :param level: Logging level (int or str, default: DEBUG)
    :param logger_name: Name of the logger (default: 'default')
    :param args: Additional arguments passed to setup_logger
    :param kwargs: Additional keyword arguments passed to setup_logger
    :return: Configured logger instance
    """

    logger = logging.getLogger(logger_name)

    if isinstance(level, str):
        level = getattr(logging, str(level).upper(), 10)

    setup_logger(logger, level=level, logger_name=logger_name, **kwargs)
    return logger

get_logger(logger_name=None, level=logging.DEBUG, **kwargs)

Get a configured logger instance.

Creates or retrieves a logger by name and sets it up with file and stream handlers. Accepts both string and integer log levels.

Parameters:

Name Type Description Default
level

Logging level (int or str, default: DEBUG)

DEBUG
logger_name str | None

Name of the logger (default: 'default')

None
args

Additional arguments passed to setup_logger

required
kwargs

Additional keyword arguments passed to setup_logger

{}

Returns:

Type Description
Logger

Configured logger instance

Source code in aloha/logger/logger.py
def get_logger(logger_name: str | None = None, level=logging.DEBUG, **kwargs) -> logging.Logger:
    """
    Get a configured logger instance.

    Creates or retrieves a logger by name and sets it up with file and stream handlers.
    Accepts both string and integer log levels.

    :param level: Logging level (int or str, default: DEBUG)
    :param logger_name: Name of the logger (default: 'default')
    :param args: Additional arguments passed to setup_logger
    :param kwargs: Additional keyword arguments passed to setup_logger
    :return: Configured logger instance
    """

    logger = logging.getLogger(logger_name)

    if isinstance(level, str):
        level = getattr(logging, str(level).upper(), 10)

    setup_logger(logger, level=level, logger_name=logger_name, **kwargs)
    return logger

setup_logger(logger, level=logging.DEBUG, logger_name=None, module=None, formatter_str=None)

Set up a logger with file and stream handlers.

Configures the logger with: - A multi-process safe daily rotating file handler - A console stream handler - A standard log format

Parameters:

Name Type Description Default
logger Logger

Logger instance to set up

required
level int

Logging level (default: DEBUG)

DEBUG
logger_name str | None

Name of the logger (optional)

None
module str | None

Module name for log file naming (optional)

None
formatter_str str | None

Custom log format string (optional)

None
Source code in aloha/logger/logger.py
def setup_logger(
    logger: logging.Logger,
    level: int = logging.DEBUG,
    logger_name: str | None = None,
    module: str | None = None,
    formatter_str: str | None = None,
):
    """
    Set up a logger with file and stream handlers.

    Configures the logger with:
    - A multi-process safe daily rotating file handler
    - A console stream handler
    - A standard log format

    :param logger: Logger instance to set up
    :param level: Logging level (default: DEBUG)
    :param logger_name: Name of the logger (optional)
    :param module: Module name for log file naming (optional)
    :param formatter_str: Custom log format string (optional)
    """
    if not logger.handlers:
        formatter = logging.Formatter(formatter_str or "%(levelname)s> %(asctime)s> %(module)s:%(lineno)s> %(message)s")

        folder = os.environ.get("DIR_LOG", "logs")
        os.makedirs(folder, exist_ok=True)

        if module is None:
            from ..settings import SETTINGS

            module = SETTINGS.config.get("APP_MODULE") or os.environ.get("APP_MODULE", None)

        if logger_name is not None and len(logger_name) > 0:
            logger_name = logger_name.strip().replace(" ", "_")

        path_file = [module, logger_name, socket.gethostname(), "p%s" % os.getpid()]  # module, logger_name, hostname, pid
        path_file = "_".join(str(i) for i in path_file if i is not None and len(str(i)) > 0)
        path_file = pjoin(folder, "%s.log" % path_file)

        file_handler = MultiProcessSafeDailyRotatingFileHandler(path_file)
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)

        stream_handler = logging.StreamHandler()
        stream_handler.setFormatter(formatter)
        logger.addHandler(stream_handler)

        logger.setLevel(level)

MultiProcessSafeDailyRotatingFileHandler

Bases: BaseRotatingHandler

Similar with logging.TimedRotatingFileHandler, while this one is - Multi process safe - Rotate at midnight only - Utc not supported

Source code in aloha/logger/handler.py
class MultiProcessSafeDailyRotatingFileHandler(BaseRotatingHandler):
    """Similar with `logging.TimedRotatingFileHandler`, while this one is
    - Multi process safe
    - Rotate at midnight only
    - Utc not supported
    """

    def __init__(self, filename: str, encoding="utf8", delay=False, utc=False, **kwargs):
        self.utc = utc
        self.suffix = "%Y-%m%d"
        self.baseFilename = filename
        self.currentFileName = self._compute_fn()
        BaseRotatingHandler.__init__(self, filename, "a", encoding, delay)

    def shouldRollover(self, record):
        if self.currentFileName != self._compute_fn():
            return True
        return False

    def doRollover(self):
        if self.stream:
            self.stream.close()
            self.stream = None
        self.currentFileName = self._compute_fn()
        if not self.delay:
            self.stream = self._open()

    def _compute_fn(self):
        return self.baseFilename.replace(".log", "") + "_" + time.strftime(self.suffix, time.localtime()) + ".log"

    def _open(self):
        return open(self.currentFileName, mode=self.mode, encoding=self.encoding)

    def close(self):
        """Closes the stream."""
        self.acquire()
        try:
            try:
                if self.stream:
                    try:
                        self.flush()
                    finally:
                        stream = self.stream
                        self.stream = None
                        if hasattr(stream, "close"):
                            # print('ttt')
                            stream.close()
            finally:
                # Issue #19523: call unconditionally to prevent a handler leak when delay is set
                StreamHandler.close(self)
        finally:
            self.release()

close()

Closes the stream.

Source code in aloha/logger/handler.py
def close(self):
    """Closes the stream."""
    self.acquire()
    try:
        try:
            if self.stream:
                try:
                    self.flush()
                finally:
                    stream = self.stream
                    self.stream = None
                    if hasattr(stream, "close"):
                        # print('ttt')
                        stream.close()
        finally:
            # Issue #19523: call unconditionally to prevent a handler leak when delay is set
            StreamHandler.close(self)
    finally:
        self.release()