MukeshKapoor25 commited on
Commit
102d950
·
1 Parent(s): 31bb69e

feat(performance): add db operation monitoring to payment and appointment repos

Browse files

Introduce 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"""