Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:18:51 +08:00
commit d80558b1cf
52 changed files with 12920 additions and 0 deletions

View File

@@ -0,0 +1,165 @@
"""
Python Logging Configuration
Blender addon용 로깅 시스템
"""
import logging
import os
from pathlib import Path
from datetime import datetime
# 로그 디렉토리 경로
def get_log_dir() -> Path:
"""로그 디렉토리 경로 가져오기"""
# CLAUDE_PROJECT_DIR 환경변수 또는 현재 작업 디렉토리 사용
project_dir = os.environ.get('CLAUDE_PROJECT_DIR', os.getcwd())
log_dir = Path(project_dir) / '.blender-toolkit' / 'logs'
# 디렉토리 생성
log_dir.mkdir(parents=True, exist_ok=True)
return log_dir
# 로그 포맷 정의
LOG_FORMAT = '[%(asctime)s] [%(levelname)-8s] [%(name)s] %(message)s'
DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
# 전역 로거 설정 완료 여부
_logger_initialized = False
def setup_logging(level: int = logging.INFO) -> None:
"""
전역 로깅 설정 초기화
Args:
level: 로그 레벨 (logging.DEBUG, INFO, WARNING, ERROR)
"""
global _logger_initialized
if _logger_initialized:
return
# 로그 디렉토리
log_dir = get_log_dir()
# 루트 로거 설정
root_logger = logging.getLogger('blender_toolkit')
root_logger.setLevel(level)
# 기존 핸들러 제거 (중복 방지)
root_logger.handlers.clear()
# 파일 핸들러 (모든 로그)
file_handler = logging.FileHandler(
log_dir / 'blender-addon.log',
mode='a',
encoding='utf-8'
)
file_handler.setLevel(level)
file_handler.setFormatter(logging.Formatter(LOG_FORMAT, DATE_FORMAT))
# 파일 핸들러 (에러만)
error_handler = logging.FileHandler(
log_dir / 'error.log',
mode='a',
encoding='utf-8'
)
error_handler.setLevel(logging.ERROR)
error_handler.setFormatter(logging.Formatter(LOG_FORMAT, DATE_FORMAT))
# 콘솔 핸들러 (개발 모드)
if os.environ.get('DEBUG'):
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
console_handler.setFormatter(
logging.Formatter('[%(levelname)-8s] %(message)s')
)
root_logger.addHandler(console_handler)
# 핸들러 추가
root_logger.addHandler(file_handler)
root_logger.addHandler(error_handler)
_logger_initialized = True
# 초기화 메시지
root_logger.info('=' * 70)
root_logger.info(f'Blender Toolkit Logger initialized')
root_logger.info(f'Log directory: {log_dir}')
root_logger.info(f'Log level: {logging.getLevelName(level)}')
root_logger.info('=' * 70)
def get_logger(name: str = None) -> logging.Logger:
"""
모듈별 로거 가져오기
Args:
name: 로거 이름 (보통 __name__ 사용)
Returns:
Logger 인스턴스
Example:
```python
from .utils.logger import get_logger
logger = get_logger(__name__)
logger.info("Hello, world!")
logger.error("An error occurred", exc_info=True)
```
"""
# 로깅 시스템이 초기화되지 않았으면 초기화
if not _logger_initialized:
# DEBUG 환경변수가 있으면 DEBUG 레벨 사용
level = logging.DEBUG if os.environ.get('DEBUG') else logging.INFO
setup_logging(level)
# 모듈별 로거 반환
logger_name = f'blender_toolkit.{name}' if name else 'blender_toolkit'
return logging.getLogger(logger_name)
# 편의 함수들
def log_function_call(logger: logging.Logger):
"""
함수 호출 로깅 데코레이터
Example:
```python
@log_function_call(logger)
def my_function(arg1, arg2):
return arg1 + arg2
```
"""
def decorator(func):
def wrapper(*args, **kwargs):
logger.debug(f'Calling {func.__name__}() with args={args}, kwargs={kwargs}')
try:
result = func(*args, **kwargs)
logger.debug(f'{func.__name__}() returned: {result}')
return result
except Exception as e:
logger.error(f'{func.__name__}() raised {type(e).__name__}: {e}', exc_info=True)
raise
return wrapper
return decorator
def log_error(logger: logging.Logger, error: Exception, context: str = None):
"""
에러 로깅 헬퍼
Args:
logger: Logger 인스턴스
error: Exception 객체
context: 에러 발생 컨텍스트 설명
"""
message = f'{type(error).__name__}: {error}'
if context:
message = f'{context} - {message}'
logger.error(message, exc_info=True)