[python] Django에서 Python 로깅의 우아한 설정

나는 아직 내가 만족하는 Django로 Python 로깅을 설정하는 방법을 찾지 못했습니다. 내 요구 사항은 매우 간단합니다.

  • 다른 이벤트에 대한 다른 로그 처리기-즉, 다른 파일에 기록 할 수 있기를 원합니다.
  • 내 모듈의 로거에 쉽게 액세스 할 수 있습니다. 모듈은 적은 노력으로 로거를 찾을 수 있어야합니다.
  • 명령 줄 모듈에 쉽게 적용 할 수 있어야합니다. 시스템의 일부는 독립 실행 형 명령 줄 또는 데몬 프로세스입니다. 로깅은 이러한 모듈에서 쉽게 사용할 수 있어야합니다.

내 현재 설정은 logging.conf내가 로그하는 각 모듈에서 파일 및 설정 로깅 을 사용하는 것입니다. 옳지 않다.

원하는 로깅 설정이 있습니까? 자세히 설명하십시오 : 구성 설정 방법 ( logging.conf코드에서 사용 또는 설정), 로거를 시작하는 위치 / 시점, 모듈에서 액세스하는 방법 등.



답변

지금까지 찾은 가장 좋은 방법은 settings.py에서 로깅 설정을 초기화하는 것입니다. 구성 파일을 사용하거나 단계별로 프로그래밍 방식으로 수행 할 수 있습니다. 요구 사항에 따라 다릅니다. 핵심은 보통 레벨을 사용하고 때로는 logging.Filters를 사용하여 루트 로거에 원하는 핸들러를 추가한다는 것입니다. 적절한 파일, 콘솔, syslog 등에 원하는 이벤트를 가져 오기 위해 필터를 사용합니다. 물론 다른 로거에 핸들러를 추가 할 수 있습니다. 그러나 내 경험상 일반적으로 이것이 필요하지 않습니다.

각 모듈에서 다음을 사용하여 로거를 정의합니다.

logger = logging.getLogger(__name__)

모듈에서 이벤트를 로깅하는 데 사용하고 (더 구분하고 싶다면) 위에서 만든 로거의 자식 인 로거를 사용하십시오.

내 앱이 settings.py에 로그인을 구성하지 않는 사이트에서 잠재적으로 사용되는 경우 다음과 같이 어딘가에 NullHandler를 정의합니다.

#someutils.py

class NullHandler(logging.Handler):
    def emit(self, record):
        pass

null_handler = NullHandler()

로깅을 사용하는 내 앱의 모듈에서 생성 된 모든 로거에 인스턴스가 추가되었는지 확인합니다. (참고 : NullHandler는 이미 Python 3.1 용 로깅 패키지에 있으며 Python 2.7에 포함될 예정입니다.) 따라서 :

logger = logging.getLogger(__name__)
logger.addHandler(someutils.null_handler)

이는 settings.py에 로그인을 구성하지 않는 사이트에서 모듈이 잘 작동하는지 확인하고 “로거 XYZ에 대한 핸들러를 찾을 수 없습니다”라는 성가신 메시지 (잠재적으로 경고)를받지 않도록하기위한 것입니다. 잘못 구성된 로깅).

이렇게하면 명시된 요구 사항을 충족합니다.

  • 현재 수행하는 것처럼 다른 이벤트에 대해 다른 로그 핸들러를 설정할 수 있습니다.
  • 모듈의 로거에 쉽게 액세스- getLogger(__name__).
  • 명령 줄 모듈에 쉽게 적용 할 수 있으며 settings.py.

업데이트 : 버전 1.3부터 ​​Django 는 로깅 지원을 통합 합니다 .


답변

나는 이것이 이미 해결 된 대답이라는 것을 알고 있지만 django> = 1.3에 따라 새로운 로깅 설정이 있습니다.

이전에서 새 것으로 이동하는 것은 자동이 아니므로 여기에 적어 두겠습니다.

그리고 물론 더 많은 것을 위해 django 문서 를 확인 하십시오 .

이것은 django-admin createproject v1.3으로 기본적으로 생성되는 기본 conf입니다. 마일리지는 최신 django 버전으로 변경 될 수 있습니다.

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        }
    }
}

이 구조는 다음 블록을 지시하는 표준 Python 로깅 dictConfig를 기반으로합니다 .

  • formatters -해당 값은 각 키가 포맷터 ID이고 각 값이 해당 Formatter 인스턴스를 구성하는 방법을 설명하는 dict 인 dict입니다.
  • filters -해당 값은 각 키가 필터 ID 인 dict이고 각 값은 해당 Filter 인스턴스를 구성하는 방법을 설명하는 dict입니다.
  • handlers-해당 값은 각 키가 핸들러 ID 인 dict이고 각 값은 해당 Handler 인스턴스를 구성하는 방법을 설명하는 dict입니다. 각 핸들러에는 다음 키가 있습니다.

    • class(필수). 이것은 핸들러 클래스의 완전한 이름입니다.
    • level(선택 과목). 핸들러의 레벨입니다.
    • formatter(선택 과목). 이 핸들러에 대한 포맷터의 ID입니다.
    • filters(선택 과목). 이 핸들러에 대한 필터의 ID 목록입니다.

나는 보통 적어도 이것을한다 :

  • .log 파일 추가
  • 이 로그에 쓰도록 내 앱 구성

다음으로 번역됩니다.

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    },
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse'
        }
    },
    'handlers': {
        'null': {
            'level':'DEBUG',
            'class':'django.utils.log.NullHandler',
        },
        'console':{
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        # I always add this handler to facilitate separating loggings
        'log_file':{
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(VAR_ROOT, 'logs/django.log'),
            'maxBytes': '16777216', # 16megabytes
            'formatter': 'verbose'
        },
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler',
            'include_html': True,
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
        'apps': { # I keep all my of apps under 'apps' folder, but you can also add them one by one, and this depends on how your virtualenv/paths are set
            'handlers': ['log_file'],
            'level': 'INFO',
            'propagate': True,
        },
    },
    # you can also shortcut 'loggers' and just configure logging for EVERYTHING at once
    'root': {
        'handlers': ['console', 'mail_admins'],
        'level': 'INFO'
    },
}

편집하다

이제 요청 예외가 항상 기록 되고 티켓 # 16288을 참조하십시오 .

기본적으로 debug가 True 일 때 이메일이 전송되지 않도록 mail_admins에 대한 올바른 필터를 명시 적으로 포함하도록 위의 샘플 conf를 업데이트했습니다.

필터를 추가해야합니다.

'filters': {
    'require_debug_false': {
        '()': 'django.utils.log.RequireDebugFalse'
    }
},

mail_admins 핸들러에 적용합니다.

    'mail_admins': {
        'level': 'ERROR',
        'filters': ['require_debug_false'],
        'class': 'django.utils.log.AdminEmailHandler',
        'include_html': True,
    }

그렇지 않으면 django.core.handers.base.handle_uncaught_exceptionsettings.DEBUG가 True 인 경우 ‘django.request’로거에 오류를 전달하지 않습니다.

Django 1.5에서이 작업을 수행하지 않으면

DeprecationWarning : ‘mail_admins’로깅 핸들러에 정의 된 필터가 없습니다. 암시 적 디버그-거짓 전용 필터 추가

그러나 django 1.4와 django 1.5에서 모두 올바르게 작동합니다.

** 편집 종료 **

이 conf는 django 문서의 샘플 conf에서 영감을 얻었지만 로그 파일 부분을 추가했습니다.

나는 종종 다음을 수행합니다.

LOG_LEVEL = 'DEBUG' if DEBUG else 'INFO'

...
    'level': LOG_LEVEL
...

그런 다음 내 파이썬 코드에서 로깅 conf가 정의되지 않은 경우 항상 NullHandler를 추가합니다. 이렇게하면 핸들러가 지정되지 않은 경우 경고가 발생하지 않습니다. Django ( ref ) 에서만 호출되지 않는 libs에 특히 유용합니다.

import logging
# Get an instance of a logger
logger = logging.getLogger(__name__)
class NullHandler(logging.Handler): #exists in python 3.1
    def emit(self, record):
        pass
nullhandler = logger.addHandler(NullHandler())

# here you can also add some local logger should you want: to stdout with streamhandler, or to a local file...

[…]

logger.warning('etc.etc.')

도움이 되었기를 바랍니다!


답변

파일 urls.py을 사용하여 최상위 수준에서 로깅을 초기화 logging.ini합니다.

의 위치는에서 logging.ini제공 settings.py되지만 그게 전부입니다.

그런 다음 각 모듈은

logger = logging.getLogger(__name__)

테스트, 개발 및 프로덕션 인스턴스를 구분하기 위해 다른 logging.ini 파일이 있습니다. 대부분의 경우, 오류 만있는 stderr로 이동하는 “콘솔 로그”가 있습니다. 로그 디렉토리로 이동하는 일반 롤링 로그 파일을 사용하는 “애플리케이션 로그”가 있습니다.


답변

현재 직접 만든 로깅 시스템을 사용하고 있습니다. 로깅을 위해 CSV 형식을 사용합니다.

django-csvlog

이 프로젝트에는 여전히 완전한 문서가 없지만 작업 중입니다.


답변