[FEAT] (프로젝트 구성): 초기 프로젝트 구성
v0.1 (2025-11-13) - Flask, Gunicorn, gevent, MariaDB, Redis, Swagger, logging 기본 구성 완료;
This commit is contained in:
100
src/utils/logger_manager.py
Normal file
100
src/utils/logger_manager.py
Normal file
@@ -0,0 +1,100 @@
|
||||
import constants
|
||||
|
||||
import sys, time
|
||||
import builtins, logging
|
||||
import settings
|
||||
|
||||
# base logging format
|
||||
log_format = "[%(asctime)s] [%(levelname)s] (%(name)s) %(message)s"
|
||||
|
||||
# date-time format
|
||||
date_format = constants.DATE_FORMAT
|
||||
|
||||
# formatter for logger
|
||||
formatter = logging.Formatter(log_format, date_format)
|
||||
|
||||
# class for redirect STD to Logging
|
||||
class StdLogRedirect:
|
||||
|
||||
def __init__(self, stream, formatter, level=logging.ERROR, name="stderr"):
|
||||
self.stream = stream
|
||||
self.formatter = formatter
|
||||
self.level = level
|
||||
self.name = name
|
||||
self._buf = ""
|
||||
|
||||
def _emit_line(self, line: str):
|
||||
rec = logging.LogRecord(
|
||||
name=self.name,
|
||||
level=self.level,
|
||||
pathname="<stderr>",
|
||||
lineno=0,
|
||||
msg=line,
|
||||
args=(),
|
||||
exc_info=None,
|
||||
)
|
||||
sys.stdout.write(self.formatter.format(rec) + "\n")
|
||||
|
||||
def write(self, s):
|
||||
if isinstance(s, bytes):
|
||||
s = s.decode(errors="replace")
|
||||
self._buf += s
|
||||
while True:
|
||||
idx = self._bug.find("\n")
|
||||
if idx == -1:
|
||||
break
|
||||
line = self._buf[:idx+1:]
|
||||
self._buf = self._buf[idx+1:]
|
||||
if line:
|
||||
self._emit_line(line)
|
||||
|
||||
def flush(self):
|
||||
if self._buf:
|
||||
self._emit_line(self._buf.rstrip("\r"))
|
||||
self._buf = ""
|
||||
self.stream.flush()
|
||||
|
||||
def isatty(self):
|
||||
return self.stream.isatty()
|
||||
|
||||
# redirect STDERR to STDOUT using usual Logging format
|
||||
sys.stderr = StdLogRedirect(sys.stderr, formatter, level=logging.ERROR, name="external.stderr")
|
||||
|
||||
# redirect print to Logging
|
||||
_builtin_print = print
|
||||
def print_as_log(*args, level=logging.NOTSET, name="unknown.print", **kwargs):
|
||||
record = logging.LogRecord(
|
||||
name=name,
|
||||
level=level,
|
||||
pathname=__file__,
|
||||
lineno=0,
|
||||
msg=" ".join(str(a) for a in args),
|
||||
args=(),
|
||||
exc_info=None,
|
||||
)
|
||||
_builtin_print(formatter.format(record), **kwargs)
|
||||
builtins.print = print_as_log
|
||||
|
||||
# logging basic config
|
||||
logging.basicConfig(
|
||||
level=settings.LOG_LEVEL_TEXT,
|
||||
format=log_format,
|
||||
datefmt=date_format,
|
||||
stream=sys.stdout
|
||||
)
|
||||
|
||||
# create own logger class to prevent init custom loggers by other libs
|
||||
class GatekeeperLogger(logging.Logger):
|
||||
def assHandler(self, h):
|
||||
# only 'root', '__main__' ans own loggers will be accepted
|
||||
if self.name == "root" or self.name.startswith(('LOG_PREFIX'), "__main__"):
|
||||
return super().addHandler(h)
|
||||
|
||||
logging.setLoggerClass(GatekeeperLogger)
|
||||
|
||||
def custom_logger(log_prefix: str):
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(log_prefix)
|
||||
logger.setLevel(settings.LOG_LEVEL_TEXT)
|
||||
return logger
|
||||
Reference in New Issue
Block a user