Spaces:
Sleeping
Sleeping
Commit ·
102d950
1
Parent(s): 31bb69e
feat(performance): add db operation monitoring to payment and appointment repos
Browse filesIntroduce async context manager to track query execution time and errors
Mark slow operations and log performance metrics for database queries
app/repositories/appointment.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
from typing import Tuple, Optional, List, Dict, Union
|
| 2 |
from app.models.appointment import appointment_table, Appointment
|
| 3 |
from app.core.sql_config import database
|
|
|
|
| 4 |
from app.utils.database import (
|
| 5 |
serialize_appointment,
|
| 6 |
validate_query_result,
|
|
|
|
| 1 |
from typing import Tuple, Optional, List, Dict, Union
|
| 2 |
from app.models.appointment import appointment_table, Appointment
|
| 3 |
from app.core.sql_config import database
|
| 4 |
+
from app.utils.performance_metrics import monitor_db_operation
|
| 5 |
from app.utils.database import (
|
| 6 |
serialize_appointment,
|
| 7 |
validate_query_result,
|
app/repositories/payment.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
from app.core.sql_config import database
|
|
|
|
| 2 |
from fastapi import HTTPException
|
| 3 |
import logging
|
| 4 |
|
|
|
|
| 1 |
from app.core.sql_config import database
|
| 2 |
+
from app.utils.performance_metrics import monitor_db_operation
|
| 3 |
from fastapi import HTTPException
|
| 4 |
import logging
|
| 5 |
|
app/utils/performance_metrics.py
CHANGED
|
@@ -8,6 +8,7 @@ import json
|
|
| 8 |
import logging
|
| 9 |
from enum import Enum
|
| 10 |
import statistics
|
|
|
|
| 11 |
|
| 12 |
# Configure metrics logger
|
| 13 |
metrics_logger = logging.getLogger("performance_metrics")
|
|
@@ -175,6 +176,34 @@ class PerformanceMetricsCollector:
|
|
| 175 |
"""Record transaction execution time"""
|
| 176 |
labels = {"transaction_type": transaction_type}
|
| 177 |
self.record_metric(MetricType.TRANSACTION_TIME, transaction_time, labels)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
|
| 179 |
def get_metric_summary(self,
|
| 180 |
metric_type: MetricType,
|
|
@@ -376,6 +405,12 @@ def record_transaction_time(transaction_time: float, transaction_type: str = "de
|
|
| 376 |
"""Record transaction time metrics"""
|
| 377 |
metrics_collector.record_transaction_time(transaction_time, transaction_type)
|
| 378 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 379 |
|
| 380 |
def get_performance_summary(time_window_minutes: int = 60) -> Dict[str, Any]:
|
| 381 |
"""Get performance summary"""
|
|
|
|
| 8 |
import logging
|
| 9 |
from enum import Enum
|
| 10 |
import statistics
|
| 11 |
+
from contextlib import asynccontextmanager
|
| 12 |
|
| 13 |
# Configure metrics logger
|
| 14 |
metrics_logger = logging.getLogger("performance_metrics")
|
|
|
|
| 176 |
"""Record transaction execution time"""
|
| 177 |
labels = {"transaction_type": transaction_type}
|
| 178 |
self.record_metric(MetricType.TRANSACTION_TIME, transaction_time, labels)
|
| 179 |
+
|
| 180 |
+
@asynccontextmanager
|
| 181 |
+
async def monitor_db_operation(self, query_type: str, table_name: str = "unknown"):
|
| 182 |
+
"""Async context manager to monitor a DB operation.
|
| 183 |
+
|
| 184 |
+
Records execution time and errors, marking slow operations.
|
| 185 |
+
|
| 186 |
+
Args:
|
| 187 |
+
query_type: e.g., "SELECT", "INSERT", "UPDATE", "DELETE".
|
| 188 |
+
table_name: table/collection name for labeling.
|
| 189 |
+
"""
|
| 190 |
+
start = time.perf_counter()
|
| 191 |
+
try:
|
| 192 |
+
yield
|
| 193 |
+
except Exception as e:
|
| 194 |
+
# Record error with query type and table name
|
| 195 |
+
self.record_query_error(query_type=query_type, error_type=type(e).__name__)
|
| 196 |
+
metrics_logger.error(f"DB {query_type} error on {table_name}: {e}")
|
| 197 |
+
raise
|
| 198 |
+
finally:
|
| 199 |
+
duration = time.perf_counter() - start
|
| 200 |
+
# Mark as slow if > 1s (tunable threshold)
|
| 201 |
+
is_slow = duration > 1.0
|
| 202 |
+
self.record_query_execution(execution_time=duration, query_type=query_type, is_slow=is_slow)
|
| 203 |
+
metrics_logger.info(
|
| 204 |
+
f"DB {query_type} on {table_name} took {duration:.3f}s" +
|
| 205 |
+
(" (slow)" if is_slow else "")
|
| 206 |
+
)
|
| 207 |
|
| 208 |
def get_metric_summary(self,
|
| 209 |
metric_type: MetricType,
|
|
|
|
| 405 |
"""Record transaction time metrics"""
|
| 406 |
metrics_collector.record_transaction_time(transaction_time, transaction_type)
|
| 407 |
|
| 408 |
+
@asynccontextmanager
|
| 409 |
+
async def monitor_db_operation(query_type: str, table_name: str = "unknown"):
|
| 410 |
+
"""Convenience async context manager that delegates to the global collector."""
|
| 411 |
+
async with metrics_collector.monitor_db_operation(query_type=query_type, table_name=table_name):
|
| 412 |
+
yield
|
| 413 |
+
|
| 414 |
|
| 415 |
def get_performance_summary(time_window_minutes: int = 60) -> Dict[str, Any]:
|
| 416 |
"""Get performance summary"""
|