gunicorn 을 활용하여 멀티프로세스를 이용하는 경우, 그리고 로깅 타입을 TimedRotatingFileHandler 을 이용하는 경우 여러 개의 프로세스가 한 파일에 접근하기 때문에 날짜가 바뀔 때마다 새 파일을 만들어야 하는데 이게 제대로 작동하지 않았다
그래서 메인 log 파일에 계속 누적하여 로그가 쌓이고 있었고, 얼마 지나지 않아 로그 사이즈가 너무 커져서 나중에는 읽기 조차 힘든 지경에 이르렀다. 여러 자료들을 살펴 보았을 때 멀티 프로세스를 쓴다면 곧바로 파일 로테이션 로깅을 사용하지 말고, 작업 큐에게 로그를 전달하여 작업 큐로부터 파일 로테이션을 돌리도록 해주면 된다고 하는데 그냥 가장 간단한 방법으로 처리하면 되지 않을까 하여 크론탭을 이용하게 됐다
크론탭은 정해진 시간, 날짜에 원하는 커맨드를 요청할 수 있게 도와주는 녀석인데, 이 녀석을 이용해서 매일 00시 00분에 새로운 로그를 생성하는 기능을 구현할 거다.
아래는 해당 부분에 대한 예시 코드이다.
import os
import datetime
old_name = "/path/to/log"
# 날짜가 바뀌었으므로 전날 기준으로 로그 파일 뒤에 postfix로 넣을 것임
# 예) log.2023-04-25
log_day = (datetime.datetime.now() - datetime.timedelta(days=1)).strftime("%Y-%m-%d")
new_name = ".".join([old_name, log_day])
# 기존 메인 로그 파일을 열어서 모든 데이터를 옮겨 주고 곧바로 메인 로그 파일을 비운다(truncate)
old = open(old_name, "r")
with open(new_name, "w") as new:
new.write(old.read()) # 기존 로그의 모든 내용을 새 로그 파일(log.2023-04-25) 에 넣어준다.
old.truncate(0) # 기존 로그를 빈 파일로 만들어준다.
old.close()
이 코드에서 굳이 os.rename 을 쓰지 않은 이유는, gunicorn 프로세스가 돌아가는 중간에 path/to/log 파일을 계속 참조하고 있는데, rename을 해 버리면 path/to/log 파일이 존재하지 않게 되어 서버 프로세스는 로그를 파일에 남길 수가 없다. 물론 max-requests 같은 인자에 의해 중간 중간 재시작되는 프로세스나 워커들은 꺼졌다 켜지기 때문에 파일이 없다면 새로 만들어서 로그를 남길 수 있으나, 모든 프로세스가 꺼졌다 켜지기 전 까지는 로그 누락이 있을 수밖에 없다.
따라서 기존 실행되고 있는 프로세스에 어떠한 영향도 주지 않기 위해서, 파일을 삭제하기 보다는 truncate 를 이용하는 편이 훨씬 안전한 처리가 가능하다. 물론 전체 서비스를 재시작하면 되지만 굳이 로깅을 위해 서비스를 내렸다 올리는 위험을 안을 필요는 없으므로, 위 방법이 현실적인 대안이 되지 않을까 생각한다.
'개발 이야기 > Python' 카테고리의 다른 글
Python 이중 for loop 를 itertools 를 활용하여 개선하기 (0) | 2024.02.26 |
---|---|
Multi Thread 결과 값 리턴하여 저장하기 (0) | 2021.07.22 |
베트남어 성조 제거하여 알파벳으로 변환하기 (0) | 2021.06.30 |
Fabric 을 이용하여 쉽고 편한 배포하기 (0) | 2020.12.10 |
Dictionary List 를 key에 따라 sort 하기 (0) | 2020.12.02 |
댓글