프로그래밍/python

로깅 전략 대한...

콘파냐 2021. 11. 24. 14:56
반응형

로깅은 언제나 항상 중요하다.

개발 중, 개발 마무리, 운영 중, 모든 상황에서 로깅이 없다면 문제점을 제대로 파악하기 어려워진다.

print('<<-- here check")

와 같은 방식의 코드는 쉽게 사용할 수 있고 편리하기는 하다.
하지만 실제로는 개발환경인지 테스트 환경인지 배포환경인지에 따라서 전략적인 로깅이 필요하다.

그런데 코드에 로깅을 어떻게 버무려 놓으면 효율적일지는 답은 없는 듯 하다.

현재 정리할 방식이 업그레이드 될 거라 생각하지만, 현재 대략적인 로깅 전략을 간단히만 정리하려고 한다.

전반적인 로깅 방향

우선 서비스는 AWS 를 사용한다. 백엔드 서버(EC2)에서 이벤트가 발생하면 각 EC2 내에 로그 파일을 filebeat를 사용해 ELK STACK 으로 보내게 된다.
filebeat에서 * 패턴 매칭으로 *.log 파일들을 긁어가도록 한다. 참고

로그를 기록할 때 로그파일을 하나로 잡게 되면 하나의 파일이 비대해 지고, 무중단 서비스일 경우 다음 업데이트 때까지 로그 파일을 깔끔하게 처리하지 못할 것이다.
따라서 로그파일은 날짜별로 기록하되 기간이 7일이 넘어간 파일이라면 삭제하도록 cron job을 등록해 두는 편이 좋을 것 같다.

현재 궁금한 것 ELK STACK 에서 날짜별로 나누어진 로그파일들을 하나로 집계하는 기능이 있냐는 것이다.(당연히 있을 거라 생각)

여기까지 파일비트와 cron으로 백엔드에 쌓이는 로그파일을 처리하면 나머지는 ELK STACK 에서 처리하면 된다. 이 때 ESK STACK 에서 적절하게 처리 후 S3에 올려 두도록 할 예정이다.

logging 모듈

시간대 변경

로깅 표시 기본 시간대는 utc가 표준이므로 KST로 바꾸기 위해서는 다음과 같은 코드가 필요하다.

logger.Formatter.converter = lambda *args: (한국 타임존 정보를 갖고 있는 현재시간 datetime객체).timetuple()

pytz를 사용하여 한국 타임존 정보를 갖는 현재시간 datetime 객체를 만들 수 있다. 자세한 정보는 구글에서 쉽게 찾을 수 있다.

날짜별 로그파일 나누기

단순하게 config.json을 사용한 설정을 할 수도 있다.
그런데 날짜별로 log를 찍을 파일 이름을 변경하려면 코드상에서 로그에 붙일 파일핸들러 설정을 해줘야 한다.

from datetime import date
def get_my_logger():
    logger = logging.('mylogger')
    date_format = str(date.today())
    hdl = logging.FileHandler(f'{log_file_name}_{date_format}.log')
    logger.addHandler(hdl)
    return logger

로거를 사용할 땐 함수 호출을 통해 사용한다. 그래야 날짜가 변경되었을 때 적절하게 로깅파일을 생성하고 기록할 것이다.
따로 root 로거를 사용하고 싶을 땐 logging.debug('message')로 사용한다.

루트 로거 사용 전략

코드에 propagate 설정을 해보자.

from datetime import date

if DEBUG:
    rootLogger = logging.getLogger('root')
    rootLogger.setLevel(logging.DEBUG) # root 로거의 기본 level warn이다. DEBUG 모드에서 이를 DEBUG로 변환
    hdl = logging.StreamHandler() # 기본 스트림 핸들러는 stdErr 이다. 
    rootLogger.addHandler(hdl) # 이 설정을 안하면 하위 로거에서 전파시 하위 로거와 동일한 핸들러를 사용하게 되어 로그가 같은 핸들러에 중복 출력된다.

def get_my_logger():
    logger = logging.('mylogger')
    logger.propagate = True if DEBUG else logger.propagate = False # 디버그 모드일 때 DEBUG == True
    date_format = str(date.today())
    hdl = logging.FileHandler(f'{log_file_name}_{date_format}.log')
    logger.addHandler(hdl)
    return logger

DEBUG 모드에서만 전파를 허용한다. 이렇게 하면 DEBUG 모드에서만 root로거로 전파가 된다.

따로 root 로거를 사용하고 싶을 땐 logging.debug('message')로 사용한다. (루트 로거의 기본 로그 레벨은 warn이다. 그래서 위 코드에서 DBUG 모드이면 debug 레벨이 되도록 설정하였다. 이렇게 하면 DEBUG 모드일 때만 logging.debug('message')의 결과가 콘솔에 찍히고 실제 배포에서는 root로거는 warn 레벨이 되므로 위 코드를 무시한다.
이렇게 DEBUG 환경설정 변수를 통해 개발과 배포 환경에 따라서 로깅전략을 세웠다.

이 방식이 개선될 부분이 있을 수 있겠으나 아직은 크게 불편함은 없다.

반응형