Files
nuriq_back/src/utils/logger_manager.py
윤영훈 abf405f8ae [FEAT] (사용자 로직): 프로필 서비스 구현 완료
v0.1.3 (2025-11-16)
- 프로필 조회, 프로필 업데이트, 탈퇴 구현 완료.
2025-11-16 18:02:27 +09:00

121 lines
3.5 KiB
Python

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._buf.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,
force=True
)
# create own logger class to prevent init custom loggers by other libs
class GatekeeperLogger(logging.Logger):
def addHandler(self, h):
# only "root", "__main__" and own loggers will be accepted
if self.name == "root" or self.name.startswith((settings.LOG_PREFIX, "__main__")):
return super().addHandler(h)
logging.setLoggerClass(GatekeeperLogger)
# Werkzeug 로거 설정 (Flask 개발 서버용)
# 기존 werkzeug 로거의 핸들러를 모두 제거하고 커스텀 포맷 적용
import logging as _logging
werkzeug_logger = _logging.getLogger("werkzeug")
werkzeug_logger.handlers = [] # 기존 핸들러 제거
werkzeug_logger.setLevel(settings.LOG_LEVEL_TEXT)
handler = _logging.StreamHandler(sys.stdout)
handler.setFormatter(formatter) # 통일된 포맷 사용
werkzeug_logger.addHandler(handler)
werkzeug_logger.propagate = False
# Flask의 기본 로거도 동일하게 설정
flask_logger = _logging.getLogger("flask.app")
flask_logger.handlers = []
flask_logger.setLevel(settings.LOG_LEVEL_TEXT)
flask_handler = _logging.StreamHandler(sys.stdout)
flask_handler.setFormatter(formatter)
flask_logger.addHandler(flask_handler)
flask_logger.propagate = False
def custom_logger(log_prefix: str):
import logging
logger = logging.getLogger(log_prefix)
logger.setLevel(settings.LOG_LEVEL_TEXT)
return logger