Python 뿐만 아니라 모든 종류의 코드를 작성하다 보면 로그에 대한 고민을 하게 됩니다. 그 중 rotating log 방식은 리눅스 커널에서부터 다양한 라이브러리에서 많이 사용하는 좋은 로그 시스템입니다. 디스크를 무한하게 점유할 가능성을 없애 주고, 로그의 양이 많고 적음에도 어느 정도 자유롭게 해 줍니다. 저는 원래 C를 많이 사용해 왔지만, 근래에는 거의 python 코드만 작성하고 있는 것 같습니다. 그래서 오늘은 Python rotating log 설정하는 방법에 대해 기록하려고 합니다.

글의 내용은 python library 공식 블로그를 참조하여 작성하였습니다.

Python rotating log 는 logging 모듈 이용

Python rorating log 를 구성하기 위해서 logging 모듈을 이용합니다. Python의 기본 모듈인 logging은 거의 모든 방식의 logging 요구사항을 충족시킬 수 있는 훌륭한 로그 모듈입니다. Python logging 모듈은 두 가지 rotating 방식을 지원합니다.

  • File size 기반 rotating logs
  • 날짜/시간 기반 rotating logs

File size 기반 rotating logs

File size 기반으로 rotating 하기 위해서 logging 모듈의 핸들러 중, RotatingFileHandler 를 사용합니다.

Python logging 모듈의 handler 중 RotatingFileHandler 클래스를 사용하면 로그 크기에 따라 rotating log 를 동작할 수 있는 핸들러 개체를 만들 수 있습니다. maxBytes 파라미터를 이용하여 현재 로그를 끊고 다음 로그 파일을 시작할 시기를 알릴 수 있습니다.

즉, 로그 파일이 특정 크기에 도달하면 rotating 됩니다. 파일 크기를 초과하려고 할 때 발생합니다. 핸들러는 파일을 닫고 새 파일을 자동으로 엽니다. backupCount 파라미터에 숫자를 전달하면 로그 파일 끝에 “.1”, “.2” 등이 추가되어 이전 파일들이 backupCount 개수 만큼 보관됩니다. 간단한 예를 살펴보겠습니다.

import logging
import time
from logging.handlers import RotatingFileHandler
#----------------------------------------------------------------------
def create_rotating_log(path):
    """
    Creates a rotating log
    """
    logger = logging.getLogger("Rotating Log")
    logger.setLevel(logging.INFO)
    
    # add a rotating handler
    handler = RotatingFileHandler(path, maxBytes=20,
                                  backupCount=5)
    logger.addHandler(handler)
    
    for i in range(10):
        logger.info("This is test log line %s" % i)
        time.sleep(1.5)
        
#----------------------------------------------------------------------
if __name__ == "__main__":
    log_file = "test.log"
    create_rotating_log(log_file)

logger 의 log level 을 INFO 로 설정하였습니다. logger의 단계는 severity 기준으로 다음과 같습니다.

LevelNumeric value
CRITICAL50
ERROR40
WARNING30
INFO20
DEBUG10
NOTSET0
logging 모듈의 level 값

Log level을 설정하면 해당 level 미만의 로그 유형은 출력 또는 기록이 안됩니다. 위의 예제에서 logging.INFO 로 설정했으므로, logger.debug(‘hello, Jay’) 와 같은 로그를 코딩하더라도 실제 기록은 안됩니다.

하지만, 로그 레벨은 코드에서 쉽게 변경할 수 있으므로, 애초 코드 작성시 적절한 레벨로 로그 구문을 코딩해 놓으면 추후 디버깅 상황에 따라 로그 레벨을 변경해서 구동해 보면서 문제를 편리하게 찾을 수 있습니다.

다른 이야기를 길게 했는데, 위의 예제에서 로그 파일이 20 바이트를 넘을 때 마다 python rotating log 가 구동되면서 최대 5개의 백업 파일을 생성하는 것을 확인할 수 있습니다. 20 바이트는 실험을 위한 너무 작은 파일 사이즈입니다. 적용할 때 적절한 크기로 설정하고 구동하기 바랍니다.

다음은 TimedRotatingFileHandler 를 살펴보겠습니다.

날짜/시간 기반 python rotating log

TimedRotatingFileHandler를 사용하면 코드를 구동한 후 경과된 시간에 따라 rotating log 를 생성할 수 있습니다.

  • second (s)
  • minute (m)
  • hour (h)
  • day (d)
  • w0-w6 (weekday, 0=Monday)
  • midnight

시간의 흐름에 따라 rotating 되는 로그를 설정하려면 두 번째 인수인 when 매개변수에 위의 시간 단위를 전달해야 합니다. interval 매개변수는 when으로 설정한 단위의 개수를 의미한다고 보시면 되겠습니다. 숫자로 설정하여 10분마다, 5일마다, 3시간마다 python rotating log 를 구동할 수 있습니다. 아래 예를 살펴보겠습니다.

import logging
import time
from logging.handlers import TimedRotatingFileHandler
#----------------------------------------------------------------------
def create_timed_rotating_log(path):
    """"""
    logger = logging.getLogger("Rotating Log")
    logger.setLevel(logging.INFO)
    
    handler = TimedRotatingFileHandler(path,
                                       when="m",
                                       interval=1,
                                       backupCount=5)
    logger.addHandler(handler)
    
    for i in range(6):
        logger.info("This is a test!")
        time.sleep(75)
#----------------------------------------------------------------------
if __name__ == "__main__":
    log_file = "timed_test.log"
    create_timed_rotating_log(log_file)

코드를 실행하면 매 분마다 로그 파일이 나누어지며 최대 5개의 백업파일을 생성할 것입니다. 만약 한 시간 마다 rotating하고 싶다면 interval 을 60으로 설정하거나, when=”h” 와 같이 설정하면 됩니다.

정리

이제 강력한 Python rotating log 를 사용하는 방법을 알게 되었습니다. 자신만의 로그 library를 꾸미거나, 운영중이거나 향후 작성하는 프로그램에 통합할 수 있기를 바랍니다.


Jay

Jay

S/W Engineer!!

0개의 댓글

답글 남기기

아바타 플레이스홀더