Spaces:
Running
Running
File size: 1,944 Bytes
385ef79 | 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 | """
request_context.py - Request-scoped tracking for predictions.
Tracks a single prediction request: timing, data sources, merges, validation.
Used to diagnose why predictions succeed or timeout.
"""
import uuid
import time
import logging
from datetime import datetime
logger = logging.getLogger(__name__)
class RequestContext:
"""Tracks a single prediction request: timing, data sources, merges."""
def __init__(self, ticker: str = ""):
self.request_id = str(uuid.uuid4())[:8]
self.ticker = ticker
self.start_time = time.time()
self.merge_log = []
self.validation_log = []
def elapsed(self) -> float:
"""Seconds elapsed since request start."""
return time.time() - self.start_time
def log_data_merge(self, source: str, data_rows: int, live_price: float):
"""Log a data merge (cached OHLCV + live price)."""
self.merge_log.append({
"source": source,
"rows": data_rows,
"live_price": live_price,
"timestamp": time.time()
})
logger.info(f"[{self.request_id}] Merged {data_rows} cached rows with live price ₹{live_price:.2f}")
def log_validation(self, cached_ticker: str, expected_ticker: str, is_match: bool):
"""Log ticker validation before merge."""
self.validation_log.append({
"cached": cached_ticker,
"expected": expected_ticker,
"match": is_match
})
status = "✓" if is_match else "✗"
logger.info(f"[{self.request_id}] {status} Data validation: {cached_ticker} vs {expected_ticker}")
def get_merge_report(self) -> dict:
"""Return merge details for API response."""
return {
"request_id": self.request_id,
"merges": len(self.merge_log),
"validations": self.validation_log,
"elapsed_ms": int(self.elapsed() * 1000),
}
|