New enterprise feature
This commit is contained in:
@@ -23,12 +23,11 @@ sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
|
||||
from shared.utils.demo_dates import adjust_date_for_demo, BASE_REFERENCE_DATE
|
||||
from shared.database.base import create_database_manager
|
||||
|
||||
from app.core.config import settings
|
||||
|
||||
logger = structlog.get_logger()
|
||||
router = APIRouter(prefix="/internal/demo", tags=["internal"])
|
||||
|
||||
# Internal API key for service-to-service auth
|
||||
INTERNAL_API_KEY = os.getenv("INTERNAL_API_KEY", "dev-internal-key-change-in-production")
|
||||
|
||||
# Database manager for this module
|
||||
config = AlertProcessorConfig()
|
||||
db_manager = create_database_manager(config.DATABASE_URL, "alert-processor-internal-demo")
|
||||
@@ -40,13 +39,12 @@ async def get_db():
|
||||
yield session
|
||||
|
||||
# Base demo tenant IDs
|
||||
DEMO_TENANT_SAN_PABLO = "a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6"
|
||||
DEMO_TENANT_LA_ESPIGA = "b2c3d4e5-f6a7-48b9-c0d1-e2f3a4b5c6d7"
|
||||
DEMO_TENANT_PROFESSIONAL = "a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6"
|
||||
|
||||
|
||||
def verify_internal_api_key(x_internal_api_key: Optional[str] = Header(None)):
|
||||
"""Verify internal API key for service-to-service communication"""
|
||||
if x_internal_api_key != INTERNAL_API_KEY:
|
||||
if x_internal_api_key != settings.INTERNAL_API_KEY:
|
||||
logger.warning("Unauthorized internal API access attempted")
|
||||
raise HTTPException(status_code=403, detail="Invalid internal API key")
|
||||
return True
|
||||
|
||||
0
services/alert_processor/app/core/__init__.py
Normal file
0
services/alert_processor/app/core/__init__.py
Normal file
132
services/alert_processor/app/core/config.py
Normal file
132
services/alert_processor/app/core/config.py
Normal file
@@ -0,0 +1,132 @@
|
||||
# ================================================================
|
||||
# services/alert_processor/app/core/config.py
|
||||
# ================================================================
|
||||
"""
|
||||
Alert Processor Service Configuration
|
||||
"""
|
||||
|
||||
import os
|
||||
from pydantic import Field
|
||||
from shared.config.base import BaseServiceSettings
|
||||
|
||||
|
||||
class AlertProcessorSettings(BaseServiceSettings):
|
||||
"""Alert Processor service specific settings"""
|
||||
|
||||
# Service Identity
|
||||
APP_NAME: str = "Alert Processor Service"
|
||||
SERVICE_NAME: str = "alert-processor-service"
|
||||
VERSION: str = "1.0.0"
|
||||
DESCRIPTION: str = "Central alert and recommendation processor"
|
||||
|
||||
# Database configuration (secure approach - build from components)
|
||||
@property
|
||||
def DATABASE_URL(self) -> str:
|
||||
"""Build database URL from secure components"""
|
||||
# Try complete URL first (for backward compatibility)
|
||||
complete_url = os.getenv("ALERT_PROCESSOR_DATABASE_URL")
|
||||
if complete_url:
|
||||
return complete_url
|
||||
|
||||
# Build from components (secure approach)
|
||||
user = os.getenv("ALERT_PROCESSOR_DB_USER", "alert_processor_user")
|
||||
password = os.getenv("ALERT_PROCESSOR_DB_PASSWORD", "alert_processor_pass123")
|
||||
host = os.getenv("ALERT_PROCESSOR_DB_HOST", "localhost")
|
||||
port = os.getenv("ALERT_PROCESSOR_DB_PORT", "5432")
|
||||
name = os.getenv("ALERT_PROCESSOR_DB_NAME", "alert_processor_db")
|
||||
|
||||
return f"postgresql+asyncpg://{user}:{password}@{host}:{port}/{name}"
|
||||
|
||||
# Use dedicated Redis DB for alert processing
|
||||
REDIS_DB: int = int(os.getenv("ALERT_PROCESSOR_REDIS_DB", "6"))
|
||||
|
||||
# Alert processing configuration
|
||||
BATCH_SIZE: int = int(os.getenv("ALERT_BATCH_SIZE", "10"))
|
||||
PROCESSING_TIMEOUT: int = int(os.getenv("ALERT_PROCESSING_TIMEOUT", "30"))
|
||||
|
||||
# Deduplication settings
|
||||
ALERT_DEDUPLICATION_WINDOW_MINUTES: int = int(os.getenv("ALERT_DEDUPLICATION_WINDOW_MINUTES", "15"))
|
||||
RECOMMENDATION_DEDUPLICATION_WINDOW_MINUTES: int = int(os.getenv("RECOMMENDATION_DEDUPLICATION_WINDOW_MINUTES", "60"))
|
||||
|
||||
# Alert severity channel mappings (hardcoded for now to avoid config parsing issues)
|
||||
@property
|
||||
def urgent_channels(self) -> list[str]:
|
||||
return ["whatsapp", "email", "push", "dashboard"]
|
||||
|
||||
@property
|
||||
def high_channels(self) -> list[str]:
|
||||
return ["whatsapp", "email", "dashboard"]
|
||||
|
||||
@property
|
||||
def medium_channels(self) -> list[str]:
|
||||
return ["email", "dashboard"]
|
||||
|
||||
@property
|
||||
def low_channels(self) -> list[str]:
|
||||
return ["dashboard"]
|
||||
|
||||
# ============================================================
|
||||
# ENRICHMENT CONFIGURATION (NEW)
|
||||
# ============================================================
|
||||
|
||||
# Priority scoring weights
|
||||
BUSINESS_IMPACT_WEIGHT: float = float(os.getenv("BUSINESS_IMPACT_WEIGHT", "0.4"))
|
||||
URGENCY_WEIGHT: float = float(os.getenv("URGENCY_WEIGHT", "0.3"))
|
||||
USER_AGENCY_WEIGHT: float = float(os.getenv("USER_AGENCY_WEIGHT", "0.2"))
|
||||
CONFIDENCE_WEIGHT: float = float(os.getenv("CONFIDENCE_WEIGHT", "0.1"))
|
||||
|
||||
# Priority thresholds
|
||||
CRITICAL_THRESHOLD: int = int(os.getenv("CRITICAL_THRESHOLD", "90"))
|
||||
IMPORTANT_THRESHOLD: int = int(os.getenv("IMPORTANT_THRESHOLD", "70"))
|
||||
STANDARD_THRESHOLD: int = int(os.getenv("STANDARD_THRESHOLD", "50"))
|
||||
|
||||
# Timing intelligence
|
||||
TIMING_INTELLIGENCE_ENABLED: bool = os.getenv("TIMING_INTELLIGENCE_ENABLED", "true").lower() == "true"
|
||||
BATCH_LOW_PRIORITY_ALERTS: bool = os.getenv("BATCH_LOW_PRIORITY_ALERTS", "true").lower() == "true"
|
||||
BUSINESS_HOURS_START: int = int(os.getenv("BUSINESS_HOURS_START", "6"))
|
||||
BUSINESS_HOURS_END: int = int(os.getenv("BUSINESS_HOURS_END", "22"))
|
||||
PEAK_HOURS_START: int = int(os.getenv("PEAK_HOURS_START", "7"))
|
||||
PEAK_HOURS_END: int = int(os.getenv("PEAK_HOURS_END", "11"))
|
||||
PEAK_HOURS_EVENING_START: int = int(os.getenv("PEAK_HOURS_EVENING_START", "17"))
|
||||
PEAK_HOURS_EVENING_END: int = int(os.getenv("PEAK_HOURS_EVENING_END", "19"))
|
||||
|
||||
# Grouping
|
||||
GROUPING_TIME_WINDOW_MINUTES: int = int(os.getenv("GROUPING_TIME_WINDOW_MINUTES", "15"))
|
||||
MAX_ALERTS_PER_GROUP: int = int(os.getenv("MAX_ALERTS_PER_GROUP", "5"))
|
||||
|
||||
# Email digest
|
||||
EMAIL_DIGEST_ENABLED: bool = os.getenv("EMAIL_DIGEST_ENABLED", "true").lower() == "true"
|
||||
DIGEST_SEND_TIME: str = os.getenv("DIGEST_SEND_TIME", "18:00")
|
||||
DIGEST_SEND_TIME_HOUR: int = int(os.getenv("DIGEST_SEND_TIME", "18:00").split(":")[0])
|
||||
DIGEST_MIN_ALERTS: int = int(os.getenv("DIGEST_MIN_ALERTS", "5"))
|
||||
|
||||
# Alert grouping
|
||||
ALERT_GROUPING_ENABLED: bool = os.getenv("ALERT_GROUPING_ENABLED", "true").lower() == "true"
|
||||
MIN_ALERTS_FOR_GROUPING: int = int(os.getenv("MIN_ALERTS_FOR_GROUPING", "3"))
|
||||
|
||||
# Trend detection
|
||||
TREND_DETECTION_ENABLED: bool = os.getenv("TREND_DETECTION_ENABLED", "true").lower() == "true"
|
||||
TREND_LOOKBACK_DAYS: int = int(os.getenv("TREND_LOOKBACK_DAYS", "7"))
|
||||
TREND_SIGNIFICANCE_THRESHOLD: float = float(os.getenv("TREND_SIGNIFICANCE_THRESHOLD", "0.15"))
|
||||
|
||||
# Context enrichment
|
||||
ENRICHMENT_TIMEOUT_SECONDS: int = int(os.getenv("ENRICHMENT_TIMEOUT_SECONDS", "10"))
|
||||
ORCHESTRATOR_CONTEXT_CACHE_TTL: int = int(os.getenv("ORCHESTRATOR_CONTEXT_CACHE_TTL", "300"))
|
||||
|
||||
# Peak hours (aliases for enrichment services)
|
||||
EVENING_PEAK_START: int = int(os.getenv("PEAK_HOURS_EVENING_START", "17"))
|
||||
EVENING_PEAK_END: int = int(os.getenv("PEAK_HOURS_EVENING_END", "19"))
|
||||
|
||||
# Service URLs for enrichment
|
||||
ORCHESTRATOR_SERVICE_URL: str = os.getenv("ORCHESTRATOR_SERVICE_URL", "http://orchestrator-service:8000")
|
||||
INVENTORY_SERVICE_URL: str = os.getenv("INVENTORY_SERVICE_URL", "http://inventory-service:8000")
|
||||
PRODUCTION_SERVICE_URL: str = os.getenv("PRODUCTION_SERVICE_URL", "http://production-service:8000")
|
||||
|
||||
|
||||
# Global settings instance
|
||||
settings = AlertProcessorSettings()
|
||||
|
||||
|
||||
def get_settings():
|
||||
"""Get the global settings instance"""
|
||||
return settings
|
||||
Reference in New Issue
Block a user