동작하는 최소 코드 수준의 v2 스캐폴딩: - docker-compose.yml: postgres, fastapi, kordoc, frontend, caddy - app/: FastAPI 백엔드 (main, core, models, ai, prompts) - services/kordoc/: Node.js 문서 파싱 마이크로서비스 - gpu-server/: AI Gateway + GPU docker-compose - frontend/: SvelteKit 기본 구조 - migrations/: PostgreSQL 초기 스키마 (documents, tasks, processing_queue) - tests/: pytest conftest 기본 설정 - config.yaml, Caddyfile, credentials.env.example 갱신 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
47 lines
1.3 KiB
Python
47 lines
1.3 KiB
Python
"""공통 유틸리티 — v1 pkm_utils.py에서 AppleScript 제거, 나머지 포팅"""
|
|
|
|
import hashlib
|
|
import logging
|
|
from pathlib import Path
|
|
|
|
|
|
def setup_logger(name: str, log_dir: str = "logs") -> logging.Logger:
|
|
"""로거 설정"""
|
|
Path(log_dir).mkdir(exist_ok=True)
|
|
logger = logging.getLogger(name)
|
|
logger.setLevel(logging.INFO)
|
|
|
|
if not logger.handlers:
|
|
# 파일 핸들러
|
|
fh = logging.FileHandler(f"{log_dir}/{name}.log", encoding="utf-8")
|
|
fh.setFormatter(logging.Formatter(
|
|
"%(asctime)s [%(levelname)s] %(message)s",
|
|
datefmt="%Y-%m-%d %H:%M:%S"
|
|
))
|
|
logger.addHandler(fh)
|
|
|
|
# 콘솔 핸들러
|
|
ch = logging.StreamHandler()
|
|
ch.setFormatter(logging.Formatter("[%(levelname)s] %(message)s"))
|
|
logger.addHandler(ch)
|
|
|
|
return logger
|
|
|
|
|
|
def file_hash(path: str | Path) -> str:
|
|
"""파일 SHA-256 해시 계산"""
|
|
sha256 = hashlib.sha256()
|
|
with open(path, "rb") as f:
|
|
for chunk in iter(lambda: f.read(8192), b""):
|
|
sha256.update(chunk)
|
|
return sha256.hexdigest()
|
|
|
|
|
|
def count_log_errors(log_path: str) -> int:
|
|
"""로그 파일에서 ERROR 건수 카운트"""
|
|
try:
|
|
with open(log_path, encoding="utf-8") as f:
|
|
return sum(1 for line in f if "[ERROR]" in line)
|
|
except FileNotFoundError:
|
|
return 0
|