Skip to content

Commit

Permalink
feat : 로깅 추가 및 셀러리 연결 오류 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
seokho-1116 committed Mar 23, 2024
1 parent 17f379d commit 86c0f60
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 34 deletions.
33 changes: 24 additions & 9 deletions backend/AnimatedDrawings/application/animation_queue.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import argparse
import json
import logging
import uuid
from _xxsubinterpreters import ChannelClosedError
from json.decoder import JSONDecodeError
Expand All @@ -10,17 +10,16 @@
from pika.spec import Basic, BasicProperties

from application.config.queue_config import QueueConfig
from application.logging.logger_factory import LoggerFactory
from application.model.motion import Motion
from application.model.retarget import Retarget
from application.task.make_animation import MakeAnimation
from application.task.save_capsule_skin import SaveCapsuleSkin
from application.task.send_notification import SendNotification

logger = logging.getLogger('animation_queue_controller')


class AnimationQueueController:
def __init__(self):
def __init__(self, output_file_path: str):
self.queue_config = QueueConfig()
self.require_keys = ['memberId', 'memberName', 'skinName', 'imageUrl',
'retarget', 'motionName']
Expand All @@ -30,9 +29,12 @@ def __init__(self):
self.make_animation_task = MakeAnimation()
self.save_capsule_skin_task = SaveCapsuleSkin()
self.send_notification_task = SendNotification()
self.logger = LoggerFactory.get_logger(__name__,
output_file_path=output_file_path)

def run(self):
# rabbitmq 채널 연결
self.logger.info('작업 큐 연결 시작')
connection = pika.BlockingConnection(
pika.ConnectionParameters(host=self.queue_config.queue_host))
channel = connection.channel()
Expand All @@ -42,13 +44,15 @@ def run(self):
channel.basic_consume(queue=self.queue_config.queue_name,
on_message_callback=self.callback,
auto_ack=False)
self.logger.info('작업 큐 연결 성공')

try:
channel.start_consuming()
except ChannelClosedError as e:
logger.info("커넥션 연결 오류")
self.logger.info("커넥션 연결 오류")
raise e
finally:
self.logger.info('큐 커넥션 종료')
channel.close()

def callback(
Expand All @@ -66,7 +70,6 @@ def callback(
:param header: 기본 정보
:param body: queue로부터 넘어온 데이터
"""
logger.info('큐 메시지 처리 시작 %s', header.message_id)
try:
json_object = self.parse_json(body)

Expand All @@ -90,7 +93,7 @@ def callback(

channel.basic_ack(delivery_tag=method.delivery_tag)
except Exception as e:
logger.exception('메시지 처리 오류', e)
self.logger.exception('작업 큐 메시지 처리 오류', exc_info=e)
channel.basic_reject(delivery_tag=method.delivery_tag,
requeue=False)

Expand All @@ -116,10 +119,22 @@ def parse_json(self, body: bytes):
return json_object

except (JSONDecodeError, KeyError, TypeError) as e:
logger.exception('json 파싱 오류', e)
self.logger.exception('작업 큐 메시지 json 파싱 오류', exc_info=e)
raise e


def parse_args() -> str:
parser = argparse.ArgumentParser()
parser.add_argument("-o", "--output", help="log file path")
args = parser.parse_args()

if args.output:
return args.output

return ''


if __name__ == '__main__':
application = AnimationQueueController()
output_log_path = parse_args()
application = AnimationQueueController(output_log_path)
application.run()
63 changes: 63 additions & 0 deletions backend/AnimatedDrawings/application/logging/logger_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import logging
import sys


class LoggerFactory:

@staticmethod
def get_logger(
name: str,
output_file_path: str = '/var/log/application.log',
level: int = logging.INFO,
format_string: str = '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
) -> logging.Logger:
"""
기본 로거를 생성해준다.
:param name: 로거의 이름
:param output_file_path: 로그를 기록할 파일의 경로
:param level: 로깅의 레벨
:param format_string: 로깅의 포맷팅
:return: 설정된 로거를 반환한다.
"""
if output_file_path is None or output_file_path == '':
output_file_path = '/var/log/application.log'

logger = logging.getLogger(name)
logger.setLevel(level)

LoggerFactory._setup_handler(format_string, level, logger,
output_file_path)

return logger

@staticmethod
def setup_logger(
logger: logging.Logger,
output_file_path: str = '/var/log/celeryd.log',
level: int = logging.WARNING,
format_string: str = '%(asctime)s - %(name)s - %(levelname)s'
) -> None:
"""
파라미터로 받은 로거에 포맷터를 설정한다.
:param logger: 설정할 로거
:param output_file_path: 로그를 기록할 파일의 경로
:param level: 로깅의 레벨
:param format_string: 로깅의 포맷팅
"""
LoggerFactory._setup_handler(format_string, level, logger,
output_file_path)

@staticmethod
def _setup_handler(format_string, level, logger, output_file_path):
formatter = logging.Formatter(format_string)

stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setLevel(level)
stream_handler.setFormatter(formatter)

file_handler = logging.FileHandler(filename=output_file_path)
file_handler.setLevel(level)
file_handler.setFormatter(formatter)

logger.addHandler(file_handler)
logger.addHandler(stream_handler)
32 changes: 19 additions & 13 deletions backend/AnimatedDrawings/application/task/base_task.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import logging

import celery.signals
import requests
from celery import Task
from celery.utils.log import get_task_logger

from application.model.notification_status import \
NotificationStatus

logger = logging.getLogger('error_task')
from application.logging.logger_factory import LoggerFactory
from application.model.notification_status import NotificationStatus


class LogErrorsTask(Task):
Expand All @@ -17,8 +15,15 @@ class LogErrorsTask(Task):
retry_jitter = False
notification_server_url = 'https://notification.archive-timecapsule.kro.kr/api/notification/capsule_skin/send'

def __init__(self):
self.task_logger = get_task_logger(__name__)

@celery.signals.after_setup_task_logger.connect
def on_after_setup_logger(logger, **kwargs):
LoggerFactory.setup_logger(logger)

def on_failure(self, exc, task_id, args, kwargs, einfo):
logger.error('태스크 처리 실패 %s', task_id)
self.task_logger.exception('태스크 처리 실패 %s', task_id, exc_info=einfo)
request_data = {
'memberId': kwargs['input_data']['memberId'],
'skinName': kwargs['input_data']['skinName'],
Expand All @@ -30,18 +35,19 @@ def on_failure(self, exc, task_id, args, kwargs, einfo):

try:
r = requests.post(self.notification_server_url,
json=request_data,
verify=False,
timeout=5)
json=request_data,
verify=False,
timeout=5)
r.raise_for_status()
except requests.exceptions.HTTPError as ex:
logger.error('알림 서버 동작 오류 request: %s, response: %s', ex.request, ex.response)
self.task_logger.exception('알림 서버 동작 오류 %s', task_id,
exc_info=ex)

super(LogErrorsTask, self).on_failure(exc, task_id, args, kwargs, einfo)

def on_retry(self, exc, task_id, args, kwargs, einfo):
logger.error('태스크 재시도 %s', task_id)
self.task_logger.exception('태스크 재시도 %s', task_id, exc_info=einfo)
super(LogErrorsTask, self).on_retry(exc, task_id, args, kwargs, einfo)

def on_success(self, retval, task_id, args, kwargs):
logger.info('태스크 처리 성공 %s', task_id)
self.task_logger.info('태스크 처리 성공 %s', task_id)
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class MakeAnimation(LogErrorsTask):
name = 'make_animation'

def __init__(self):
super().__init__()
self.s3_bucket_name = S3Config().s3_bucket_name

def run(self, *args, **kwargs):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
from sqlalchemy.orm import Session

from application.config.database_config import DatabaseConfig
from application.task.base_task import LogErrorsTask
from application.model.capsule_skin import CapsuleSkin
from application.model.motion import Motion
from application.model.retarget import Retarget
from application.task.base_task import LogErrorsTask


class SaveCapsuleSkin(LogErrorsTask):
Expand Down
21 changes: 13 additions & 8 deletions backend/AnimatedDrawings/application/task/send_notification.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import logging

import requests
import celery.signals
from celery.utils.log import get_task_logger

from application.model.notification_status import \
NotificationStatus
from application.logging.logger_factory import LoggerFactory
from application.model.notification_status import NotificationStatus
from application.task.base_task import LogErrorsTask

logger = logging.getLogger('send_notification')


class SendNotification(LogErrorsTask):
name = 'send_notification'

def __init__(self):
super().__init__()
self.task_logger = get_task_logger(__name__)

@celery.signals.after_setup_task_logger.connect
def on_after_setup_logger(logger, **kwargs):
LoggerFactory.setup_logger(logger)

def run(self, *args, **kwargs):
request_data = {
'memberId': kwargs['input_data']['memberId'],
Expand All @@ -21,12 +27,11 @@ def run(self, *args, **kwargs):
'skinUrl': kwargs['filename'],
'status': NotificationStatus.SUCCESS.value
}

try:
r = requests.post(self.notification_server_url,
json=request_data,
verify=False,
timeout=5)
r.raise_for_status()
except requests.exceptions.HTTPError as ex:
logger.error('알림 서버 동작 오류 request: %s, response: %s', ex.request, ex.response)
self.task_logger.exception('알림 서버 동작 오류', exc_info=ex)
10 changes: 7 additions & 3 deletions backend/AnimatedDrawings/supervisord.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[supervisord]
nodaemon=true
loglevel=info

[inet_http_server]
port = *:9001
Expand All @@ -8,23 +9,26 @@ password = 1234

[program:flower]
directory = /app/application
command = /opt/conda/bin/conda run -n animated_drawings celery -A celery_app flower --conf="/app/application/config/flowerconfig.py"
command = /opt/conda/envs/animated_drawings/bin/celery -A celery_app flower --conf="/app/application/config/flowerconfig.py"
priority = 100
loglevel=info
stdout_logfile = /var/log/flower.log
stderr_logfile = /var/log/flower.err

[program:application]
directory = /app/application
command = /opt/conda/bin/conda run -n animated_drawings python3 animation_queue.py
command = /opt/conda/envs/animated_drawings/bin/python3 -u animation_queue.py
loglevel=info
priority = 100
stdout_logfile = /var/log/application.log
stderr_logfile = /var/log/application.err
environment=ENVIRONMENT=%(ENV_ENVIRONMENT)s,PYOPENGL_PLATFORM="osmesa"

[program:celery]
directory = /app/application
command = /opt/conda/bin/conda run -n animated_drawings celery -A celery_app worker
command = /opt/conda/envs/animated_drawings/bin/celery -A celery_app worker
priority = 200
loglevel=info
stdout_logfile = /var/log/celeryd.log
stderr_logfile = /var/log/celeryd.err
environment=ENVIRONMENT=%(ENV_ENVIRONMENT)s,PYOPENGL_PLATFORM="osmesa"
Expand Down

0 comments on commit 86c0f60

Please sign in to comment.