umyunsang's picture
Upload folder using huggingface_hub
d2585c1 verified
"""결과 리포트 생성 — JSON + 터미널 요약."""
from __future__ import annotations
import json
import time
from datetime import datetime, timezone
from typing import Any, Dict, List, Optional
from .config import BASE_URL, VALID_TOOLS
from .flow_tracker import LatencyAggregator
from .http_client import get_http_backend
from .logger import E2ELogger
def write_json_report(
results: List[dict],
output_path: str,
run_id: str,
cold_start_wait: float = 0.0,
observed_tools: Optional[set] = None,
latency_aggregator: Optional[LatencyAggregator] = None,
) -> None:
"""JSON 결과 파일을 출력한다."""
_observed = observed_tools or set()
passed = sum(1 for r in results if r.get("status") == "passed")
failed = sum(1 for r in results if r.get("status") == "failed")
skipped = sum(1 for r in results if r.get("status") == "skipped")
tool_ratio = len(_observed) / len(VALID_TOOLS) if VALID_TOOLS else 0
output: Dict[str, Any] = {
"meta": {
"run_id": run_id,
"timestamp_utc": datetime.now(timezone.utc).isoformat(),
"target_url": BASE_URL,
"cold_start_wait_seconds": cold_start_wait,
"http_backend": get_http_backend(),
},
"summary": {
"total": len(results),
"passed": passed,
"failed": failed,
"skipped": skipped,
"tool_coverage": {
"observed": sorted(_observed),
"ratio": round(tool_ratio, 2),
},
},
"scenarios": results,
}
if latency_aggregator:
output["latency_stats"] = latency_aggregator.all_stats()
with open(output_path, "w", encoding="utf-8") as f:
json.dump(output, f, ensure_ascii=False, indent=2)
def print_summary(results: List[dict], logger: E2ELogger, observed_tools: set) -> None:
"""터미널에 결과 요약을 출력한다."""
passed = sum(1 for r in results if r.get("status") == "passed")
failed = sum(1 for r in results if r.get("status") == "failed")
skipped = sum(1 for r in results if r.get("status") == "skipped")
total = len(results)
logger.info("=" * 60)
logger.info(f"결과: {passed}/{total} 통과, {failed} 실패, {skipped} 스킵")
tool_ratio = len(observed_tools) / len(VALID_TOOLS) if VALID_TOOLS else 0
logger.info(f"도구 커버리지: {len(observed_tools)}/{len(VALID_TOOLS)} ({tool_ratio:.0%})")
if observed_tools:
logger.info(f" 관측된 도구: {sorted(observed_tools)}")