diff --git a/backend/api/seo_dashboard.py b/backend/api/seo_dashboard.py index c837416c..3f14b27f 100644 --- a/backend/api/seo_dashboard.py +++ b/backend/api/seo_dashboard.py @@ -474,11 +474,11 @@ async def seo_dashboard_health_check(): # Phase 2B: Semantic health monitoring endpoint async def get_semantic_health(current_user: dict = Depends(get_current_user)) -> SemanticHealthMetric: """ - Get real-time semantic health metrics for the user's content and competitors. + Get the canonical semantic health summary for the user's content and competitors. This endpoint provides Phase 2B semantic intelligence monitoring data. - + Returns: - SemanticHealthMetric with current health status, score, and recommendations + SemanticHealthMetric with health status, aggregate score, and recommendations. """ try: user_id = str(current_user.get('id')) @@ -487,7 +487,7 @@ async def get_semantic_health(current_user: dict = Depends(get_current_user)) -> semantic_monitor = RealTimeSemanticMonitor(user_id) # Get current semantic health (will use cache if available) - semantic_health = await semantic_monitor.check_semantic_health(user_id) + semantic_health: SemanticHealthMetric = await semantic_monitor.check_semantic_health(user_id) logger.info(f"[Semantic Health API] Retrieved health data for user {user_id}: {semantic_health.status} (score: {semantic_health.value:.2f})") diff --git a/backend/services/intelligence/monitoring/semantic_dashboard.py b/backend/services/intelligence/monitoring/semantic_dashboard.py index 5880690a..a6a3b71c 100644 --- a/backend/services/intelligence/monitoring/semantic_dashboard.py +++ b/backend/services/intelligence/monitoring/semantic_dashboard.py @@ -100,7 +100,7 @@ class RealTimeSemanticMonitor: logger.info(f"Real-time semantic monitor initialized for user {user_id}") - async def check_semantic_health(self, user_id: Optional[str] = None) -> Any: + async def check_semantic_health(self, user_id: Optional[str] = None) -> SemanticHealthMetric: """ Public wrapper for semantic health check. Aggregates metrics into a single health status object. @@ -109,12 +109,19 @@ class RealTimeSemanticMonitor: metrics = await self._check_semantic_health() if not metrics: - # Return default/unknown state if no metrics - @dataclass - class HealthResult: - status: str = "unknown" - value: float = 0.0 - return HealthResult() + # Return a canonical semantic health summary when no metrics are available. + return SemanticHealthMetric( + metric_name="semantic_health", + value=0.0, + threshold=0.0, + status="warning", + timestamp=datetime.utcnow().isoformat(), + description="No semantic health metrics available yet", + recommendations=[ + "Run semantic analysis to populate health metrics", + "Check data sources and try again shortly" + ] + ) # Aggregate metrics # 1. Status: "critical" if any critical, else "warning" if any warning, else "healthy" @@ -128,13 +135,32 @@ class RealTimeSemanticMonitor: # 2. Value: Average of metric values avg_value = sum(m.value for m in metrics) / len(metrics) - - @dataclass - class HealthResult: - status: str - value: float - - return HealthResult(status=status, value=avg_value) + + # 3. Threshold: Average threshold across health metrics + avg_threshold = sum(m.threshold for m in metrics) / len(metrics) + + # 4. Recommendations: de-duplicated recommendations from non-healthy metrics + recommendations = [] + seen_recommendations = set() + for metric in metrics: + if metric.status != "healthy": + for recommendation in metric.recommendations: + if recommendation not in seen_recommendations: + seen_recommendations.add(recommendation) + recommendations.append(recommendation) + + if not recommendations: + recommendations = ["Continue monitoring semantic performance"] + + return SemanticHealthMetric( + metric_name="semantic_health", + value=avg_value, + threshold=avg_threshold, + status=status, + timestamp=datetime.utcnow().isoformat(), + description="Aggregated semantic health across monitoring metrics", + recommendations=recommendations, + ) async def start_monitoring(self, competitors: List[str] = None) -> bool: """Start real-time semantic monitoring."""