본문 바로가기

개발이야기/Python

Django에서 Request Log를 쉽게 확인해보자

728x90

현재 현업에서 Django를 사용해 Test에서 활용할 수 있는 Mock 서버를 만들어 사용 중 이다.

Mock 서버에는 자동화 Test에서 여러 요청 들이 들어오는데 언제 어떤 요청이 들어왔는지 확인이 필요할 때가 있다.

그럴 때 마다 Docker logs를 사용해

귀찮고 눈이 아프게

확인했었는데 여간 불편한 일이 아니었다.

 

그래서, Django에 기본 Logger를 적용하고 이를 쉽게 확인 할 수 있는 방법을 적용해보려고 한다.

먼저 Django 기본 Logger 부터 적용해보자.

Django 기본 Logger

Django 기본 Logger 는 Django runserver 를 실행해보면 확인 해볼 수 있다.
서버 실행 부터 Exception, Request 정보 등 Debugging에 필요한 내용들이 콘솔에 표시 된다.

Django의 기본 Logger 는 django.util.log 에 정의되어 있다. 우리는 이를 settings.py에 재 정의해야 한다.

# settings.py
# ...
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    # 로그를 출력할 조건
    'filters': {
        'require_debug_false': {
            # debug false인 경우 출력
            '()': 'django.utils.log.RequireDebugFalse',
        },
        'require_debug_true': {
            # debug true 인 경우 출력
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    # 로그 출력 포맷 정의 - 2가지 포맷을 정의 (logfile, django.server)
    'formatters': {
        'logfile': {
            'format': '[%(levelname)s] [%(asctime)s] [%(name)s] %(message)s',
            'datefmt': '%Y/%m/%d %H:%M:%S'
        },

        'django.server': {
            '()': 'django.utils.log.ServerFormatter',
            'format': '[{server_time}] {message}',
            'style': '{',
        },
    },

    # 로그를 출력할 채널 (콘솔, File)
    'handlers': {
        'console': {
            'level': 'INFO', # 로그 레벨
            'class': 'logging.StreamHandler', # 콘솔로 출력
        },
        'django.server': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'django.server', # 출력할 포맷 정의
        },
        'file': {
            'level': 'INFO',
            'encoding': 'utf-8', # 출력 인코딩
            'class': 'logging.handlers.RotatingFileHandler', 
            # file로 출력(특정 조건이면 새로운 파일을 생성)
            'filename': BASE_DIR / 'logs/request.log', # log 파일 위치
            'maxBytes': 1024*1024*5, # log 파일의 최대 Size (5MB)
            'backupCount': 10, # 생성될 최대 Log 파일의 개수, 이 개수를 넘어가면 가장 오래된 파일이 삭제됨
            'formatter': 'logfile', # 출력할 포맷 정의
        },
    },

    'loggers': {
        'django': {
           'handlers': ['console', 'file'],
           'level':'INFO',  
        },

        'django.server': { # django.server 로거는 runserver의 로그임
            'handlers': ['django.server'], # 출력 채널 정의
            'level': 'INFO',
            'propagate': False,
        },

        'django.request': { # django.request 로거
            'handlers': ['console', 'file'], # 출력 채널을 콘솔과 파일로 선택
            'level':'INFO',
            'propagate': False,
        }
    },
}

위에 있는 내용을 Flow chart 로 그려보면 아래와 같다.

django.request logger

Django로 들어오는 request에 대한 정보를 로그로 출력하기 위해서 django.request logger 가 필요하다.
이를 쉽게 사용할 수 있는 Python package가 있다.
django-request-logging 이다.

$ pip install django-request-logging

설치가 완료되면 settings.py MIDDLEWARE 에 아래와 같이 추가 한다.

MIDDLEWARE = (
    ...,
    'request_logging.middleware.LoggingMiddleware',
    ...,
)

추가로 django.request 패키지는 기본적으로 log에 ansi color를 적용해 출력하고 있는데 이를 해제 하려면 settings.py에 아래와 같이 옵션을 추가해 주면 된다.

REQUEST_LOGGING_ENABLE_COLORIZE=False

위에 LOGGING 설정에서 따로 필터를 적용하지 않았기 때문에 django runserver나 웹서버에서 실행되는 상태에도 요청에 대한 로그가 파일로 남게 된다.
웹서버로 실행시키는 경우 로그 파일이 담겨있는 폴더는 생성해줘야 할 수도 있다.

django log viewer

지금까지 django로 들어오는 모든 요청에 대해 로그를 출력하고 그 내용을 file에 적재할 수 있도록 구성이 마무리가 되었다.
이를 확인하기 위해서는 아직까지 Django가 운영되고 있는 환경에 직접 접근해 file을 열어봐야 하는데..
이를 Django admin에서 볼 수 있게 해주는 Python 패키지가있다.

django log viewer 다.

pip install django-log-viewer

pip로 설치가 완료되면 settings.py INSTALLED_APP에 아래와 같이 추가해주자.

INSTALLED_APPS = [
    ...
    "log_viewer",
]

그다음엔 로그를 확인 할 수 있도록 URL을 정의해줘야 한다.
project urls.py에 아래와 같이 log viewer의 URL을 정의해보자

path('logs/', include('log_viewer.urls')),

이제 django 를 실행하고 /logs 로 진입해보자
아래와 같이 log 를 admin page 에서 확인 할 수 있다.
다운로드도 가능하다.

django log viewer에서 로그를 가져오기 위한 몇가지 옵션들이 있다.
로그를 구분하기 위한 패턴을 설정해야 개별 로그 별로 표시 된다.

그리고 로그가 쌓이는 위치도 아래 처럼 지정해주면 좋다.

LOG_VIEWER_FILES_DIR = 'logs/'
LOG_VIEWER_PATTERNS = ['[INFO]', '[DEBUG]', '[WARNING]', '[ERROR]', '[CRITICAL]']

자세한 내용은 아래 페이지를 참조하자.

https://pypi.org/project/django-log-viewer/