본문 바로가기

Django/따라하는 장고

41. logging(로깅)

저번 게시물에서 DEBUG=False 로 설정했기 때문에 파이보 이용중 오류가 발생한다면 404오류같은 페이지가 출력되고 오류의 원인같은 정보는 출력되지 않는다. 이제 오류의 원인이 무엇인지 파악을 할 수 없는데 그렇다고 DEBUG=True 로 변경할수는 없다. 이를 해결하기 위해 로그 파일을 이용하는것이 가장 좋다.

로그를 파일로 저장하기 위해서 먼저 장고의 DEFAULT_LOGGING 설정을 알아보자.

DEFAULT_LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse',
        },
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'formatters': {
        'django.server': {
            '()': 'django.utils.log.ServerFormatter',
            'format': '[{server_time}] {message}',
            'style': '{',
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
        },
        'django.server': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'django.server',
        },
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console', 'mail_admins'],
            'level': 'INFO',
        },
        'django.server': {
            'handlers': ['django.server'],
            'level': 'INFO',
            'propagate': False,
        },
    }
}

version 은 고정값 1을 사용해야만 한다. 다른값이 입력되면 오류가 발생한다.

disable_existing_loggers 항목은 False로 설정했다. True 로 설정하면 기존에 설정된 로거들을 사용하지 않는다. 파이보도 False 로 설정할 것이다.

filters 는 특정 조건에서 로그를 출력하거나 출력하지 않기 위해서 아용된다. require_debug_false 필터는 DEBUG=False 인지 판단하는 필터이고 require_debug_ture 필터는 디버그가 True 인지 판단하는 필터이다.

formatters 는 로그를 출력할 형식을 정한다. 포맷터에 사용된 항목은 server_time(서버의 시간), message(출력 내용) 이다.

handlers 는 로그의 출력방법을 정의한다. console은 콘솔에 로그를 출력한다. 로그레벨이 INFO 이상이고 디버그가True 일때만 로그를 출력한다.

django.server 는 python manage.py runserver 로 작동하는 개발 서버에서만 사용하는 핸들러로 콘솔에 로그를 출력한다. mail_admins 는 로그내용을 이메일로 전송하는 핸들러로 로그레벨이 ERROR 이상이고 DEBUG=False 일때만 로그를 전송한다. 이 핸들러를 사용하려면 환경설정파일에 ADMINS 항목을추가하고 관리자 이메일을 추가해줘야한다. 그리고 이메일발송을 위한 SMTP 설정도 해줘야한다.

loggers 항목은 로그를 출력하는 프로그램에서 사용하는 로거의 이름을 의미한다. django 는 장고 프레임워크가 사용하는 로거이고 로그 레벨이 INFO이상일 경우에만 로그를 출력한다. django.server 는 개발서버가 사용하는 로거로 로그레벨이 INFO 이상일 경우에만 로그를 출력한다. 'propagate' : False 의 의미는 django.server 가 출력하는 로그를 장고 로거로 전달하지 않는다는 의미이다. True 로 최상위 패키지명이 django 로 동일하기 때문에 django.server 하위 패키지에서 출력하는 로그가 django.server 로거에도 출력되고 django 로거에도 출력되어 이중출력 현상이 발생한다.

로그레벨은 5단계로 구성된다. logging.debug, logging.info, logging.warning, logging.error, logging.critical 함수로 출력된다.

1단계 DEBUG : 디버깅 목적으로 사용된다.

2단계 INFO : 일반 정보를 출력할 목적으로 사용된다.

3단계 WARNING : 경고 정보를 출력할 목적으로 사용된다. 주로 작은문제를 출력한다.

4단계 ERROR : 오류 정보를 출력할 목적으로 사용된다. 주로 큰 문제를 출력한다.

5단계 CRITICAL : 아주 심각한 문제를 출력할 목적으로 사용된다.

로그는 설정한 레벨 이상의 로그만 출력된다. 예를들어 핸들러나 로거의 레벨을 INFO로 설정하면 DEBUG로그는 출력되지 않고, INFO 이상의 로그 INFO, WARNING, ERROR, CRITICAL 로그들만 출력된다.

 

이 파일들을 적용하기위해 먼저 projects\mysite\config\settings\base.py 에 위에 적힌 DEFAULT_LOGGING 을 복사하자.

 

복사를 그대로 하는데 이름만 DEFAULT_LOGGING 에서 LOGGING 으로 변경해주자.

그리고 포맷터 standard 를 추가하자.

standard 포맷터에 사용한 항목들은 asctime(현재시간), levelname(로그의 레벨,단계), name(로거명), message(출력 내용) 이다.

 

handlers 에 file 핸들러도 추가해주자.

file 핸들러에 사용한 항목은 

level : 출력 레벨로 INFO를 사용

filters : DEBUG=False 인 운영환경에서 사용

class : 파일 핸들러로 RotatingFileHandler 사용. RotatingFileHandler 는 파일 크기가 설정한 크기보다 커지면 파일 뒤에 인덱스를 붙여서 백업한다. 이 핸들러의 장점은 로그가 무한히 증가해도 일정 개수의 파일로 Rolling 되기 때문에 로그 파일이 너무 켜저 디스크가 꽉 차는 위험을 방지한다.

filename : 로그 파일명은 logs 디렉토리에 mysite.log 로 설정

maxBytes : 로그 파일의 최대 크기는 5MB

backupCount : 롤릴되는 파일의 개수는 총 5개로 설정

formatter : 포맷터는 standard를 사용.

 

마지막으로 django 로거의 handlers 에 file 핸들러를 추가하자.

 

설정을 다 완료한 후 git으로 서버에 적용하자. 서버에 적용한 후 서버에 logs 디렉토리를 만들어 주자.

개발환경에서도 projects\mysite\logs 디렉토리를 만들어주자. 그리고 logs 디렉토리는 버전 관리 대상이 아니므로 .gitignore 파일에 logs 디렉토리를 추가하자.

잘 적용되었나 테스트를 해보기 위해 

projects\mysite\pybo\views\base_views.py 파일에 다음과 같이 강제로 오류를 발생시켜보자.

index 함수가 호출되면 3을 0으로 나누려고 하기 때문에 ZeroDivisonError 가 발생한다. 깃을 이용해 서버에 적용하자. 설정한 후 서버에서 파이보 메인 페이지에 접속해보자. 'Server Error (500)' 오류가 발생한다. 이제 로그를 확인해보자.

어떤 오류가 발생했는지 로그파일에 출력된다. 앞으로는 tail -f mysite.log 로 로그를 확인하자. 이 명령을 하면 mysite.log 파일에 로그가 깧일 때마다 로그의 내용이 자동으로 출력된다.

 

지금까지 설정한 로깅은 장고가 사용하는 django 와 django.server 라는 로거로만 사용했다. 이번엔 새로운 로거를 생성해 파이보 프로그램에서 로그를 출력해보자.

먼저 projects\mysite\pybbo\views\base_views.py 를 수정하자.

적어 뒀었던 3/0 강제오류 코드를 지우고 사진과 같이 수정하자. 로그 파일에 로그를 출력하기 위해서는 logging 모듈이 필요하다. logger = logging.getLogger('로거명') 으로 얻은 logger 객체를 이용해 logger.debug, logger.error, logger.warning 등의 함수를 이용해ㅑ 로그를 출력할 수 있다. 이렇게 설정해도 'INFO 레벨로 출력' 이라는 문장은 로그로 출력되지 않는다. 그 이유는 위 코드에서 사용한 pybo 라는 로거는 LOGGING 설정에 등록되지 않은 상태이기 때문이다.

이를 등록하기 위해 projects\mysite\config\settings\base.py 를 다음과 같이 수정하자.

console 과 file 핸들러를 사용하는 pybo 로거를 등로했다.

이제 서버에 변경내용을 적용하고 파이보 메인페이지에 접속후 로그를 확인해보자.

잘 작동한다.

'Django > 따라하는 장고' 카테고리의 다른 글

42. 마무리  (0) 2022.12.14
40. DEBUG(디버그)  (0) 2022.12.13
39. 서버관리자  (0) 2022.12.12
38. Nginx(엔진엑스)  (0) 2022.12.12
37. Gunicorn(구니콘)  (0) 2022.12.09