"""Business-list cost governance, anomaly, allocation, and trend facts.""" from __future__ import annotations from collections.abc import Callable, Sequence from datetime import UTC, datetime, timedelta from decimal import Decimal from sqlalchemy import and_, case, func, select from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.ext.asyncio import AsyncSession from app.domains.cmdb.cost_service import detect_anomalies from app.domains.cmdb.cost_view import ( COST_MEASURE_LIST, engineering_row_clause, fact_engineering_amount, ) from app.domains.cmdb.models import ( SCOPE_STATUS_ACTIVE, CmdbCloudScope, CmdbCostFact, CmdbServerEfficiency, ) from app.integrations.models import Integration from app.intelligence.privacy import EvidenceObject from app.intelligence.snapshot_service import ( MetricObservation, ProviderResult, ProviderUnavailable, SnapshotSubject, ) _EVIDENCE_LIMIT = 50 def _utc(value: datetime) -> datetime: return value.replace(tzinfo=UTC) if value.tzinfo is None else value.astimezone(UTC) def _pct(value: Decimal | int, total: Decimal | int) -> Decimal: return (Decimal(value) * 100 / Decimal(total)).quantize(Decimal("0.01")) class CostEfficiencyFactProvider: """Collect only the shared business/list view; invoice data never enters.""" dimension = "cost_efficiency" def __init__(self, *, now: Callable[[], datetime] | None = None) -> None: self._now = now or (lambda: datetime.now(UTC)) @staticmethod def _validate_subject(subject: SnapshotSubject) -> None: if subject.subject_type == "platform" and subject.subject_id == "platform": return if subject.subject_type == "domain" and subject.subject_id == "cost_efficiency": return raise ValueError("Cost facts only support platform or cost_efficiency snapshots") async def collect(self, db: AsyncSession, subject: SnapshotSubject) -> ProviderResult: self._validate_subject(subject) try: return await self._collect(db) except SQLAlchemyError as exc: raise ProviderUnavailable("cost datastore unavailable") from exc async def _collect(self, db: AsyncSession) -> ProviderResult: now = _utc(self._now()) enabled_integration_ids = { str(value) for value in ( await db.execute( select(Integration.id).where( Integration.kind == "cloud", Integration.enabled.is_(True), ) ) ).scalars() } scopes = list( ( await db.execute( select(CmdbCloudScope).where( CmdbCloudScope.integration_id.in_(enabled_integration_ids), CmdbCloudScope.deleted_at.is_(None), CmdbCloudScope.status == SCOPE_STATUS_ACTIVE, ) ) ).scalars() ) if enabled_integration_ids else [] list_budget_scopes = [ row for row in scopes if row.budget_measure == COST_MEASURE_LIST and row.budget_usd_monthly is not None and row.budget_usd_monthly > 0 ] budget_gaps = [row for row in scopes if row not in list_budget_scopes] budget_as_of = max((_utc(row.updated_at) for row in scopes), default=None) last_complete_day = now.date() - timedelta(days=1) current_start = last_complete_day - timedelta(days=29) previous_end = current_start - timedelta(days=1) previous_start = previous_end - timedelta(days=29) amount = fact_engineering_amount() current_window = and_( CmdbCostFact.date >= current_start, CmdbCostFact.date <= last_complete_day, ) previous_window = and_( CmdbCostFact.date >= previous_start, CmdbCostFact.date <= previous_end, ) integration_filter = CmdbCostFact.integration_id.in_(enabled_integration_ids) totals_row = ( await db.execute( select( func.coalesce(func.sum(case((current_window, amount), else_=0)), 0), func.coalesce(func.sum(case((previous_window, amount), else_=0)), 0), func.coalesce( func.sum( case( ( and_( current_window, CmdbCostFact.auto_owner_source.is_not(None), CmdbCostFact.auto_owner_source != "none", ), amount, ), else_=0, ) ), 0, ), func.max(case((current_window, CmdbCostFact.date), else_=None)), ).where( integration_filter, CmdbCostFact.date >= previous_start, CmdbCostFact.date <= last_complete_day, ) ) ).one() if enabled_integration_ids else (0, 0, 0, None) current_cost = Decimal(str(totals_row[0] or 0)) previous_cost = Decimal(str(totals_row[1] or 0)) allocated_cost = Decimal(str(totals_row[2] or 0)) allocated_cost = min(current_cost, max(Decimal("0"), allocated_cost)) cost_as_of = ( datetime.combine(totals_row[3], datetime.min.time(), tzinfo=UTC) if totals_row[3] is not None else None ) resource_rows = list( ( await db.execute( select(CmdbCostFact.integration_id, CmdbCostFact.resource_id) .where( integration_filter, current_window, engineering_row_clause(), CmdbCostFact.resource_id.is_not(None), ) .group_by(CmdbCostFact.integration_id, CmdbCostFact.resource_id) .add_columns(func.count(func.distinct(CmdbCostFact.date)).label("data_days")) ) ).all() ) if enabled_integration_ids else [] resource_keys = {(str(row.integration_id), str(row.resource_id)) for row in resource_rows} evaluable_resource_keys = { (str(row.integration_id), str(row.resource_id)) for row in resource_rows if int(row.data_days or 0) >= 7 } anomalies = await detect_anomalies( db, days=30, integration_ids=sorted(enabled_integration_ids), limit=None, measure=COST_MEASURE_LIST, as_of_date=now.date(), resource_keys=evaluable_resource_keys, # Shared Intelligence scans every active cloud account. Keep # each aggregation to a week so TiDB cannot cancel the snapshot # for exceeding its per-query memory budget. chunk_days=7, ) if enabled_integration_ids else [] anomalies = [ row for row in anomalies if ( str(row["integration_id"]), str(row["resource_id"]) ) in evaluable_resource_keys ] anomalous_keys = { (str(row["integration_id"]), str(row["resource_id"])) for row in anomalies } efficiency = list( ( await db.execute( select(CmdbServerEfficiency).where( CmdbServerEfficiency.integration_id.in_(enabled_integration_ids) ) ) ).scalars() ) if enabled_integration_ids else [] priced_efficiency = [row for row in efficiency if row.monthly_cost_usd is not None] efficiency_cost = sum( (Decimal(str(row.monthly_cost_usd or 0)) for row in priced_efficiency), Decimal("0"), ) estimated_savings = sum( (Decimal(str(row.estimated_monthly_savings_usd or 0)) for row in priced_efficiency), Decimal("0"), ) optimizable_rows = [ row for row in priced_efficiency if row.estimated_monthly_savings_usd is not None and row.estimated_monthly_savings_usd > 0 ] efficiency_as_of = max( (_utc(row.computed_at) for row in efficiency), default=None, ) growth_rate = ( max(Decimal("0"), (current_cost - previous_cost) * 100 / previous_cost) if previous_cost > 0 else Decimal("0") ).quantize(Decimal("0.01")) unallocated_fact_ids = list( ( await db.execute( select(CmdbCostFact.id) .where( integration_filter, current_window, engineering_row_clause(), ( CmdbCostFact.auto_owner_source.is_(None) | (CmdbCostFact.auto_owner_source == "none") ), ) .order_by(CmdbCostFact.id) .limit(_EVIDENCE_LIMIT) ) ).scalars() ) if enabled_integration_ids else [] def refs(kind: str, ids: Sequence[object]) -> tuple[EvidenceObject, ...]: return tuple(EvidenceObject(kind, str(value)) for value in ids[:_EVIDENCE_LIMIT]) anomaly_refs = tuple( EvidenceObject("costresource", f"{integration_id}:{resource_id}") for integration_id, resource_id in sorted(anomalous_keys)[:_EVIDENCE_LIMIT] ) metric_times = [value for value in (budget_as_of, cost_as_of, efficiency_as_of) if value] return ProviderResult( dimension=self.dimension, metrics=( MetricObservation( "cost_efficiency.business_budget_coverage", _pct(len(list_budget_scopes), len(scopes)) if scopes else 0, confidence=100 if scopes else 0, evidence=refs("scope", [row.id for row in budget_gaps]), data_as_of=budget_as_of, ), MetricObservation( "cost_efficiency.anomaly_rate", _pct(len(anomalous_keys), len(evaluable_resource_keys)) if evaluable_resource_keys else 0, confidence=( _pct(len(evaluable_resource_keys), len(resource_keys)) if resource_keys else 0 ), evidence=anomaly_refs, data_as_of=cost_as_of, ), MetricObservation( "cost_efficiency.optimizable_cost_rate", _pct(estimated_savings, efficiency_cost) if efficiency_cost > 0 else 0, confidence=100 if efficiency_cost > 0 else 0, evidence=refs("server", [row.server_id for row in optimizable_rows]), data_as_of=efficiency_as_of, ), MetricObservation( "cost_efficiency.allocation_coverage", _pct(allocated_cost, current_cost) if current_cost > 0 else 0, confidence=100 if current_cost > 0 else 0, evidence=refs("costfact", unallocated_fact_ids), data_as_of=cost_as_of, ), MetricObservation( "cost_efficiency.growth_rate", growth_rate, confidence=100 if previous_cost > 0 else 0, data_as_of=cost_as_of, ), ), aggregate_facts={ "active_scope_count": len(scopes), "business_budget_scope_count": len(list_budget_scopes), "business_cost_resource_count": len(resource_keys), "evaluable_cost_resource_count": len(evaluable_resource_keys), "anomalous_resource_count": len(anomalous_keys), "priced_efficiency_resource_count": len(priced_efficiency), "optimizable_resource_count": len(optimizable_rows), "current_business_cost_usd": current_cost.quantize(Decimal("0.01")), "previous_business_cost_usd": previous_cost.quantize(Decimal("0.01")), "allocated_business_cost_usd": allocated_cost.quantize(Decimal("0.01")), "estimated_monthly_savings_usd": estimated_savings.quantize(Decimal("0.01")), "growth_rate_pct": growth_rate, "cost_measure": COST_MEASURE_LIST, "window_days": 30, }, data_as_of=min(metric_times) if metric_times else None, )