[FEAT] (프로젝트 구성): 초기 프로젝트 구성

v0.1 (2025-11-13)
- Flask, Gunicorn, gevent, MariaDB, Redis, Swagger, logging 기본 구성 완료;
This commit is contained in:
2025-11-13 14:14:52 +09:00
commit 422c0638fd
19 changed files with 673 additions and 0 deletions

100
src/utils/logger_manager.py Normal file
View 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