FinOps Cost Dashboard Setup with Power BI
Step-by-step guide to building an executive FinOps dashboard in Power BI for multi-cloud cost visibility across Azure, OCI, and AWS.
📊 Build Your FinOps Control Center
Build a comprehensive FinOps dashboard in Power BI to track cloud spending, trends, and optimization opportunities across your multi-cloud environment.
🎯 What You'll Build
A single-pane-of-glass dashboard showing:
Total Cloud Spend
Aggregated costs across all platforms with historical trends
Cost Trends
Month-over-month and year-over-year comparisons
Environment Breakdown
Costs segmented by production vs non-production
Top 10 Resources
Most expensive resources at a glance
Budget vs Actual
Real-time alerts when approaching budget limits
Cost per Team
Chargeback reports using tag-based attribution
📋 Prerequisites
- •Power BI Desktop (free version works)
- •Access to Azure Cost Management, OCI Cost Analysis, or AWS Cost Explorer
- •Basic understanding of Power BI and DAX
- •Azure AD permissions for Cost Management API (Reader role)
🏗️ Architecture Overview
Azure Cost Data → Azure Cost Management Connector
OCI Cost Data → OCI API → CSV Export → Power BI
↓
Power BI Dashboard
↓
Publish to Power BI Service
↓
Share with StakeholdersStep 1: Set Up Azure Cost Management Connector
Option A: Direct Azure Connector (Recommended)
- 1.Open Power BI Desktop
- 2.Click Get Data → Azure → Azure Cost Management
- 3.Sign in with Azure AD credentials
- 4.Select Scope:
- Management Group (for multi-subscription)
- Subscription ID
- Resource Group
- 5.Configure Date Range: Start Date: 2024-01-01, End Date: Today, Granularity: Daily
Option B: Cost Management Export (For Automation)
Set up automated exports:
# Azure CLI: Create cost export
az costmanagement export create \
--name "monthly-costs" \
--scope "/subscriptions/YOUR-SUB-ID" \
--schedule-recurrence "Monthly" \
--recurrence-period from="2025-01-01" to="2025-12-31" \
--storage-account-id "/subscriptions/.../storageAccounts/costsexport" \
--storage-container "exports" \
--definition type="ActualCost" timeframe="MonthToDate"Then connect Power BI to the storage account.
Step 2: Import OCI Cost Data
OCI doesn't have a direct Power BI connector, so use CSV exports:
Generate OCI Cost Report via CLI
#!/bin/bash
# oci-cost-export.sh
TENANCY_ID="ocid1.tenancy.oc1..aaa..."
COMPARTMENT_ID="ocid1.compartment.oc1..aaa..."
START_DATE="2024-01-01"
END_DATE="2025-01-31"
# Get usage report
oci usage-api usage-summary request-summarized-usages \
--tenant-id "$TENANCY_ID" \
--time-usage-started "$START_DATE" \
--time-usage-ended "$END_DATE" \
--granularity DAILY \
--query-type COST \
--compartment-depth 5 \
--group-by='["service","compartmentName"]' \
--output table > oci-costs.csvImport CSV to Power BI
- 1.Power BI Desktop → Get Data → Text/CSV
- 2.Select
oci-costs.csv - 3.Click Transform Data to clean
💡 Transform Steps
- • Remove unnecessary columns
- • Rename columns to match Azure schema:
time_usage_started→Datecomputed_amount→Costservice→ServiceNamecompartment_name→ResourceGroup
Step 3: Data Modeling
Create Unified Cost Table
Merge Azure and OCI data into single table:
// Create UnifiedCosts table
UnifiedCosts =
UNION(
SELECTCOLUMNS(
AzureCosts,
"Date", [Date],
"Cloud", "Azure",
"Cost", [Cost],
"Service", [ServiceName],
"Environment", [Tags.Environment],
"Owner", [Tags.Owner],
"Project", [Tags.Project]
),
SELECTCOLUMNS(
OCICosts,
"Date", [Date],
"Cloud", "OCI",
"Cost", [Cost],
"Service", [ServiceName],
"Environment", [FreeformTags.Environment],
"Owner", [FreeformTags.Owner],
"Project", [FreeformTags.Project]
)
)Create Date Table
// Calendar table for time intelligence
Calendar =
ADDCOLUMNS(
CALENDAR(DATE(2024,1,1), TODAY()),
"Year", YEAR([Date]),
"Month", FORMAT([Date], "MMM"),
"MonthNum", MONTH([Date]),
"Quarter", "Q" & FORMAT([Date], "Q"),
"YearMonth", FORMAT([Date], "YYYY-MM")
)Define Measures
// Total Cost
Total Cost = SUM(UnifiedCosts[Cost])
// Month-over-Month Change
MoM Change =
VAR CurrentMonth = [Total Cost]
VAR PreviousMonth = CALCULATE([Total Cost], DATEADD(Calendar[Date], -1, MONTH))
RETURN
DIVIDE(CurrentMonth - PreviousMonth, PreviousMonth, 0)
// Budget Variance
Budget Variance =
VAR ActualCost = [Total Cost]
VAR BudgetAmount = 50000 // Or reference Budget table
RETURN
ActualCost - BudgetAmount
// Cost per Environment
Prod Cost = CALCULATE([Total Cost], UnifiedCosts[Environment] = "prod")
NonProd Cost = CALCULATE([Total Cost], UnifiedCosts[Environment] <> "prod")
// Average Daily Cost
Avg Daily Cost =
AVERAGEX(
VALUES(Calendar[Date]),
[Total Cost]
)Step 4: Build Dashboard Visuals
Page 1: Executive Summary
KPI Cards (Top Row):
- 1. Total Spend (MTD)
- 2. Budget Remaining
- 3. MoM Change %
- 4. Largest Single Resource Cost
Charts (Main Area):
- Line Chart: Daily cost trend (last 90 days)
- X-axis: Date
- Y-axis: Total Cost
- Legend: Cloud (Azure, OCI)
- Donut Chart: Cost by Environment
- Values: Total Cost
- Legend: Environment (prod, staging, dev)
- Bar Chart: Top 10 Services by Cost
- Y-axis: Service Name
- X-axis: Total Cost
- Color: Cloud
Page 2: Detailed Analysis
- • Table: Resource-Level Costs (Columns: Resource Name, Owner, Project, Daily Cost, Total Cost)
- • Matrix: Cost by Team & Project (Rows: Owner, Project | Columns: Month | Values: Total Cost)
- • Treemap: Service Distribution (Group: Service Name | Size: Total Cost | Color: Cloud)
Page 3: Trends & Forecasting
- • Line Chart: Monthly Trend with Forecast (Use Power BI's built-in forecast - 30 days ahead with confidence interval)
- • Stacked Area Chart: Cost Breakdown Over Time (X-axis: Month | Y-axis: Total Cost | Legend: Service Category)
Step 5: Add Interactivity
Slicers (Filters)
Add slicers to filter entire dashboard:
- • Date Range (Calendar slicer)
- • Cloud Provider (Azure / OCI)
- • Environment (prod / staging / dev)
- • Owner (Team list)
Drill-Through Pages
Create drill-through page for resource details:
- • Right-click any resource → "Drill through" → Resource Details
- • Shows full cost breakdown, tags, daily trend
Step 6: Set Up Alerts
Budget Alert Measure
Budget Alert =
VAR CurrentSpend = [Total Cost]
VAR BudgetLimit = 50000
VAR PercentUsed = DIVIDE(CurrentSpend, BudgetLimit, 0)
RETURN
IF(
PercentUsed > 0.8,
"🔴 Over Budget",
IF(
PercentUsed > 0.6,
"🟡 Warning",
"🟢 On Track"
)
)Conditional Formatting
Apply traffic light colors to budget KPI:
- • Green: < 60% of budget
- • Yellow: 60-80% of budget
- • Red: > 80% of budget
Step 7: Publish & Share
- 1.Publish to Power BI Service
- File → Publish → Select Workspace
- Configure scheduled refresh (daily at 6 AM)
- 2.Set Up Row-Level Security (RLS)
// Only show team's costs [Owner] = USERNAME() - 3.Create App
- Publish as Power BI App
- Share with organization
- 4.Pin to Teams
- Add dashboard tab in Microsoft Teams channel
🚀 Advanced Tips
Anomaly Detection
// Flag unusual spending
Cost Anomaly =
VAR CurrentCost = [Total Cost]
VAR AvgCost = [Avg Daily Cost]
VAR StdDev = STDEV.P(UnifiedCosts[Cost])
RETURN
IF(
CurrentCost > AvgCost + (2 * StdDev),
"⚠️ Anomaly Detected",
"Normal"
)Currency Conversion
If multi-currency:
Cost USD =
SWITCH(
UnifiedCosts[Currency],
"EUR", UnifiedCosts[Cost] * 1.10,
"GBP", UnifiedCosts[Cost] * 1.27,
UnifiedCosts[Cost] // Default USD
)✅ DO
- • Update dashboard at least daily
- • Use consistent color schemes
- • Include tooltips explaining metrics
- • Test with different user roles
❌ DON'T
- • Clutter with too many visuals
- • Use pie charts for >5 categories
- • Forget last-updated timestamp
- • Mix currencies without conversion
⚠️ Troubleshooting
- Issue: Power BI refresh fails
Solution: Check gateway connection, verify API permissions - Issue: OCI data not updating
Solution: Automate CSV export with cron job - Issue: Slow dashboard performance
Solution: Use incremental refresh, limit date range
🎯 Next Steps
- • Integrate AWS costs using AWS Cost and Usage Report
- • Add forecasting models using Azure Machine Learning
- • Set up email alerts for budget overruns
- • Create executive summary PDF export
📚 Related Resources
Need more FinOps insights? Check out FinOps Flight Deck for strategies and best practices.