-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmonitoring.py
More file actions
102 lines (89 loc) · 3.13 KB
/
Copy pathmonitoring.py
File metadata and controls
102 lines (89 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import logging
import json
import time
from datetime import datetime, timezone
class JSONFormatter(logging.Formatter):
def format(self, record):
log_obj = {
"timestamp": datetime.now(timezone.utc).isoformat(),
"level": record.levelname,
"message": record.getMessage(),
"module": record.module,
"function": record.funcName,
}
if hasattr(record, "extra_data"):
log_obj.update(record.extra_data)
return json.dumps(log_obj)
def get_logger(name: str = "production-api") -> logging.Logger:
logger = logging.getLogger(name)
if not logger.handlers:
handler = logging.StreamHandler()
handler.setFormatter(JSONFormatter())
logger.addHandler(handler)
logger.setLevel(logging.INFO)
return logger
class RequestTimer:
def __enter__(self):
self._started_at = time.perf_counter()
self.elapsed_ms = 0.0
return self
def __exit__(self, exc_type, exc_value, traceback):
self.elapsed_ms = (time.perf_counter() - self._started_at) * 1000
class MetricsCollector:
def __init__(self):
self.metrics = {
"requests_total": 0,
"errors_total": 0,
"latency_sum": 0.0,
"latency_count": 0,
"tokens_input": 0,
"tokens_output": 0,
"cache_hits": 0,
"cache_misses": 0,
}
def record_request(
self,
latency_ms: float,
input_tokens: int = 0,
output_tokens: int = 0,
error: bool = False,
cache_hit: bool = False,
):
self.metrics["requests_total"] += 1
self.metrics["latency_sum"] += latency_ms
self.metrics["latency_count"] += 1
self.metrics["tokens_input"] += input_tokens
self.metrics["tokens_output"] += output_tokens
if error:
self.metrics["errors_total"] += 1
if cache_hit:
self.metrics["cache_hits"] += 1
else:
self.metrics["cache_misses"] += 1
def get_summary(self) -> dict:
avg_latency = (
self.metrics["latency_sum"] / self.metrics["latency_count"]
if self.metrics["latency_count"] > 0
else 0
)
error_rate = (
self.metrics["errors_total"] / self.metrics["requests_total"]
if self.metrics["requests_total"] > 0
else 0
)
cache_hit_rate = (
self.metrics["cache_hits"]
/ (self.metrics["cache_hits"] + self.metrics["cache_misses"])
if (self.metrics["cache_hits"] + self.metrics["cache_misses"]) > 0
else 0
)
return {
"total_requests": self.metrics["requests_total"],
"total_errors": self.metrics["errors_total"],
"error_rate": f"{error_rate:.2%}",
"average_response_time_ms": round(avg_latency, 2),
"model_usage": {},
"total_input_tokens": self.metrics["tokens_input"],
"total_output_tokens": self.metrics["tokens_output"],
"cache_hit_rate": round(cache_hit_rate * 100, 2),
}