Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/hesabixAPI/app/services/monitoring_background_jobs.py
2026-04-14 19:34:55 +03:30

125 lines
4.4 KiB
Python
Executable file

"""
Background jobs برای سیستم مانیتورینگ
"""
from __future__ import annotations
import asyncio
import logging
from datetime import datetime
from adapters.db.session import get_db_session
from app.services.monitoring_service import (
HardwareMonitoringService,
ServiceMonitoringService,
)
from app.services.monitoring_realtime import monitoring_realtime_manager
from app.services.alert_service import AlertService
logger = logging.getLogger(__name__)
async def monitoring_metrics_collection_loop(interval_seconds: int = 10) -> None:
"""
Background loop برای جمع‌آوری و ذخیره metrics
هر interval_seconds ثانیه یکبار اجرا می‌شود (پیش‌فرض: 10 ثانیه)
"""
from sqlalchemy.exc import TimeoutError as SQLTimeoutError
while True:
try:
def _collect_and_store_metrics() -> dict:
"""جمع‌آوری و ذخیره metrics در thread جداگانه"""
try:
with get_db_session(retries=1, delay=0.5) as db:
hardware_service = HardwareMonitoringService(db)
alert_service = AlertService(db)
try:
metrics = hardware_service.collect_and_store_metrics()
# بررسی هشدارها
if metrics:
alerts = alert_service.check_hardware_metrics(metrics)
for alert_data in alerts:
alert_service.save_alert(alert_data, cooldown_minutes=5)
return metrics or {}
except Exception as e:
logger.error(f"Error collecting hardware metrics: {e}", exc_info=True)
return {}
except SQLTimeoutError as e:
# اگر connection pool پر است، skip کن و interval را افزایش بده
logger.warning(f"Skipping metrics collection due to connection pool exhaustion: {e}")
return {}
except Exception as e:
logger.error(f"Error in metrics collection: {e}", exc_info=True)
return {}
# اجرا در thread جداگانه
metrics = await asyncio.to_thread(_collect_and_store_metrics)
# ارسال به WebSocket clients (در event loop اصلی)
if metrics:
try:
await monitoring_realtime_manager.broadcast_hardware_metrics(metrics)
except Exception as e:
logger.error(f"Error broadcasting metrics: {e}", exc_info=True)
except Exception as e:
logger.error(f"Error in monitoring metrics collection loop: {e}", exc_info=True)
await asyncio.sleep(interval_seconds)
async def monitoring_service_status_check_loop(interval_seconds: int = 30) -> None:
"""
Background loop برای بررسی وضعیت سرویس‌ها
هر interval_seconds ثانیه یکبار اجرا می‌شود (پیش‌فرض: 30 ثانیه)
"""
from sqlalchemy.exc import TimeoutError as SQLTimeoutError
while True:
try:
def _check_and_store_services() -> dict:
"""بررسی و ذخیره وضعیت سرویس‌ها در thread جداگانه"""
try:
with get_db_session(retries=1, delay=0.5) as db:
service_monitor = ServiceMonitoringService(db)
alert_service = AlertService(db)
try:
services = service_monitor.check_all_services()
# ذخیره وضعیت هر سرویس
for service_name, status_data in services.items():
service_monitor.store_service_status(service_name, status_data)
# بررسی هشدارها
if services:
alerts = alert_service.check_service_status(services)
for alert_data in alerts:
alert_service.save_alert(alert_data, cooldown_minutes=5)
return services
except Exception as e:
logger.error(f"Error checking services status: {e}", exc_info=True)
return {}
except SQLTimeoutError as e:
# اگر connection pool پر است، skip کن
logger.warning(f"Skipping service status check due to connection pool exhaustion: {e}")
return {}
except Exception as e:
logger.error(f"Error in service status check: {e}", exc_info=True)
return {}
# اجرا در thread جداگانه
services = await asyncio.to_thread(_check_and_store_services)
# ارسال به WebSocket clients (در event loop اصلی)
if services:
try:
await monitoring_realtime_manager.broadcast_service_status(services)
except Exception as e:
logger.error(f"Error broadcasting services: {e}", exc_info=True)
except Exception as e:
logger.error(f"Error in service status check loop: {e}", exc_info=True)
await asyncio.sleep(interval_seconds)