November 25, 2020
CloudWatch는 AWS에서 제공하는 모니터링 및 관찰 서비스이다. CloudWatch를 사용하여 서버의 비정상적인 동작을 감지하고 경보를 설정하고 로그와 지표를 시각화하고 자동화된 작업을 수행하고 문제를 해결하고 인사이트를 발견하여 애플리케이션을 원활하게 관리할 수 있다. 여기에서는 Django 웹 애플리케이션 로깅을 AWS CloudWatch에 연결하는 방법을 설명한다.
watchtower는 AWS CloudWatch Logs를 위한 오픈소스 로그 핸들러 이며 AWS로 쉽게 로그를 보낼 수 있게 도와주며 다음과 같이 패키지를 설치 한다.
pip install watchtower
pip install boto3django의 settings.py에 다음과 같이 code를 작성한다.
import logging
from boto3.session import Session
AWS_ACCESS_KEY_ID = 'aws access key'
AWS_SECRET_ACCESS_KEY = 'aws secret access key'
AWS_REGION_NAME = '리전 이름 ex) 서울 : ap-northeast-2'
AWS_LOG_GROUP = '로그그룹 이름',
AWS_LOG_STREAM = '로그스트림 이름',
AWS_LOGGER_NAME = 'my-logger' # logger를 지정해준다
# logger
boto3_session = Session(
aws_access_key_id=AWS_ACCESS_KEY_ID,
aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
region_name=AWS_REGION_NAME
)
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'aws': {
# 여기에서 AWS에 대한 특정 포맷을 추가할 수 있다.
# 포맷을 변경하려면 다음을 참고 한다.
# https://stackoverflow.com/questions/533048/how-to-log-source-file-name-and-line-number-in-python/44401529
'format': u"%(asctime)s [%(levelname)-8s] %(message)s [%(pathname)s:%(lineno)d]",
'datefmt': "%Y-%m-%d %H:%M:%S"
},
},
'handlers': {
'watchtower': {
'level': 'DEBUG',
'class': 'watchtower.CloudWatchLogHandler',
'boto3_session': boto3_session,
'log_group': AWS_LOG_GROUP,
'stream_name': AWS_LOG_STREAM,
'formatter': 'aws', # 앞에서 생성한 format
},
},
'loggers': {
AWS_LOGGER_NAME: {
'level': 'DEBUG',
'handlers': ['watchtower'],
'propagate': False,
},
# 다른 로거들을 이 다음에 추가할 수 있다.
},
}여기서는 AWS_ACCESS_KEY_ID와 AWS_SECRET_ACCESS_KEY를 통해 자격증명을 받았지만 IAM계정에 CloudWatchLogs관련 권한을 설정하고 이를 boto3가 인스턴스 메타데이터에서 자격 증명을 수집하도록 요청할 수 도 있다. 한편 AWS_ACCESS_KEY_ID와 AWS_SECRET_ACCESS_KEY는 IAM계정 생성시 발급된다.

로그 그룹은 CloudWatch → 로그 그룹에서 생성가능하며 이때 생성한 이름을 settings.py의 AWS_LOG_GROUP에 추가해준다.

로그 스트림은 CloudWatch → 생성한 로그 그룹 → 로그 스트림 생성에서 만들 수 있으며 이때 지정한 이름을 settings.py의 AWS_LOG_STREAM에 추가해준다.
또는 만약 로그 스트림을 생성하지 않은 상태라면 settings.py의 AWS_LOG_STREAM에서 지정된 이름으로 자동으로 로그 스트림이 생성된다.
import logging
logger = logging.getLogger('my-logger')
def add (a, b):
try:
return int(a) + int(b)
except:
logger.error('test!') # CloudWatch로 전송되는 로그위와 같이 테스트 코드를 작성하였으면 함수의 파라미터로 1과 int가 아닌test를 전달하여 고의로 에러를 발생 시켜 보자.

이제 CloudWatch에서 생성한 (또는 생성된) 로그스트림에서 앞서 작성한 테스트 코드의 에러 로그를 확인 할 수 있다.