Adicionar src/renatoxsr-py/logger.py
This commit is contained in:
@@ -0,0 +1,242 @@
|
||||
#!/usr/bin/env python3
|
||||
# vim: set ft=python ts=4 sw=4 et: fileencoding=utf-8
|
||||
# SPDX-FileCopyrightText: 2025-present RenatoXSR <renatoxsr@gmail.com>
|
||||
# SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
"""Create a logger object (stdout) and optionally a logfile."""
|
||||
|
||||
from datetime import datetime
|
||||
from enum import StrEnum
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
from platform import node, platform, system
|
||||
import sys
|
||||
import colorlog
|
||||
|
||||
|
||||
from renatoxsr.const import COLORS, INVALID
|
||||
# Defaults
|
||||
FORMAT = f"[%(name)s:%(levelname)s:%(filename)s:%(funcName)s:%(lineno)d][%(process)d] %(message)s"
|
||||
now = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
|
||||
default_logfile = Path.cwd() / "logs" / f"{now}-{__name__}.log"
|
||||
|
||||
def get_formatter(format: str = FORMAT) -> logging.Formatter:
|
||||
"""Return a new logger formatter.
|
||||
|
||||
Args:
|
||||
format (str, optional): [description]. Defaults to None.
|
||||
|
||||
Returns:
|
||||
logging.Formatter: [description].
|
||||
|
||||
"""
|
||||
formatter = logging.Formatter(format)
|
||||
return formatter
|
||||
|
||||
|
||||
def set_logfile(
|
||||
*,
|
||||
name: str | None = None,
|
||||
formatter: logging.Formatter | None = None,
|
||||
format: str | None = None,
|
||||
logfile: Path | None = None,
|
||||
) -> logging.Handler:
|
||||
"""Log a message to a file .
|
||||
|
||||
Args:
|
||||
name (str, optional): [description]. Defaults to None.
|
||||
formatter (logging.Formatter, optional): [description]. Defaults to None.
|
||||
format (str, optional): [description]. Defaults to None.
|
||||
logfile (Path, optional): [description]. Defaults to None.
|
||||
|
||||
Returns:
|
||||
logging.Handler: [description].
|
||||
|
||||
"""
|
||||
# file handler
|
||||
now_str = now
|
||||
|
||||
if name is None:
|
||||
name = __name__
|
||||
|
||||
if formatter is None:
|
||||
if format is not None:
|
||||
formatter = get_formatter(format)
|
||||
else:
|
||||
formatter = get_formatter()
|
||||
|
||||
if logfile is None:
|
||||
logfile = default_logfile
|
||||
|
||||
if logfile.is_file():
|
||||
logfile.parent.mkdir(parents=True, exist_ok=True)
|
||||
file_handler = logging.FileHandler(logfile, mode="a", encoding="utf-8")
|
||||
|
||||
if logfile.is_dir():
|
||||
logfile.mkdir(parents=True, exist_ok=True)
|
||||
file_handler = logging.FileHandler(
|
||||
logfile / f"{name}.log", mode="a", encoding="utf-8"
|
||||
)
|
||||
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
return file_handler
|
||||
|
||||
|
||||
def set_loglevel(logger_instance: logging.Logger | None = None, logLevel="") -> int:
|
||||
"""Set the loglevel of a logger instance .
|
||||
|
||||
Args:
|
||||
logger_instance (logging.Logger, optional): [description]. Defaults to None.
|
||||
logLevel (str, optional): logging.[DEBUG|INFO|etc]. Defaults to "".
|
||||
|
||||
Returns:
|
||||
logging.setLevel or None
|
||||
int: EffectiveLoglevel()
|
||||
|
||||
"""
|
||||
if logger_instance:
|
||||
logger_instance.setLevel(getattr(logging, logLevel, "INFO"))
|
||||
elif logLevel:
|
||||
logger.setLevel(getattr(logging, logLevel, "INFO"))
|
||||
return logger.getEffectiveLevel()
|
||||
|
||||
|
||||
def set_logger(
|
||||
*,
|
||||
name: str | None = None,
|
||||
formatter: logging.Formatter | None = None,
|
||||
format: str | None = None,
|
||||
loglevel: str | None = None,
|
||||
logfile: Path | None = None,
|
||||
log_to_file: bool = False,
|
||||
) -> logging.Logger:
|
||||
"""Create and return a logger.
|
||||
|
||||
Args:
|
||||
name (str): logger name.
|
||||
formatter (logging.Formatter): formatter to use.
|
||||
format (str): format string to create a formatter.
|
||||
loglevel (str): log level to select.
|
||||
logfile (Path): logfile path.
|
||||
log_to_file (bool): whether to log to file.
|
||||
|
||||
Returns:
|
||||
logging.Logger: configured logger.
|
||||
|
||||
"""
|
||||
if name is None:
|
||||
name = __name__
|
||||
|
||||
if formatter is None:
|
||||
if isinstance(format, str):
|
||||
formatter = get_formatter(format)
|
||||
else:
|
||||
formatter = get_formatter()
|
||||
|
||||
stdout_handler = colorlog.StreamHandler()
|
||||
stdout_handler.setFormatter(colorlog.ColoredFormatter(
|
||||
"%(log_color)s" + FORMAT,
|
||||
reset=True,
|
||||
log_colors={
|
||||
'DEBUG': 'cyan',
|
||||
'INFO': 'green',
|
||||
'WARNING': 'yellow',
|
||||
'ERROR': 'red',
|
||||
'CRITICAL': 'red,bg_white',
|
||||
},
|
||||
secondary_log_colors={},
|
||||
style ='%',
|
||||
))
|
||||
|
||||
# stdout handler
|
||||
#stdout_handler = logging.StreamHandler()
|
||||
#stdout_handler.setFormatter(formatter)
|
||||
|
||||
logger = logging.getLogger(name)
|
||||
logger.addHandler(stdout_handler)
|
||||
|
||||
# file handler
|
||||
if logfile:
|
||||
log_to_file = True
|
||||
|
||||
|
||||
|
||||
if log_to_file:
|
||||
file_handler = set_logfile(
|
||||
name=name,
|
||||
formatter=formatter,
|
||||
format=format,
|
||||
logfile=logfile,
|
||||
)
|
||||
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
if loglevel is None:
|
||||
loglevel = os.getenv("LOGLEVEL", "INFO")
|
||||
# if logging.getLevelNamesMapping().get(loglevel.upper()) is None:
|
||||
if loglevel not in logging.getLevelNamesMapping():
|
||||
loglevel = "INFO"
|
||||
|
||||
logger.setLevel(loglevel)
|
||||
|
||||
logger.debug("Loglevel: %s", os.getenv("LOGLEVEL"))
|
||||
return logger
|
||||
|
||||
|
||||
# upon import:
|
||||
loglevel = "INFO"
|
||||
for arg in [a for a in sys.argv if a.startswith("--log")]:
|
||||
if arg.startswith("--loglevel="):
|
||||
loglevel = arg.split("=", 1)[1]
|
||||
if arg.startswith("--logfile="):
|
||||
log_to_file = arg.split("=", 1)[1]
|
||||
if arg == "--debug":
|
||||
loglevel = "DEBUG"
|
||||
logger = set_logger()
|
||||
logger.setLevel(loglevel)
|
||||
|
||||
|
||||
# CRITICAL = 50
|
||||
# FATAL = CRITICAL
|
||||
# ERROR = 40
|
||||
# WARNING = 30
|
||||
# WARN = WARNING
|
||||
# INFO = 20
|
||||
# DEBUG = 10
|
||||
# NOTSET = 0
|
||||
|
||||
# _levelToName = {
|
||||
# CRITICAL: 'CRITICAL',
|
||||
# ERROR: 'ERROR',
|
||||
# WARNING: 'WARNING',
|
||||
# INFO: 'INFO',
|
||||
# DEBUG: 'DEBUG',
|
||||
# NOTSET: 'NOTSET',
|
||||
# }
|
||||
# _nameToLevel = {
|
||||
# 'CRITICAL': CRITICAL,
|
||||
# 'FATAL': FATAL,
|
||||
# 'ERROR': ERROR,
|
||||
# 'WARN': WARNING,
|
||||
# 'WARNING': WARNING,
|
||||
# 'INFO': INFO,
|
||||
# 'DEBUG': DEBUG,
|
||||
# 'NOTSET': NOTSET,
|
||||
# }
|
||||
|
||||
|
||||
# def log(level, msg, *args, **kwargs):
|
||||
# logger.log(level, f"{COLORS.level}" + msg + f"{COLORS.RESET}", *args, **kwargs)
|
||||
|
||||
# def debug(msg, *args, **kwargs):
|
||||
# logger.log("DEBUG", msg, *args, **kwargs)
|
||||
|
||||
# def info(msg, *args, **kwargs):
|
||||
# logger.log("INFO", msg, *args, **kwargs)
|
||||
|
||||
# def error(msg, *args, **kwargs):
|
||||
# logger.log("ERROR", msg, *args, **kwargs)
|
||||
|
||||
# def warning(msg, *args, **kwargs):
|
||||
# logger.log("WARNING", msg, *args, **kwargs)
|
||||
Reference in New Issue
Block a user