First (way too late) commit
Dumping my fever dream coding session into source control finally.
This commit is contained in:
157
src/df_tools/mylogging.py
Normal file
157
src/df_tools/mylogging.py
Normal file
@@ -0,0 +1,157 @@
|
||||
import datetime
|
||||
import logging as _logging
|
||||
from pathlib import Path
|
||||
|
||||
from loguru import logger
|
||||
from rich.console import Console
|
||||
from rich.logging import RichHandler
|
||||
|
||||
"""
|
||||
Setup logging to use loguru for logging, with rich for pretty console output.
|
||||
|
||||
Intercepts standard logging calls.
|
||||
"""
|
||||
|
||||
console = Console()
|
||||
|
||||
# "<green>{time:MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
|
||||
|
||||
|
||||
def setup_logging(
|
||||
level: int | str = _logging.INFO,
|
||||
console_level: int | str | None = None,
|
||||
log_file: str | Path | None = None,
|
||||
format_console: str | None = "{message}",
|
||||
format_logs: str | None = "{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {name}:{function}:{line} - {message}",
|
||||
console_locals: bool = False,
|
||||
enqueue: bool = True,
|
||||
console_tracebacks: bool = False,
|
||||
console_markup: bool = True,
|
||||
console_omit_repeated_times: bool = False,
|
||||
console_show_time: bool = True,
|
||||
console_show_path: bool = False,
|
||||
loguru_tracebacks: bool = False,
|
||||
loguru_locals: bool = False,
|
||||
loguru_rotation: str | int | datetime.time | datetime.timedelta | None = "10 MB",
|
||||
loguru_retention: str | int | datetime.timedelta | None = "10 days",
|
||||
loguru_compression: str = "gz", # "gz", "bz2", "xz", "lzma", "tar", "tar.gz", "tar.bz2", "tar.xz", "zip"
|
||||
loguru_watch_files: bool = False,
|
||||
loguru_delay_file_creation: bool = False,
|
||||
) -> None:
|
||||
"""Setup logging with loguru and rich.
|
||||
|
||||
Disclosure:
|
||||
Most of this code is adapted from online examples, loguru documentation, and Gemini's
|
||||
suggestions. I am not an expert in logging, loguru, or rich.
|
||||
"""
|
||||
|
||||
# Intercept standard logging
|
||||
class InterceptHandler(_logging.Handler):
|
||||
def emit(self, record: _logging.LogRecord):
|
||||
try:
|
||||
level = logger.level(record.levelname).name
|
||||
except ValueError:
|
||||
level = record.levelno # type: ignore
|
||||
|
||||
frame, depth = _logging.currentframe(), 2
|
||||
while frame and frame.f_code.co_filename == _logging.__file__:
|
||||
frame = frame.f_back # type: ignore
|
||||
depth += 1
|
||||
|
||||
logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
|
||||
|
||||
logger.remove()
|
||||
_logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True)
|
||||
|
||||
# Add console handler
|
||||
|
||||
# Hanlder for my console output
|
||||
handler_console = RichHandler(
|
||||
console=console,
|
||||
level=console_level if console_level is not None else level,
|
||||
show_level=True,
|
||||
show_path=console_show_path,
|
||||
show_time=console_show_time,
|
||||
rich_tracebacks=console_tracebacks,
|
||||
tracebacks_show_locals=console_locals,
|
||||
markup=console_markup,
|
||||
omit_repeated_times=console_omit_repeated_times,
|
||||
)
|
||||
# handler_console.setFormatter(_logging.Formatter(format_console))
|
||||
|
||||
logger.add(
|
||||
handler_console,
|
||||
format=str(format_console),
|
||||
level=console_level if console_level is not None else level,
|
||||
backtrace=console_tracebacks,
|
||||
diagnose=console_locals,
|
||||
enqueue=enqueue,
|
||||
)
|
||||
|
||||
# Add log file handler
|
||||
if log_file:
|
||||
logger.add(
|
||||
log_file,
|
||||
level=level,
|
||||
format=str(format_logs),
|
||||
rotation=loguru_rotation,
|
||||
retention=loguru_retention,
|
||||
compression=loguru_compression,
|
||||
enqueue=enqueue,
|
||||
backtrace=loguru_tracebacks,
|
||||
diagnose=loguru_locals,
|
||||
watch=loguru_watch_files,
|
||||
delay=loguru_delay_file_creation,
|
||||
)
|
||||
|
||||
|
||||
# def setup_logging(
|
||||
# level: Union[int, str] = _logging.INFO,
|
||||
# log_format: str = "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
|
||||
# "<level>{level: <8}</level> | "
|
||||
# "<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - "
|
||||
# "<level>{message}</level>",
|
||||
# date_format: str = "YYYY-MM-DD HH:mm:ss.SSS",
|
||||
# log_file: str | None = None,
|
||||
# file_log_level: Union[int, str] = _logging.DEBUG,
|
||||
# file_log_format: str = "{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {name}:{function}:{line} - {message}",
|
||||
# file_date_format: str = "YYYY-MM-DD HH:mm:ss.SSS",
|
||||
# ) -> None:
|
||||
# class InterceptHandler(_logging.Handler):
|
||||
# def emit(self, record: _logging.LogRecord) -> None:
|
||||
# try:
|
||||
# level = logger.level(record.levelname).name
|
||||
# except ValueError:
|
||||
# level = record.levelno
|
||||
|
||||
# frame, depth = _logging.currentframe(), 2
|
||||
# while frame.f_code.co_filename == _logging.__file__:
|
||||
# frame = frame.f_back # type: ignore[union-attr]
|
||||
# depth += 1
|
||||
|
||||
# logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
|
||||
|
||||
# _logging.root.handlers = [InterceptHandler()]
|
||||
# _logging.root.setLevel(level)
|
||||
|
||||
# rich_handler = RichHandler(
|
||||
# rich_tracebacks=True,
|
||||
# tracebacks_show_locals=True,
|
||||
# markup=True,
|
||||
# log_time_format=date_format,
|
||||
# )
|
||||
# rich_handler.setLevel(level)
|
||||
# rich_handler.setFormatter(_logging.Formatter(log_format))
|
||||
|
||||
# _logging.getLogger().addHandler(rich_handler)
|
||||
|
||||
# if log_file:
|
||||
# logger.add(
|
||||
# log_file,
|
||||
# level=file_log_level,
|
||||
# format=file_log_format,
|
||||
# datefmt=file_date_format,
|
||||
# rotation="10 MB",
|
||||
# retention="10 days",
|
||||
# compression="zip",
|
||||
# )
|
||||
Reference in New Issue
Block a user