fix(azure/dashboard): reconcile committed figure with Coverage tab - #1126
Conversation
The Home dashboard showed a non-zero "current / committed" figure for Azure (e.g. $166) while the Coverage tab reported $0 / "No usage detected" for the same subscription. The two surfaces read different fields of the same active commitments, and the Coverage path silently dropped Azure rows. Root cause: getCoverageBreakdown summed only the recurring MonthlyCost and guarded it with `if p.MonthlyCost != nil`. Azure all-upfront RIs carry MonthlyCost == nil (no recurring charge at the commitment layer, documented on config.PurchaseHistoryRecord.MonthlyCost), so every such row was skipped and the provider collapsed to nil Services / nil OverallCoveragePct. The dashboard, by contrast, aggregates EstimatedSavings (always populated), so it still counted the commitment. PR #1105 only fixed the recommendation converter's RecurringMonthlyCost for future rows; it never touched the Coverage handler, so the divergence persisted. Fix: derive the effective covered monthly spend via a shared commitmentCoveredMonthly helper = recurring MonthlyCost (when present) + amortised upfront (UpfrontCost / (Term * MonthsPerYear)), matching the canonical effective-monthly formula already used by analytics.Collector and exchange_lookup. An all-upfront commitment now contributes its amortised upfront instead of being silently dropped, so Coverage reflects the same active commitments the dashboard does. A nil MonthlyCost is treated as a real $0 recurring component (not a fabricated total), and Term <= 0 is guarded against division by zero, mirroring the collector's skip-bad-term defence. Regression test TestHandler_getCoverageBreakdown_AzureAllUpfrontConsistency seeds an active Azure compute all-upfront RI (MonthlyCost nil, $1200 upfront / 1y = $100/mo) and asserts both that the dashboard primitive counts it AND that the Coverage tab now reports $100/mo covered (100% coverage) instead of nil. It fails pre-fix (azure.Services nil) and passes post-fix.
|
@coderabbitai review |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughCoverage breakdown calculation for active commitments now properly handles all-upfront purchases by amortising upfront costs into monthly equivalents, fixing prior zero-coverage cases where ChangesCoverage Breakdown Upfront Amortization
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
✅ Action performedReview finished.
|
Problem
The app owner reported on the live GUI: the Home page graph's current / committed figure for Azure showed $166, while the Coverage tab showed ZERO coverage for Azure. The same Azure subscription cannot both have active committed spend and zero coverage.
Repro
by_service[svc].current_savings, sourced fromaggregateActiveCommitmentsPerServicewhich sums each active commitment'sEstimatedSavings(always populated) -> shows $166.GET /api/inventory/coverage) summed only the recurringMonthlyCost, guarded byif p.MonthlyCost != nil.Azure all-upfront RIs carry
MonthlyCost == nil(no recurring charge at the commitment layer; documented onconfig.PurchaseHistoryRecord.MonthlyCost). So every Azure all-upfront row was silently dropped, the provider collapsed toServices=nil/OverallCoveragePct=nil, and the frontend rendered "No usage detected" -> ZERO. Meanwhile the dashboard still counted the same commitment.Root cause
getCoverageBreakdown(internal/api/handler_inventory.go:184) ignored the upfront component entirely and skipped nil-MonthlyCostrows. PR #1105 only fixed the recommendation converter'sRecurringMonthlyCostfor future rows; it never touched the Coverage handler, so the divergence persisted (not deploy-lag — confirmed against committedorigin/feat/multicloud-web-frontend).Fix
Introduce a shared
commitmentCoveredMonthlyhelper computing the effective covered monthly spend = recurringMonthlyCost(when present) + amortised upfront (UpfrontCost / (Term * MonthsPerYear)). This mirrors the canonical effective-monthly formula already used byanalytics.Collector(the dashboard's savings analytics) andexchange_lookup, so the two surfaces agree on what "covered" means.MonthlyCostis treated as a real $0 recurring component, not a fabricated total (no silent fallback; absent != 0 distortion).Term <= 0is guarded against division by zero, matchinganalytics.Collector's skip-bad-term defence.The dashboard chart (savings) and Coverage tab (covered spend) measure different quantities by design and remain distinct numbers, but the actual defect - Azure silently dropping to zero coverage while the dashboard counts active commitments - is resolved: Coverage now reflects the same active Azure commitments.
Tests
TestHandler_getCoverageBreakdown_AzureAllUpfrontConsistencyseeds an active Azure compute all-upfront RI (MonthlyCostnil, $1200 upfront / 1y term = $100/mo) and asserts:aggregateActiveCommitmentsPerServicecounts it ($166 savings);azure:compute, not nil/zero.Fails pre-fix (
azure.Servicesnil -> "No usage detected"), passes post-fix.go build ./...green;go test ./internal/api/ ./internal/analytics/ ./internal/purchase/all green (2015 tests). No frontend change required - the UI already renderscovered_monthlycorrectly once it is non-zero.Summary by CodeRabbit