anoderb
feat: integrate machine learning forecasting pipeline and unify settings & dashboard under Sikomo theme
2860429
Raw
History Blame Contribute Delete
2.9 kB
# logger.py — In-memory log handler for scraper and forecast log separation
import logging
from datetime import datetime
from typing import List, Dict, Optional
class MemoryLogHandler(logging.Handler):
"""Stores log entries in memory for API log streaming."""
def __init__(self, capacity: int = 500):
super().__init__()
self.capacity = capacity
self.logs: List[Dict] = []
def emit(self, record):
try:
msg = record.getMessage()
log_entry = {
"timestamp": datetime.fromtimestamp(record.created).isoformat(),
"level": record.levelname,
"source": record.name.split('.')[-1],
"message": msg
}
self.logs.append(log_entry)
if len(self.logs) > self.capacity:
self.logs.pop(0)
except Exception:
self.handleError(record)
def get_logs(self, limit: int = 100, level: Optional[str] = None) -> List[Dict]:
filtered = self.logs
if level and level.upper() != "ALL":
filtered = [l for l in filtered if l["level"] == level.upper()]
return filtered[-limit:]
def clear_logs(self):
self.logs.clear()
# Separated handlers
scraper_memory_handler = MemoryLogHandler(capacity=500)
forecast_memory_handler = MemoryLogHandler(capacity=500)
def get_app_logger(name: str) -> logging.Logger:
"""Default app logger for scraping operations."""
logger = logging.getLogger(f"app.scraper.{name}")
logger.setLevel(logging.INFO)
# Add memory handler
if not any(h is scraper_memory_handler for h in logger.handlers):
logger.addHandler(scraper_memory_handler)
# Add console stream handler
if not any(isinstance(h, logging.StreamHandler) and not isinstance(h, MemoryLogHandler) for h in logger.handlers):
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s] scraper.%(name)s: %(message)s"))
logger.addHandler(console)
return logger
def get_forecast_logger(name: str) -> logging.Logger:
"""Dedicated app logger for forecasting operations."""
logger = logging.getLogger(f"app.forecast.{name}")
logger.setLevel(logging.INFO)
# Add memory handler
if not any(h is forecast_memory_handler for h in logger.handlers):
logger.addHandler(forecast_memory_handler)
# Add console stream handler
if not any(isinstance(h, logging.StreamHandler) and not isinstance(h, MemoryLogHandler) for h in logger.handlers):
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s] forecast.%(name)s: %(message)s"))
logger.addHandler(console)
return logger