Files
bancho.py/app/logging.py
2025-04-04 21:30:31 +09:00

103 lines
2.3 KiB
Python

from __future__ import annotations
import datetime
import logging.config
import re
from collections.abc import Mapping
from enum import IntEnum
from zoneinfo import ZoneInfo
import yaml
from app import settings
def configure_logging() -> None:
with open("logging.yaml") as f:
config = yaml.safe_load(f.read())
logging.config.dictConfig(config)
class Ansi(IntEnum):
# Default colours
BLACK = 30
RED = 31
GREEN = 32
YELLOW = 33
BLUE = 34
MAGENTA = 35
CYAN = 36
WHITE = 37
# Light colours
GRAY = 90
LRED = 91
LGREEN = 92
LYELLOW = 93
LBLUE = 94
LMAGENTA = 95
LCYAN = 96
LWHITE = 97
RESET = 0
def __repr__(self) -> str:
return f"\x1b[{self.value}m"
def get_timestamp(full: bool = False, tz: ZoneInfo | None = None) -> str:
fmt = "%d/%m/%Y %I:%M:%S%p" if full else "%I:%M:%S%p"
return f"{datetime.datetime.now(tz=tz):{fmt}}"
ANSI_ESCAPE_REGEX = re.compile(r"(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]")
def escape_ansi(line: str) -> str:
return ANSI_ESCAPE_REGEX.sub("", line)
ROOT_LOGGER = logging.getLogger()
def log(
msg: str,
start_color: Ansi | None = None,
extra: Mapping[str, object] | None = None,
) -> None:
"""\
A thin wrapper around the stdlib logging module to handle mostly
backwards-compatibility for colours during our migration to the
standard library logging module.
"""
# TODO: decouple colors from the base logging function; move it to
# be a formatter-specific concern such that we can log without color.
if start_color is Ansi.LYELLOW:
log_level = logging.WARNING
elif start_color is Ansi.LRED:
log_level = logging.ERROR
else:
log_level = logging.INFO
if settings.LOG_WITH_COLORS:
color_prefix = f"{start_color!r}" if start_color is not None else ""
color_suffix = f"{Ansi.RESET!r}" if start_color is not None else ""
else:
msg = escape_ansi(msg)
color_prefix = color_suffix = ""
ROOT_LOGGER.log(log_level, f"{color_prefix}{msg}{color_suffix}", extra=extra)
TIME_ORDER_SUFFIXES = ["nsec", "μsec", "msec", "sec"]
def magnitude_fmt_time(nanosec: int | float) -> str:
suffix = None
for suffix in TIME_ORDER_SUFFIXES:
if nanosec < 1000:
break
nanosec /= 1000
return f"{nanosec:.2f} {suffix}"