apeters 1d204f26b8 pre-Korves.Net
Signed-off-by: apeters <apeters@korves.net>
2025-05-21 08:05:07 +00:00

125 lines
4.2 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import logging
import json
import traceback
from logging.handlers import RotatingFileHandler
from components.utils.datetimes import datetime, timedelta
SUCCESS_LEVEL = 25
CRITICAL_LEVEL = 50
logging.addLevelName(SUCCESS_LEVEL, "SUCCESS")
logging.addLevelName(CRITICAL_LEVEL, "CRITICAL")
LOG_COLORS = {
"DEBUG": "\033[94m",
"INFO": "\033[96m",
"SUCCESS": "\033[92m",
"WARNING": "\033[93m",
"ERROR": "\033[91m",
"CRITICAL": "\033[95m",
"RESET": "\033[0m",
"BOLD": "\033[1m",
}
class JSONFormatter(logging.Formatter):
def __init__(self, text):
super().__init__()
self.text = text
def format(self, record):
exc_text = None
if record.exc_info:
exc_text = traceback.format_exc()
log_entry = {
"text": self.text,
"record": {
"elapsed": {
"repr": str(timedelta(seconds=record.relativeCreated / 1000)),
"seconds": record.relativeCreated / 1000,
},
"exception": exc_text,
"extra": record.__dict__.get("extra", {}),
"file": {"name": record.filename, "path": record.pathname},
"function": record.funcName,
"level": {
"icon": ""
if record.levelno == SUCCESS_LEVEL
else ""
if record.levelno == logging.INFO
else "⚠️",
"name": record.levelname,
"no": record.levelno,
},
"line": record.lineno,
"message": record.getMessage(),
"module": record.module,
"name": record.name,
"process": {"id": record.process, "name": record.processName},
"thread": {"id": record.thread, "name": record.threadName},
"time": {
"repr": datetime.utcfromtimestamp(record.created).isoformat()
+ "+00:00",
"timestamp": record.created,
},
},
}
return json.dumps(log_entry)
class PlainTextFormatter(logging.Formatter):
def format(self, record):
log_time = datetime.utcfromtimestamp(record.created).strftime(
"%Y-%m-%d %H:%M:%S.%f"
)[:-3]
level_color = LOG_COLORS.get(record.levelname, LOG_COLORS["RESET"])
message_bold = f"{LOG_COLORS['BOLD']}{record.getMessage()}{LOG_COLORS['RESET']}"
return f"{log_time} | {LOG_COLORS['BOLD']}{level_color}{record.levelname:<8}{LOG_COLORS['RESET']} | {record.funcName}:{record.lineno} - {message_bold}"
class Logger:
def __init__(self):
self.logger = logging.getLogger("custom_logger")
self.logger.setLevel(logging.DEBUG)
stdout_handler = logging.StreamHandler()
stdout_handler.setLevel(logging.DEBUG)
stdout_handler.setFormatter(PlainTextFormatter())
self.logger.addHandler(stdout_handler)
def add(self, filepath, level, colorize, max_size_mb, retention, text, serialize):
for handler in self.logger.handlers[:]:
if isinstance(handler, RotatingFileHandler):
self.logger.removeHandler(handler)
handler.close()
handler = RotatingFileHandler(
filepath,
maxBytes=max_size_mb * 1024 * 1024,
backupCount=retention,
encoding="utf-8",
)
handler.setLevel(level)
handler.setFormatter(JSONFormatter(text(None)))
self.logger.addHandler(handler)
def log(self, level, message):
self.logger.log(level, message, stacklevel=2)
def info(self, message):
self.logger.info(message, stacklevel=2)
def warning(self, message):
self.logger.warning(message, stacklevel=2)
def error(self, message):
self.logger.error(message, stacklevel=2)
def debug(self, message):
self.logger.debug(message, stacklevel=2)
def success(self, message):
self.logger.log(SUCCESS_LEVEL, message, stacklevel=2)
def critical(self, message):
self.logger.log(CRITICAL_LEVEL, message, exc_info=True, stacklevel=2)