IMG_Worker/modules/log_bridge.py

105 lines
3.7 KiB
Python

"""
ImageWorker와 메인 프로세스 간 로그 브리지
"""
import threading
import queue
import logging
import sys
import os
class LogBridge:
"""ImageWorker 프로세스의 로그를 메인 프로세스로 전달하는 브리지"""
def __init__(self, main_logger, log_queue):
self.main_logger = main_logger
self.log_queue = log_queue
self.reader_thread = None
self.running = False
def start(self):
"""로그 리더 스레드 시작"""
if self.running:
return
self.running = True
self.reader_thread = threading.Thread(target=self._log_reader, daemon=True)
self.reader_thread.start()
def stop(self):
"""로그 리더 스레드 중지"""
self.running = False
try:
self.log_queue.put(None) # 종료 신호
except Exception:
pass
def _log_reader(self):
"""로그 큐에서 메시지를 읽어 메인 로거로 전달"""
while self.running:
try:
log_record = self.log_queue.get(timeout=1)
if log_record is None: # 종료 신호
break
# 메인 로거로 전달
process_name = log_record.get('process_name', 'ImageWorker')
level = log_record.get('level', logging.INFO)
message = log_record.get('message', '')
exc_info = log_record.get('exc_info', False)
# 로그 브릿지를 통해 넘어오는 모든 메시지를 DEBUG 레벨로 처리
# 이렇게 하면 GUI에는 표시되지 않고 콘솔과 파일에만 기록됨
level = logging.DEBUG
# 메시지에 프로세스 이름 추가
formatted_message = f"[{process_name}] {message}"
# 메인 로거로 출력
if hasattr(self.main_logger, 'log'):
self.main_logger.log(formatted_message, level=level, exc_info=exc_info)
else:
self.main_logger.log(level, formatted_message, exc_info=exc_info)
except queue.Empty:
continue
except Exception as e:
# 로그 처리 중 오류 발생 시 stderr로 출력
print(f"LogBridge 오류: {e}", file=sys.stderr)
class ImageWorkerLogger:
"""ImageWorker에서 사용할 로거 (큐를 통해 메인 프로세스로 전송)"""
def __init__(self, log_queue, process_name=None):
self.log_queue = log_queue
self.process_name = process_name or f"ImageWorker-{os.getpid()}"
def log(self, message, level=logging.INFO, exc_info=False):
"""로그 메시지를 큐를 통해 메인 프로세스로 전송"""
try:
log_record = {
'process_name': self.process_name,
'level': level,
'message': str(message),
'exc_info': exc_info
}
self.log_queue.put(log_record)
except Exception:
# 큐 전송 실패 시 stderr로 출력
print(f"[{self.process_name}] {message}", file=sys.stderr)
def debug(self, msg, *args, **kwargs):
self.log(msg, logging.DEBUG)
def info(self, msg, *args, **kwargs):
self.log(msg, logging.INFO)
def warning(self, msg, *args, **kwargs):
self.log(msg, logging.WARNING)
def error(self, msg, *args, **kwargs):
exc_info = kwargs.get('exc_info', False)
self.log(msg, logging.ERROR, exc_info=exc_info)
def critical(self, msg, *args, **kwargs):
self.log(msg, logging.CRITICAL)