Framework/Django

[Django] Logging

jammmm 2025. 12. 29. 15:46
반응형

개발을 하다보면 시스템의 상태에 대한 로깅이 필요한 경우가 있다. 이번 글에서는 Django 에서 제공하는 logging 기능과 어떻게 사용하는지 등에 대해서 정리해본다.

1. Logging

Django 는 python 의 기본 logging 모듈을 기반으로 기능을 제공한다. logging 모듈에 사용되는 Logger, Handler, Filter, Formatter 등을 Django setting 에 설정하고, 이를 코드에서 호출하여 사용할 수 있다.

- Loggers

로그를 남기기 위해 사용하는 객체로 logging system 의 기능을 제공하는 일종의 인터페이스이다. 각 logger 의 이름을 지정하여 원하는 logger 를 선택해서 logging 을 수행할 수 있다.

Logger 는 DEBUG, INFO, WARNING, ERROR, CRITICAL 중 하나의 log level 을 지정할 수 있다. Logger 에 입력되는 메시지는 여러가지 정보를 가진 Log Record 형식으로 전달된다. Log record 는 메시지의 log level 정보도 포함하고 있는데, 이 level 의 logger 에 지정된 level 이상인 경우에만 logger 에서 메시지를 처리한다.

Logger 에 입력되어 처리하기로 결정된 메시지는 Handler 로 넘어가서 다음 작업을 수행한다.

- Handlers

Logger 에 들어온 메시지를 어떻게 처리할지 결정하는 엔진 역할을 하는 객체이다. 메시지를 파일에 기록하거나, 화면에 출력하거나, socket 통신으로 전송할 수도 있다.

Handler 도 Logger 와 같이 log level 을 지정할 수 있는데, level 에 맞지 않는 메시지의 경우 처리하지 않고 무시한다.

Logger 는 여러개의 Handler 를 가질 수 있는데, 이때 서로 다른 level 을 가진 Handler 를 포함하여 log level 에 맞게 logging 되도록 구성할 수 있다.

- Filters

Filter 는 Logger 와 Handler 사이에서 어떤 메시지를 전달할 지 추가적인 필터링 기능을 제공하는 객체이다.

기본적으로 log level 기준을 통과한 메시지는 모두 Filter 로 전달된다. 여기에 Filter 객체를 추가한 경우 ERROR 메시지만 전달하거나 특정 기준으로 Log record 의 속성을 수정할 수도 있다.

Filter 는 Logger 나 Handler 에 설치할 수 있으며, 여러개의 Filter 를 추가하여 Filter chain 을 구성할 수도 있다.

- Formatters

Formatter 는 logging 처리될 메시지의 텍스트 형식을 설정하는 객체이다. 일반적으로 log record 속성을 포함한 파이썬 문자열 형식으로 구성되지만 필요에 따라 커스텀 형식으로 구성할 수도 있다.

2. Logging 설정 및 사용

Django 에서 Logging 설정은 django settings 의 LOGGING 변수에 정의하여 설정한다. LOGGING 은 logger, handler, filter, formatter 등의 logging 설정을 포함한 dict 형식의 값을 가진다.

사용자가 직접 정의하지 않아도 django 는 기본 logging 설정을 가지고 있는데 이 값은 django/utils/log.py 에 정의되어 있다. (https://docs.djangoproject.com/en/6.0/ref/logging/#default-logging-definition)

- LOGGING 설정

간단하게 StreamHandler 와 FileHandler 를 사용하여 메시지를 화면에 출력하는 logger 와 파일에 기록하는 logger 를 정의한 LOGGING 예시이다.

# djang settings module
LOGGING = {
    "version": 1,  # the dictConfig format version
    "disable_existing_loggers": False,  # retain the default loggers
    "formatters": {
        "verbose": {
            "format": "{levelname} {asctime} {module} {process:d} {thread:d} {message}",
            "style": "{",
        },
    },
    "handlers": {
        # print out log on console
        "console": {
            "class": "logging.StreamHandler",
            "level": "DEBUG",
        },
        # write log on file
        "file": {
            "class": "logging.FileHandler",
            "filename": DEBUG_LOG_FILE,
            "level": "DEBUG",
        },
        # write formatted log on console
        "formatted_console": {
            "class": "logging.StreamHandler",
            "level": "DEBUG",
            "formatter": "verbose", # use verbose formatter
        },
    },
    "loggers": {
        "console_debug": {
            "level": "DEBUG",
            "handlers": ["console"],
        },
        "file_debug": {
            "level": "DEBUG",
            "handlers": ["file"],
        },
        "console_info_with_format": {
            "level": "INFO",
            "handlers": ["formatted_console"],
        }
    }
}


위에 정의된 logger 들을 코드에서 사용하기 위해서는 logging.getLogger() 메서드를 사용하여 logger 객체를 얻어야 한다.

 

# get loggers
logger = logging.getLogger(__name__) # root logger
console_debug_logger = logging.getLogger("console_debug")
file_debug_logger = logging.getLogger("file_debug")
console_info_with_format_logger = logging.getLogger("console_info_with_format")



여기서 console_debug_logger, file_debug_logger, console_info_with_format_logger 는 settings 에 정의한 logger 들을 가져온다. 반면에 logger 는 특정한 이름을 지정하지 않았기 때문에 python logging 모듈에 정의된 root logger 객체를 생성하여 반환한다. 필요한 경우에는 settings 설정을 통해 root logger 도 커스텀할 수 있다.

 

# test loggers
def test_console_loggers(self):
    loggers = [logger, console_debug_logger, console_info_with_format_logger]
    for l in loggers:
        l.debug("debug")
        l.info("info")
        l.warning("warning")
        l.error("error")
        l.critical("critical")



logger 객체를 사용할 때는 logger 객체의 메서드들을 이용하면 된다. 예시와 같이 특정 log level 을 지정된 메서드를 통해 logging 하는 방법도 있고, log() 메서드를 이용하여 log level 을 사용자가 매개변수로 입력해줄 수도 있다.

 

warning
error
critical
debug
info
warning
error
critical
INFO 2025-12-29 06:30:36,342 test_logging 2695 8540835712 info
WARNING 2025-12-29 06:30:36,342 test_logging 2695 8540835712 warning
ERROR 2025-12-29 06:30:36,342 test_logging 2695 8540835712 error
CRITICAL 2025-12-29 06:30:36,342 test_logging 2695 8540835712 critical



위의 테스트 코드를 실행하면 위와 같은 내용이 console 에 출력된 것을 확인할 수 있다.

root logger 는 log level 이 WARNING 으로 지정되어 있기 때문에 warning, error, critical 까지를 출력했다.

console_debug_logger 는 DEBUG 로 지정되어 있기 때문에 debug, info, warning, error, critical 을 모두 출력했다.

마지막으로 console_info_with_format_logger 는 log level 이 INFO 로 지정되어 있기 때문에 info, warning, error, critical 이 출력되었으며, formatter 를 설정했기 때문에 verbose formatter 에 정의된 대로 메시지 형식을 갖추어 로그가 출력됐다.

[References]
https://docs.djangoproject.com/en/6.0/topics/logging/

 

Logging | Django documentation

The web framework for perfectionists with deadlines.

docs.djangoproject.com

https://docs.djangoproject.com/en/6.0/ref/logging/

 

Logging | Django documentation

The web framework for perfectionists with deadlines.

docs.djangoproject.com

 

https://docs.djangoproject.com/en/6.0/howto/logging/

 

How to configure and use logging | Django documentation

The web framework for perfectionists with deadlines.

docs.djangoproject.com

 

반응형