Files
connectai/core_py/monitoring.py
T

57 lines
2.0 KiB
Python

import time
import functools
import statistics
from typing import List, Callable, Any
class PerformanceMonitor:
"""
모니터링 및 SLO 측정 엔진 (Phase 3: Monitoring Integration)
모든 병목 지점에 타이밍 래퍼를 삽입하여 실시간 가시성 확보.
"""
def __init__(self):
self.latencies: List[float] = []
self.slo_threshold_ms = 200.0 # P95 목표: 200ms 이하
def track_latency(self, func: Callable):
"""메서드 실행 시간을 측정하는 데코레이터"""
@functools.wraps(func)
async def wrapper(*args, **kwargs):
start_time = time.perf_counter()
result = await func(*args, **kwargs) if asyncio.iscoroutinefunction(func) else func(*args, **kwargs)
latency = (time.perf_counter() - start_time) * 1000
self.latencies.append(latency)
if latency > self.slo_threshold_ms:
print(f"[SLO Alert] {func.__name__} violated SLO! Latency: {latency:.2f}ms (Goal: {self.slo_threshold_ms}ms)")
return result
return wrapper
def get_stats(self) -> dict:
"""현재까지의 지연 시간 통계 산출 (P95 포함)"""
if not self.latencies:
return {"count": 0}
stats = {
"count": len(self.latencies),
"avg_ms": statistics.mean(self.latencies),
"max_ms": max(self.latencies),
"p95_ms": statistics.quantiles(self.latencies, n=20)[18] if len(self.latencies) >= 20 else "N/A"
}
return stats
def report(self):
"""정기 성능 보고서 출력"""
stats = self.get_stats()
print("\n" + "="*40)
print("📊 [SYSTEM PERFORMANCE REPORT]")
print(f"Total Requests: {stats['count']}")
print(f"Average Latency: {stats.get('avg_ms', 0):.2f}ms")
print(f"P95 Latency: {stats['p95_ms']}")
print("="*40 + "\n")
monitor = PerformanceMonitor()
import asyncio # for decorator awareness