# Django 6.0.7 문서

# 로깅 구성 및 사용 방법

더 보기

- Django 로깅 참조

- Django 로깅 개요

Django는 쉽게 확장할 수 있는 :ref:`기본 로깅 구성 <default-logging-configuration>`을 제공합니다.

## 기본 로깅 호출하기

코드 내에서 로그 메시지를 보내려면 로깅 호출을 입력합니다.

``settings.py``에서 로깅 호출을 사용하고 싶은 유혹에 빠지지 마십시오.

Django 로깅을 `setup()` 함수의 일부로 구성하면 ``settings.py``에 있는 로깅 호출이 예상대로 작동하지 않을 수 있습니다. 왜냐하면 로깅이 그 시점에서 설정되지 않기 때문입니다. 로깅을 탐색하려면 아래 예에서 제안된 뷰 함수를 사용하십시오.

먼저 Python 로깅 라이브러리를 불러온 다음, `logging.getLogger`를 사용하여 로거 인스턴스를 가져옵니다. ``getLogger()`()` 메서드에 로거 및 해당 로거가 기록하는 레코드를 식별할 수 있는 이름을 지정하세요. 좋은 옵션은 ``__name__``을 사용하는 것입니다(자세한 내용은 아래의 로거 네임스페이싱 사용 참고). 이렇게 하면 현재 Python 모듈의 이름이 점으로 구분된 경로 형태로 사용됩니다:

    import logging

    logger = logging.getLogger(__name__)

모듈 수준에서 이 선언을 수행하는 것이 좋습니다.

그런 다음 함수 안(예: 뷰 안)에서 로거에 레코드를 보냅니다:

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

이 코드가 실행되면 해당 메시지를 포함한 :class:`~logging.LogRecord`가 로거로 전송됩니다. Django의 기본 로깅 구성을 사용하는 경우 메시지가 콘솔에 나타납니다.

위의 예에서 사용된 `WARNING` 수준은 여러 로깅 심각도 수준들 <topic-logging-parts-loggers>`중 하나입니다: ``DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`. 따라서 다른 예는 다음과 같습니다:

    logger.critical("Payment system is not responding")

중요

``WARNING``보다 낮은 수준의 레코드는 기본적으로 콘솔에 나타나지 않습니다. 이 동작을 변경하려면 추가 구성이 필요합니다.

## 로깅 구성 사용자 정의

Django의 로깅 구성은 별 다른 구성 없이도 작동하지만, 몇 가지 추가 구성을 통해 로그가 다양한 대상(로그 파일, 외부 서비스, 이메일 등)으로 전송되는 방식을 정확하게 제어할 수 있습니다.

다음을 설정할 수 있습니다:

- 어떤 레코드를 어떤 핸들러로 보낼지 결정하는 로거 매핑

- 받은 레코드로 무엇을 할지 결정하는 핸들러

- 레코드 전송에 대한 추가 제어를 제공하고 레코드를 바로 수정할 수 있는 필터

- `LogRecord` 객체를 사람이나 다른 시스템에서 사용할 문자열이나 다른 형식으로 변환하는 포맷터

로깅 구성에는 다양한 방법들이 있습니다. Django에서는 `LOGGING` 구성이 가장 일반적으로 사용됩니다. 이 구성은 :ref:`dictConfig 형식 <logging-config-dictschema>`을 사용하고 :ref:`기본 로깅 구성 <default-logging-definition>`을 확장합니다.

사용자 지정 설정이 Django의 기본값과 병합되는 방법에 대한 설명은 :ref:`configuring-logging`을 참조하세요.

로깅을 구성하는 다른 방법에 대한 자세한 내용은 mod:Python 로깅 문서 <python:logging.config>`를 참조하세요. 단순화를 위해 이 문서에서는 ``LOGGING` 설정을 통한 구성만 고려합니다.

### 기본 로깅 구성

로깅을 구성할 때, 다음을 수행하는 것이 좋습니다:

#### `LOGGING` 사전 생성

``settings.py``에서:

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

``disable_existing_loggers``를 ``False``로 설정하여 기본 로깅 구성을 유지하고 확장하는 것이 거의 항상 좋습니다.

#### 핸들러 구성

이 예제는 Python의 `FileHandler`를 사용하여 ``DEBUG`` 이상의 로그를 (프로젝트 루트에 있는) `general.log` 파일에 저장하는 ``file``이라는 단일 핸들러를 구성합니다:

    LOGGING = {
        # ...
        "handlers": {
            "file": {
                "class": "logging.FileHandler",
                "filename": "general.log",
            },
        },
    }

핸들러 클래스마다 사용하는 구성 옵션이 다릅니다. 사용 가능한 핸들러 클래스에 대한 자세한 내용은 Django에서 제공하는 :class:`~django.utils.log.AdminEmailHandler`와 Python에서 제공하는 다양한 :mod:`handler classes <logging.handlers>`를 참고하세요.

로깅 수준은 핸들러에서도 설정할 수 있습니다(기본적으로 모든 수준의 로그 메시지를 수락함). 위의 예를 사용하여 다음을 추가합니다:

    {
        "class": "logging.FileHandler",
        "filename": "general.log",
        "level": "DEBUG",
    }

`DEBUG` 수준 이상의 레코드만 허용하는 핸들러 구성을 정의합니다.

#### 로거 매핑 설정

이 핸들러로 레코드를 보내려면, 로거 매핑을 구성합니다. 예를 들면 다음과 같습니다:

    LOGGING = {
        # ...
        "loggers": {
            "": {
                "level": "DEBUG",
                "handlers": ["file"],
            },
        },
    }

매핑의 이름은 처리할 로그 레코드를 결정합니다. 이 구성(`''`)은 unnamed*입니다. 즉, *모든 로거의 레코드를 처리한다는 의미입니다(레코드를 처리할 로거를 결정하기 위해 매핑 이름을 사용하는 방법은 아래의 로거 네임스페이싱 사용 참조).

`DEBUG` 수준 이상의 메시지를 ``file``이라는 핸들러로 전달합니다.

로거는 여러 핸들러에 메시지를 전달할 수 있으므로, 로거와 핸들러 간의 관계는 many-to-many입니다.

만약 다음을 실행하는 경우:

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

코드에서 프로젝트 루트의 `general.log` 파일에서 해당 메시지를 찾을 수 있습니다.

#### 포맷터 구성

By default, the final log output contains the message part of each `LogRecord` object. Use a formatter if you want to include additional data. First name and define your formatters - this example defines formatters named `verbose` and `simple`:

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

`style` 키워드를 사용하면 `str.format`에 ``{``를 지정하거나 :class:`string.Template()` 형식에 ``$``를 지정할 수 있습니다. 기본값은 ``$``입니다.

include할 수 있는 `LogRecord` 속성에 대해 :ref:`logrecord-attributes`를 참조하십시오.

포맷터를 핸들러에 적용하려면, 이름으로 포맷터를 참조하는 핸들러의 사전에 `formatter` 항목을 추가하십시오. 예를 들면 다음과 같습니다:

    "handlers": {
        "file": {
            "class": "logging.FileHandler",
            "filename": "general.log",
            "formatter": "verbose",
        },
    }

#### 로거 네임스페이싱 사용

명명되지 않은 로깅 설정 ``’’``은 모든 Python 응용 프로그램에서 로그를 캡처합니다. 명명된 로깅 구성은 이름이 일치하는 로거에서만 로그를 캡처합니다.

로거 인스턴스의 네임스페이스는 :func:`~logging.getLogger`를 사용하여 정의됩니다. 예를 들어 ``my_app``의 ``views.py``에서:

    logger = logging.getLogger(__name__)

는 `my_app.views` 네임스페이스에 로거를 생성합니다. ``__name__``을 사용하면 프로젝트의 애플리케이션 내에서 출처에 따라 로그 메시지를 자동으로 구성할 수 있습니다. 또한 이름 충돌이 발생하지 않도록 보장해줍니다.

``my_app.views``라는 로거 매핑은 이 로거에서 레코드를 캡처합니다:

    LOGGING = {
        # ...
        "loggers": {
            "my_app.views": {...},
        },
    }

`my_app``이라는 이름의 로거 매핑은 ``my_app` 네임스페이스(`my_app.views`, `my_app.utils` 등 포함) 내의 모든 로거에서 레코드를 캡처하기 떄문에 더 관대합니다:

    LOGGING = {
        # ...
        "loggers": {
            "my_app": {...},
        },
    }

다음과 같이 로거 네임스페이스를 명시적으로 정의할 수도 있습니다:

    logger = logging.getLogger("project.payment")

그리고 그에 따라 로거 매핑을 설정합니다.

##### 로거 계층 및 전파 사용

로거 이름 지정은 *계층적*입니다. `my_app``은 ``my_app.views.private``의 부모인 ``my_app.views``의 부모입니다. 달리 지정하지 않는 한, 로거 매핑은 처리하는 레코드를 부모에게 전파합니다. ``my_app.views.private` 네임스페이스에 있는 로거의 레코드는 `my_app` 및 `my_app.views` 모두에 대한 매핑에 의해 처리됩니다.

이 동작을 관리하려면, 당신이 정의한 매핑에서 전파 키를 설정합니다.

    LOGGING = {
        # ...
        "loggers": {
            "my_app": {
                # ...
            },
            "my_app.views": {
                # ...
            },
            "my_app.views.private": {
                # ...
                "propagate": False,
            },
        },
    }

``propagate``의 기본값은 ``True``입니다. 이 예에서 ``my_app.views.private``의 로그는 상위에서 처리되지 않지만 ``my_app.views``의 로그는 처리됩니다.

### 반응형 로깅 구성

로깅은 필요하지 않은 정보를 제외한 가능한 많은 정보를 포함할 때 가장 유용합니다. 필요한 정보의 양은 수행 중인 작업에 따라 다릅니다. 디버깅할 때는 프로덕션에서는 과도하고 도움이 되지 않는 수준의 정보가 필요합니다.

필요할 때 필요한 세부 수준을 제공하도록 로깅을 구성할 수 있습니다. 이를 위해 수동으로 구성을 변경하는 것보다, 환경에 따라 자동으로 구성을 적용하는 것이 더 좋은 방법입니다.

예를 들어, 개발 및 스테이징 환경에서 `DJANGO_LOG_LEVEL` 환경 변수를 적절하게 설정하여 로거 매핑에서 사용할 수 있습니다:

    "level": os.getenv("DJANGO_LOG_LEVEL", "WARNING")

- 따라서 환경이 더 낮은 로그 수준을 지정하지 않는 한 이 구성은 `WARNING` 이상의 심각도를 가진 레코드만 핸들러로 전달합니다.

구성의 다른 옵션(예: 핸들러의 `level` 또는 `formatter` 옵션)도 유사하게 관리할 수 있습니다.