Source code for mapstp.cli.mapstp_logging
"""Intercept log messages from the used libraries and pass them to `loguru`.
See https://github.com/Delgan/loguru
"""
from __future__ import annotations
from typing import Final
import logging
import os
import sys
from pathlib import Path
from loguru import logger
[docs]
class InterceptHandler(logging.Handler):
"""Send events from standard logging to loguru."""
[docs]
def emit(self: InterceptHandler, record: logging.LogRecord) -> None:
"""See :meth:`logging.Handler.emit`.
Args:
record: data to log
"""
# Get corresponding Loguru level if it exists
try:
level = logger.level(record.levelname).name
except ValueError:
level = logging.getLevelName(record.levelno)
# Find caller from where originated the logged message
frame = logging.currentframe()
depth = 2
while frame.f_code.co_filename == logging.__file__: # pragma: no cover
frame = frame.f_back # type: ignore[assignment]
depth += 1
logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
# from loguru._defaults.py
MAPSTP_CONSOLE_LOG_FORMAT: Final[str] = os.getenv(
"MAPSTP_CONSOLE_LOG_FORMAT",
"<green>{time:YYYY-MM-DD HH:mm:ss}</green> | "
"<level>{level: <8}</level> | "
"<level>{message}</level>",
)
MAPSTP_FILE_LOG_PATH: Final[Path] = Path(
os.getenv(
"MAPSTP_FILE_LOG_PATH",
"mapstp.log",
),
)
[docs]
def init_logger(
*,
stderr_format: str | None = MAPSTP_CONSOLE_LOG_FORMAT,
log_path: Path | None = MAPSTP_FILE_LOG_PATH,
) -> None:
"""Configure logger with given parameters.
Args:
stderr_format: log message format for stderr handler, if None, no stderr logging.
log_path: path to file for logging, if None, no file logging.
"""
log = logging.getLogger()
log.addHandler(InterceptHandler())
logger.remove()
if stderr_format:
logger.add(
sys.stderr,
format=stderr_format,
level="INFO",
backtrace=False,
diagnose=False,
)
if log_path:
logger.add(log_path, rotation="1 day", retention=3, backtrace=True, diagnose=True)