[Django] Logging
개발을 하다보면 시스템의 상태에 대한 로깅이 필요한 경우가 있다. 이번 글에서는 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