[Django] - logging

오동훈·2023년 1월 21일
0

Django

목록 보기
19/23
post-custom-banner

1. 로그란?

로그는 모든 행위와 이벤트 정보를 시간의 경과에 따라 기록한 데이터입니다.

따라서 시스템 상에서 로그를 생성하는 과정을 로깅이라고 합니다.

Django를 통해 개발하면서 이러한 로그를 남기고 추후에 활용할 수 있습니다.

2. Django에서 로그는 어떻게 남기나~?

Django에서는 Python 내장 logging 모듈을 사용하고 있습니다.

1. 구성 요소

Python 내장 logging 모듈은 다음과 같이 크게 세 가지로 구성되어 있는데요 한 번 살펴보겠습니다.

1. Loggers

우선 Loggers 입니다. Logger는 logging 시스템의 진입점으로 메세지를 쓸 수 있습니다.
이 때 메세지는 다음과 같은 로그 레벨을 가질 수 있습니다.

  • DEBUG - 디버깅을 위한 정보
  • INFO - minor한 문제에 대한 정보
  • WARNING - minor한 문제에 대한 정보
  • ERROR - major한 문제에 대한 정보
  • CRITICAL - critical한 문제에 대한 정보

    ⭐ 중요도 DEBUG < INFO < WARNING < ERROR < CRITICAL

Logger에 메세지가 들어오면 메세지의 로그 레벨과 Logger의 로그 레벨을 비교합니다.
메시지의 로그 레벨이 Logger의 로그 레벨 이상이면 메시지가 추가됩니다.

예를 들어, INFO Logger에는 DEBUG를 제외한 모든 나머지 로그 레벨의 메시지가 전부 들어올 수 있습니다.

2. Handlers

Handler는 Logger의 각 메세지에 발생하는 일을 결정하는 엔진입니다.
화면, 파일 또는 네트워크 소켓에 메세지를 쓰는 것과 같은 특정 로깅 동작을 설명합니다.
Handler도 로그 레벨이 있으며 동일하게 동작합니다.

3. Filters

Filter는 Logger에서 Handler로 전달되는 로그 레코드에 대한 추가 제어를 제공합니다.

4. Formatters

로그 데이터들을 텍스트로 렌더링 되는데 그 때의 형식을 지정합니다.

2. 로깅 구성

1. Logging 만들기

disable_existing_loggers = False로 설정하는 것은 기본 로깅 구성을 유지하고 확장한다는 의미를 가지고 있습니다.

LOGGING = {
    'version': 1,                       # the dictConfig format version
    'disable_existing_loggers': False,  # retain the default loggers
}

2. Handler 구성

file이라는 단일 핸들러는 Python의 FileHandler를 사용해 DEBUG 수준 이상의 로그를 general.log(프로젝트 루트에 있음)에 저장하라는 코드입니다.

  • 로그 레코드로 무슨 작업 할 것인지에 대한 정의하는 곳이 Handler 입니다.
  • 로깅 수준은 핸들러에서도 설정 가능합니다.
  • 로그 레코드 log Level < Handler log Level
  • 로거는 핸들러를 여러 개 가질 수 있고, 각 핸들러는 서로 다른 로그 레벨을 가질 수 있습니다.
    메세지의 중요도에 따라 다른 방식의 로그 처리가 가능합니다.
LOGGING = {
    [...]
    'handlers': {
        'file': {
            'class': 'logging.FileHandler',	# FileHandler 사용
            'filename': 'general.log',		# 파일명을 general.log로 저장
            'level': 'DEBUG',				# log 수준은 DEBUG 이상
        },
    },
}

3. logger mapping

로거, 로그 레코드 저장소입니다. loggers에 첫 번째 logger는 ''로 이름이 없습니다. 이는 모든 로거의 레코드를 처리한다는 의미를 가지고 있습니다. 그리고 이 로거는 DEBUG 로그 수준 이상의 메세지를 file이라는 handler로 전달합니다.

  • 로거는 여러 핸들러에 메세지를 전달할 수 있어, 로거와 핸들러 간의 관계는 다대다입니다.
LOGGING = {
    [...]
    'loggers': {
        '': {
            'level': 'DEBUG',		# log 수준은 DEBUG 이상
            'handlers': ['file'],	# file이라는 handle로 전달 / 여러 핸들러에 전달 가능
        },
    },
}

로그를 실행하보고 싶다면 다음처럼 log level을 지정해 에러를 일으켜 주면 됩니다. 그러면 루트에 있는 general.log 파일에서 해당 log를 조회할 수 있습니다.

logger.debug('Attempting to connect to API')

위와 같은 방식으로는 현재 ''로 모든 DEBUG 이상의 로그들을 처리할 수 있지만, 그렇지 않고 특정 이름으로 지정되어 있다면 다음처럼 지정해 로그를 발생시켜주면 됩니다.

LOGGING = {
    [...]
    'loggers': {
        'my_app.views': {
            ...
        },
    },
}
import logging

logger = logging.getLogger(__name__)
logger = logging.getLogger("")

def some_view(request):
    ...
    if some_risky_state:
        logger.warning('Platform is running at risk')

4. formatter 구성

formatter는 log가 저장되는 텍스트의 포맷 형식을 정의할 수 있습니다.

LOGGING = {
    [...]
    'formatters': {
        'verbose': {
            'format': '{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}',
            'style': '{',
        },
        'simple': {
            'format': '{levelname} {message}',
            'style': '{',
        },
    },
}

python Docs - LogRecode 속성을 참고하면 다양한 포맷 형식을 확인할 수 있습니다.

5. logger의 계층화

my_appmy_app.views상위이고, my_app.viewsmy_app.views.private의 상위입니다. 따라서 my_app에서는 my_app.views.private에서도 확인해 처리할 수 있습니다. 달리 지정하지 않는 한 로거 매핑은 레코드를 부모에게 전파합니다.

  • propagate의 기본값은 True입니다.
  • my_app.views.private는 상위에서 처리되지 않게 되고, my_app.views의 로그는 상위에서 처리되게 됩니다.
LOGGING = {
    [...]
    'loggers': {
        'my_app': {
            [...]
        },
        'my_app.views': {
            [...]
        },
        'my_app.views.private': {
            [...]
            'propagate': False,		# 전파 False
        },
    },
}

6. 로깅 호출 메소드

  • logger.debug() : DEBUG 레벨의 로그 메시지를 생성
  • logger.info() : INFO 레벨의 로그 메시지를 생성
  • logger.warning() : WARNING 레벨의 로그 메시지를 생성
  • logger.ERROR() : ERROR 레벨의 로그 메시지를 생성
  • logger.critical() : CRITICAL 레벨의 로그 메시지를 생성
  • logger.log() : 원하는 로그 레벨을 정해서 로그 메시지를 생성
  • logger.exception() : 익셉션 스택 정보를 포함하는 ERROR 레벨의 로그 메시지를 생성

Django 공식문서 - Logging
Django 공식문서 - Logging 구성 및 사용 방법
Django 공식문서 - Django 로깅 개요
python Docs - LogRecode 속성

profile
삽질의 기록들🐥
post-custom-banner

0개의 댓글