Merge branch 'review/pr-362'
This commit is contained in:
@@ -474,11 +474,11 @@ async def seo_dashboard_health_check():
|
|||||||
# Phase 2B: Semantic health monitoring endpoint
|
# Phase 2B: Semantic health monitoring endpoint
|
||||||
async def get_semantic_health(current_user: dict = Depends(get_current_user)) -> SemanticHealthMetric:
|
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.
|
This endpoint provides Phase 2B semantic intelligence monitoring data.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
SemanticHealthMetric with current health status, score, and recommendations
|
SemanticHealthMetric with health status, aggregate score, and recommendations.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
user_id = str(current_user.get('id'))
|
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)
|
semantic_monitor = RealTimeSemanticMonitor(user_id)
|
||||||
|
|
||||||
# Get current semantic health (will use cache if available)
|
# 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})")
|
logger.info(f"[Semantic Health API] Retrieved health data for user {user_id}: {semantic_health.status} (score: {semantic_health.value:.2f})")
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class RealTimeSemanticMonitor:
|
|||||||
|
|
||||||
logger.info(f"Real-time semantic monitor initialized for user {user_id}")
|
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.
|
Public wrapper for semantic health check.
|
||||||
Aggregates metrics into a single health status object.
|
Aggregates metrics into a single health status object.
|
||||||
@@ -109,12 +109,19 @@ class RealTimeSemanticMonitor:
|
|||||||
metrics = await self._check_semantic_health()
|
metrics = await self._check_semantic_health()
|
||||||
|
|
||||||
if not metrics:
|
if not metrics:
|
||||||
# Return default/unknown state if no metrics
|
# Return a canonical semantic health summary when no metrics are available.
|
||||||
@dataclass
|
return SemanticHealthMetric(
|
||||||
class HealthResult:
|
metric_name="semantic_health",
|
||||||
status: str = "unknown"
|
value=0.0,
|
||||||
value: float = 0.0
|
threshold=0.0,
|
||||||
return HealthResult()
|
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
|
# Aggregate metrics
|
||||||
# 1. Status: "critical" if any critical, else "warning" if any warning, else "healthy"
|
# 1. Status: "critical" if any critical, else "warning" if any warning, else "healthy"
|
||||||
@@ -129,12 +136,31 @@ class RealTimeSemanticMonitor:
|
|||||||
# 2. Value: Average of metric values
|
# 2. Value: Average of metric values
|
||||||
avg_value = sum(m.value for m in metrics) / len(metrics)
|
avg_value = sum(m.value for m in metrics) / len(metrics)
|
||||||
|
|
||||||
@dataclass
|
# 3. Threshold: Average threshold across health metrics
|
||||||
class HealthResult:
|
avg_threshold = sum(m.threshold for m in metrics) / len(metrics)
|
||||||
status: str
|
|
||||||
value: float
|
|
||||||
|
|
||||||
return HealthResult(status=status, value=avg_value)
|
# 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:
|
async def start_monitoring(self, competitors: List[str] = None) -> bool:
|
||||||
"""Start real-time semantic monitoring."""
|
"""Start real-time semantic monitoring."""
|
||||||
|
|||||||
Reference in New Issue
Block a user