108 lines
3.6 KiB
Python
108 lines
3.6 KiB
Python
import logging
|
|
import os
|
|
import sys
|
|
import types
|
|
from datetime import datetime
|
|
from logging import LogRecord
|
|
from pathlib import Path
|
|
from typing import Callable, Iterable, List, Optional, Union
|
|
|
|
from loguru import logger
|
|
from rich.console import Console, ConsoleRenderable
|
|
from rich.text import Text
|
|
from rich.theme import Theme
|
|
from rich.traceback import Traceback
|
|
from richuru import ExceptionHook, LoguruHandler, LoguruRichHandler, _loguru_exc_hook
|
|
|
|
|
|
class HookedLoguruRichHandler(LoguruRichHandler):
|
|
"""
|
|
A hooked version of LoguruRichHandler to fix some issues.
|
|
"""
|
|
|
|
def render(
|
|
self,
|
|
*,
|
|
record: LogRecord,
|
|
traceback: Optional[Traceback],
|
|
message_renderable: "ConsoleRenderable",
|
|
) -> "ConsoleRenderable":
|
|
"""Render log for display.
|
|
|
|
Args:
|
|
record (LogRecord): logging Record.
|
|
traceback (Optional[Traceback]): Traceback instance or None for no Traceback.
|
|
message_renderable (ConsoleRenderable): Renderable (typically Text) containing log message contents.
|
|
|
|
Returns:
|
|
ConsoleRenderable: Renderable to display log.
|
|
"""
|
|
current_path = Path(os.getcwd())
|
|
path = Path(record.pathname)
|
|
try:
|
|
path = path.relative_to(current_path)
|
|
if sys.platform == "win32":
|
|
path = str(path).replace("\\", "/")
|
|
except ValueError:
|
|
path = Path(record.pathname).name
|
|
path = str(path)
|
|
level = self.get_level_text(record)
|
|
time_format = None if self.formatter is None else self.formatter.datefmt
|
|
log_time = datetime.fromtimestamp(record.created)
|
|
|
|
log_renderable = self._log_render(
|
|
self.console,
|
|
[message_renderable] if not traceback else [message_renderable, traceback],
|
|
log_time=log_time,
|
|
time_format=time_format,
|
|
level=level,
|
|
path=path,
|
|
line_no=record.lineno,
|
|
link_path=record.pathname if self.enable_link_path else None,
|
|
)
|
|
return log_renderable
|
|
|
|
|
|
def install(
|
|
rich_console: Optional[Console] = None,
|
|
exc_hook: Optional[ExceptionHook] = _loguru_exc_hook,
|
|
rich_traceback: bool = True,
|
|
tb_ctx_lines: int = 3,
|
|
tb_theme: Optional[str] = None,
|
|
tb_suppress: Iterable[Union[str, types.ModuleType]] = (),
|
|
time_format: Union[str, Callable[[datetime], Text]] = "[%x %X]",
|
|
keywords: Optional[List[str]] = None,
|
|
level: Union[int, str] = 20,
|
|
) -> None:
|
|
"""Install Rich logging and Loguru exception hook"""
|
|
logging.basicConfig(handlers=[LoguruHandler()], level=0)
|
|
logger.configure(
|
|
handlers=[
|
|
{
|
|
"sink": HookedLoguruRichHandler(
|
|
console=rich_console
|
|
or Console(
|
|
theme=Theme(
|
|
{
|
|
"logging.level.success": "green",
|
|
"logging.level.trace": "bright_black",
|
|
}
|
|
)
|
|
),
|
|
rich_tracebacks=rich_traceback,
|
|
tracebacks_show_locals=True,
|
|
tracebacks_suppress=tb_suppress,
|
|
tracebacks_extra_lines=tb_ctx_lines,
|
|
tracebacks_theme=tb_theme,
|
|
show_time=False,
|
|
log_time_format=time_format,
|
|
keywords=keywords,
|
|
),
|
|
"format": (lambda _: "{message}") if rich_traceback else "{message}",
|
|
"level": level,
|
|
}
|
|
]
|
|
)
|
|
if exc_hook is not None:
|
|
sys.excepthook = exc_hook
|