TIL DAY 15 || Python Debugger using RotatingFileHandler, StreamHandler

TK·2021년 3월 5일
0

TIL

목록 보기
20/55
post-thumbnail

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 로 지정했다.
  • now 안에 현재날짜를 datetime 모듈로 가져와서
  • 현재 디렉토리에 logs 라는 폴더가 없으면 새로만들게 한다.
  • ./logs/log-현재날짜 폴더가 없으면 현재날짜 폴더를 새로 만든다.

Problems

여기서 한가지 문제를 겪었다.
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, ...)

RotatingFileHandler()

  • RoatatingFileHandler 의 첫번째 인자로 log-현재날짜 폴더안에 생성 할 파일이름을 지정해준다. Debugger.log 로 로거 이름에 맞게 설정해주었다.
  • maxBytes 는 10 mb 로 설정하고, backupCount 는 3 으로 설정했다.
  • backupCount 가 의미하는 바는, maxBytes 이상으로 로그가 쌓였을 때 카운트 수 만큼 백업 파일을 새로 만들어준다.

backupCount 가 3 일 시 로그 파일에 기록되는 내용이 용량을 초과했을 때
1. Debugger.log 가 닫히고 Debugger.log.1 파일로 이름이 변경
2. Debugger.log 파일에 현재 로그를 기록.
3. Debugger.log.3 파일까지 기록됨

--> 따라서 가장 최근파일은 Debugger.log.3 가 아닌 Debugger.log 이다.

가장 헷갈렸던 부분이여서 문서를 한참 들여다보았다.

StreamHandler()

  • 그리고 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_hdlrStreamHandler 의 object
  • f_hdlrRotatingFileHandler 의 object 이다.

둘의 역할은 로그가 도착하는 최종 목적지 라고 생각하면 될 것 같다.

그래서 addHandler 메소드를 통해 debugger 라는 로거에 목적지 s_hdlr (콘솔), f_hdlr(설정했던 파일) 를 더해주는 것이다.

  • Logger.setLevel() 은 로거가 처리할 가장 낮은 심각도의 로그 메시지를 지정해주는 것이다.

나중에 custom 한 debugger 를 작성할 때는 좀 더 수월할 것 같다.

참고자료: https://docs.python.org/ko/3/library/logging.handlers.html

profile
Backend Developer

0개의 댓글