파이썬 로그 (로깅)

파이썬 로깅 (logging)

파이썬으로 모듈로 배치 파일을 작성할 때 매우 중요한 사항이 있습니다. 바로 이 포스팅 주제인 로그입니다. 서비스 장애가 발생했을 때 가장 먼저 확인하는 것이 바로 로그입니다. 모든 프로그램은 로그를 자동으로 생성하지 않습니다.  프로그래머의 재량과 센스에 의존하여 장애가 발생했을 시 그 포인트를 쉽게 찾아가기 위해 중요하다 생각하는 부분에 로그를 작성하도록 하는 것입니다.

 

로그 파일은 프로그램 작성 시에도 매우 중요한 역할을 하는데 프로그래머의 의도에 맞게 제대로 된 루틴을 수행하는지 그리고 그 값이 충분히 도출되었는지 확인을 할 수 있기 때문입니다. 

 

이러한 로그 파일을 만들기 위해 프로그래머는 로그 파일을 컨트롤할 수 있는 모듈을 따로 작성해 그 모듈을 사용하곤 했습니다. 하지만 파이썬에서는 내장 모듈인 logging 모듈이 있어 필요하면 그냥 가져다 사용하면 됩니다. 세상 참 많이 좋아졌네요.

 

파이썬 로그 만들기

로그를 생성해 보기에 앞서 로그 레벨을 잠깐 확인해 보겠습니다. 파이썬의 logging모듈은 5단계의 로그 레벨이 존재합니다.

 

로그 레벨

단계 구분 키워드 설명
1 단계 CRITICAL 가장 심각하고 치명적인 크리티컬 에러
2 단계 ERROR 에러 
3 단계 WARNING 경고
4 단계 INFO 정보성
5 단계 DEBUG 프로그램 디버깅 정보

 

logging 모듈에서는 기본적으로 3단계가 설정되어 있어 있지만 설정을 변경해 주면 원하는 단계까지 확장 또는 축소가 가능합니다. 단, 모듈 수행 중에는 로그 레벨 변경이 불가능합니다.

 

기본인 사용 방법

logging 모듈을 사용하는데 가장 기본적인 사항입니다. 아래와 같은 예제는 정말 간단히 로그를 컨트롤하고 출력 메시지를 콘솔 화면에서 확인할 수 있습니다.

 

import logging

logging.basicConfig(level=logging.DEBUG)

logging.critical("Critical message.")
logging.error("Error message.")
logging.warning("Warning message.")
logging.info("Infomation message.")
logging.debug("Debug message.")

# 결과
CRITICAL:root:Critical message.
ERROR:root:Error message.
WARNING:root:Warning message.
INFO:root:Infomation message.
DEBUG:root:Debug message.

 

복잡적인 사용 방법

일반적인 로그라 함은 로그 파일에 담겨 있어야 합니다. 게다가 로그 파일도 debug까지 쌓는 로그와 error까지 쌓는 로그를 동시에 생성하고 때에 따라서는 콘솔 화면에 출력이 되어야 합니다. 그리고 로그가 마구 마구 쌓이기 시작하면 디스크 용량에 부하를 주게 됩니다. 그래서 로그파일의 용량별로 파일을 나눠 주어야 합니다.

 

그리고 로그를 쌓는 것보다 더욱 중요한 작업이 있는데 바로 로그 출력 시간을 기록하는 것입니다. 사실 로그에서 가장 중요한 부분이라 할 수 있습니다. 시간이 없는 로그는 디스크의 공간만 낭비할 뿐입니다.

 

import logging
import logging.handlers

# 로거 생성
logger = logging.getLogger('CaptainBIN Logger')
logger.setLevel(logging.DEBUG)

# 로그 파일 용량
max_limit_bytes = 1024 * 1024

# 로그 포맷팅
log_fmt = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")

# 디버그 레벨 파일 핸들러
#fh_debug = logging.FileHandler('Captain_BIN_debud.log')
fh_debug = logging.handlers.RotatingFileHandler(filename="Captain_BIN_debug.log", maxBytes=max_limit_bytes, backupCount=5)
fh_debug.setLevel(logging.DEBUG)
fh_debug.setFormatter(log_fmt)

# 에러 레벨 파일 핸들러
#fh_error = logging.FileHandler('Captain_BIN_error.log')
fh_error = logging.handlers.RotatingFileHandler(filename="Captain_BIN_error.log", maxBytes=max_limit_bytes, backupCount=5)
fh_error.setLevel(logging.ERROR)
fh_error.setFormatter(log_fmt)

# 콘솔 스트림 출력 핸들러
std_stream = logging.StreamHandler()
std_stream.setLevel(logging.DEBUG)
std_stream.setFormatter(log_fmt)

# 핸들러 등록
logger.addHandler(fh_debug)
logger.addHandler(fh_error)
logger.addHandler(std_stream)

# 메시지 출력
logger.critical("Critical message.")
logger.error("Error message.")
logger.warning("Warning message.")
logger.info("Infomation message.")
logger.debug("Debug message.")

 

위의 예제 코드는 앞서 설명한 기능들이 모두 포함되어 있습니다. 참고로 backupCount에 설정되어 있는 개수에 +1을 해주어야 실제 생성되는 로그 개수와 일치합니다. 즉, 설정한 Captain_BIN_error.log 파일명에 최초 생성된 후 Captain_BIN_error.log_1 이 붙는 형태로 지정된 개수만큼 로그 파일이 생성됩니다.

MORE