Django 로 인스타그램 클론코딩을 진행하던 중 오류를 관리하기 위해서는 custom debugger 를 만들 필요성을 느꼈다.
지금은 클론코딩이라 사용자가 거의 없고 프로젝트 크기도 그렇게 크지 않기 때문에 오류를 그냥 콘솔보고 체크할 수도 있지만, 나중에 사이즈가 커졌을 때 생기는 모든 오류를 스크롤 올려가면서 하나하나 확인하기 쉽지 않기때문에 debugger 를 만들어서 관리하기로 했다.
다음은 '날짜'별로 로그파일을 기록하는 debugger 를 만든 코드이다.
한 파일에 모든 날짜를 관리하면 보기 힘들기 때문에 날짜별로 나눠놓았다.
원래는 서버를 돌릴 때 마다 발생하는 오류를 다른 파일에 관리하려고 했지만 그럴필요를 아직 느끼진 못해서 날짜별로만 정리해보았다.
# debugger.py
import logging
import datetime
import os
from logging.handlers import RotatingFileHandler
debugger = logging.getLogger("Debugger")
# to make directory for log files
try:
now = str(datetime.datetime.now().date()).replace('-', '')
if not os.path.isdir('./logs'):
os.mkdir('./logs')
if not os.path.isdir('./logs/log-{}'.format(now)):
os.mkdir('./logs/log-{}'.format(now))
f_hdlr = RotatingFileHandler('./logs/log-{}/Debugger.log'.format(now),
encoding='UTF-8',
maxBytes=10 * 1024 * 1024,
backupCount=3)
except Exception as e:
print(e)
f_hdlr = RotatingFileHandler('Debugger.log',
encoding='UTF-8',
maxBytes=10 * 1024 * 1024,
backupCount=3)
s_hdlr = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
s_hdlr.setFormatter(formatter)
f_hdlr.setFormatter(formatter)
debugger.addHandler(f_hdlr)
debugger.addHandler(s_hdlr)
debugger.setLevel(logging.DEBUG)
logging.getLogger('Debugger')
메소드를 통해 로거의 이름을 Debugger
로 지정했다.logs
라는 폴더가 없으면 새로만들게 한다../logs/log-현재날짜
폴더가 없으면 현재날짜 폴더를 새로 만든다.여기서 한가지 문제를 겪었다.
debugger.py 의 경로는 /utils/debugger.py
로, 가장 상단 디렉토리의 utils 폴더 안에 들어있었는데. 로그를 만들면 utils 폴더 내부가 아니라 자꾸 최상단 디렉토리에 logs
폴더가 만들어지는 것이였다.
원래 utils 폴더 내부에 관리할 것도 아니였지만 테스트코드를 돌렸을 때 자꾸 .
, 즉 기준경로가 프로젝트 폴더 기준으로 잡혔다.
왜 그런지 알아봤더니 Django 의 settings.py 에서 만들어지는 BASE_DIR 때문이였다.
이를 통해, BASE_DIR은 부모의 부모 폴더 즉, 프로젝트 폴더를 가리킨다는 것을 파악할 수 있다. 장고는 이 경로를 기준으로 프로젝트 내 필요한 파일들을 찾아다닌다.
좀 더 명확히 경로를 설정하기 위해서 BASE_DIR를 명시해주면 좋을 것 같다는 생각이 들었다. 앞으로 BASE_DIR 의 하위 경로를 나타내야 하는 경우가 생기면 다음과 같이 쓰면 된다.
os.path.join(BASE_DIR, ...)
RoatatingFileHandler
의 첫번째 인자로 log-현재날짜
폴더안에 생성 할 파일이름을 지정해준다. Debugger.log
로 로거 이름에 맞게 설정해주었다.backupCount 가 3
일 시 로그 파일에 기록되는 내용이 용량을 초과했을 때
1. Debugger.log
가 닫히고 Debugger.log.1
파일로 이름이 변경
2. Debugger.log
파일에 현재 로그를 기록.
3. Debugger.log.3
파일까지 기록됨
--> 따라서 가장 최근파일은 Debugger.log.3
가 아닌 Debugger.log
이다.
가장 헷갈렸던 부분이여서 문서를 한참 들여다보았다.
그리고 s_hdlr = logging.StreamHandler()
의 logging.StreamHandler()
는 콘솔에 로그를 출력해주는 메소드이다.
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
에서
Formatter
메소드를 통해 출력되는 로그의 포맷을 설정할 수 있다.
마지막 코드가 조금 헷갈릴 수 있는데 천천히 보자.
s_hdlr.setFormatter(formatter)
f_hdlr.setFormatter(formatter)
debugger.addHandler(f_hdlr)
debugger.addHandler(s_hdlr)
debugger.setLevel(logging.DEBUG)
s_hdlr
는 StreamHandler
의 objectf_hdlr
는 RotatingFileHandler
의 object 이다.둘의 역할은 로그가 도착하는 최종 목적지 라고 생각하면 될 것 같다.
그래서 addHandler
메소드를 통해 debugger 라는 로거에 목적지 s_hdlr
(콘솔), f_hdlr
(설정했던 파일) 를 더해주는 것이다.
Logger.setLevel()
은 로거가 처리할 가장 낮은 심각도의 로그 메시지를 지정해주는 것이다.나중에 custom 한 debugger 를 작성할 때는 좀 더 수월할 것 같다.
참고자료: https://docs.python.org/ko/3/library/logging.handlers.html