Fabric Control Tower — Reference Component
Part of the Frontier Fabric AgentOps RVAS. This is the control tower itself — the Fabric workspace you stand up across Challenge 3 (OneLake foundation), Challenge 4 (medallion pipeline), and Challenge 5 (Direct Lake dashboards).
Overview
This component implements the Microsoft Fabric analytics layer of the AgentOps Control Tower. It processes data from Azure Monitor, Cost Management, and Cosmos DB through a medallion architecture (Bronze → Silver → Gold) in Microsoft Fabric, producing Power BI reports for operational insights.
Raw telemetry — cost exports, platform metrics, diagnostic logs, and AI-agent conversations — flows into a Fabric Lakehouse via ADLS Gen2 shortcuts and Cosmos DB Mirroring. PySpark notebooks transform the data through progressively refined layers, and a Direct Lake semantic model powers interactive Power BI dashboards without any data duplication.
Architecture
┌─────────────────────────────────────────────────────────────────────────────┐
│ Data Sources │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────────────┐ │
│ │ ADLS Gen2 │ │ ADLS Gen2 │ │ Cosmos DB │ │
│ │ Cost Exports │ │ Metrics / Logs │ │ Agent Conversations │ │
│ │ Resource Metadata│ │ (Azure Monitor) │ │ (Agent Workload) │ │
│ └────────┬─────────┘ └────────┬─────────┘ └────────────┬─────────────┘ │
│ │ │ │ │
└───────────┼──────────────────────┼──────────────────────────┼────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Microsoft Fabric │
│ │
│ ┌─────────────────────────────────────┐ ┌────────────────────────────┐ │
│ │ Lakehouse (OneLake) │ │ Mirrored Database │ │
│ │ ├─ Files/ │ │ Cosmos DB → Delta Tables │ │
│ │ │ ├─ costs/ (shortcut) │ │ (near-real-time sync) │ │
│ │ │ ├─ metrics/ (shortcut) │ └────────────┬───────────────┘ │
│ │ │ ├─ logs/ (shortcut) │ │ │
│ │ │ └─ resource-metadata/ (shortcut│ │ │
│ │ └─ Tables/ │ │ │
│ │ ├─ bronze_* (raw Delta) │◄───────────────┘ │
│ │ ├─ silver_* (cleansed Delta) │ │
│ │ └─ gold_* (aggregated Delta)│ │
│ └─────────────────┬───────────────────┘ │
│ │ │
│ ┌─────────────────▼───────────────────┐ │
│ │ Notebooks (PySpark) │ │
│ │ 01_bronze_ingestion │ │
│ │ 02_silver_transformation │ │
│ │ 03_gold_aggregation │ │
│ │ 04_cosmos_mirroring_transform │ │
│ └─────────────────┬───────────────────┘ │
│ │ │
│ ┌─────────────────▼───────────────────┐ │
│ │ Pipelines │ │
│ │ ├─ Load E2E Pipeline │ │
│ │ └─ Daily Refresh Pipeline │ │
│ └─────────────────┬───────────────────┘ │
│ │ │
│ ┌─────────────────▼───────────────────┐ ┌────────────────────────────┐ │
│ │ Semantic Model (Direct Lake) │──▶│ Power BI Reports │ │
│ │ fact_costs, fact_metrics, ... │ │ Cost Overview │ │
│ │ dim_resource, dim_date, ... │ │ Capacity Utilization │ │
│ │ Measures: TotalCost, ErrorRate ... │ │ Operational Health │ │
│ └─────────────────────────────────────┘ │ Agent Performance │ │
│ │ Resource Inventory │ │
│ └────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
Prerequisites
| Requirement | Details |
|---|---|
| Azure subscription | Contributor access on the target resource group |
| Microsoft Fabric capacity | F2 or higher (F64+ recommended for production) |
| Python | 3.11 or later |
| Azure CLI | 2.60+ with az login completed |
| Azure Developer CLI (azd) | Latest version |
| GitHub OIDC | Federated credential configured for the repository |
Deployment
1. Deploy Azure Infrastructure
Provision the storage account, key vault, and managed identity used by Fabric:
azd auth login
azd provision
This creates:
- Storage Account (ADLS Gen2) — landing zone for cost exports, metrics, and logs
- Key Vault — stores connection strings and Fabric API credentials
- User-Assigned Managed Identity — grants Fabric access to ADLS Gen2
2. Configure Fabric Workspace
Create the Fabric workspace, lakehouse, ADLS shortcuts, and import notebooks:
pip install -r src/setup/requirements.txt
python src/setup/setup_fabric_workspace.py \
--workspace-name "Observability-Analytics" \
--storage-account-url "https://<account>.dfs.core.windows.net" \
--capacity-id "<fabric-capacity-id>"
The script performs the following:
- Creates (or reuses) a Fabric workspace assigned to the specified capacity.
- Creates an Observability lakehouse inside the workspace.
- Adds ADLS Gen2 shortcuts under
Files/for each data container (costs,metrics,logs,resource-metadata). - Uploads and imports all PySpark notebooks from
fabric/notebooks/. - Creates the Load E2E Pipeline and Daily Refresh Pipeline.
3. Configure Cosmos DB Mirroring
Enable Fabric Mirroring for the Cosmos DB database containing agent conversations:
python src/setup/setup_cosmos_mirroring.py \
--workspace-id "<workspace-id>" \
--cosmos-account "<cosmos-account-name>" \
--database "observability"
The script:
- Enables the Cosmos DB account for Fabric Mirroring (continuous backup, analytical store).
- Creates a mirrored database item in the Fabric workspace.
- Configures table selection and replication for the
conversations,messages, andfeedbackcontainers.
4. Run Notebooks
Run the notebooks in order — either manually in Fabric or via the E2E pipeline:
| Order | Notebook | Purpose |
|---|---|---|
| 1 | 01_bronze_ingestion |
Load raw Parquet into Delta tables |
| 2 | 02_silver_transformation |
Cleanse, normalize, and enrich |
| 3 | 03_gold_aggregation |
Build analytical aggregates |
| 4 | 04_cosmos_mirroring_transform |
Transform mirrored conversation data |
To trigger all four in sequence, open the Load E2E Pipeline in Fabric and click Run.
Notebooks
01_bronze_ingestion.ipynb
Reads raw Parquet files from ADLS Gen2 shortcuts and writes Delta tables into the Lakehouse Tables/ section.
Input: Files/costs/, Files/metrics/, Files/logs/, Files/resource-metadata/
Output: bronze_costs, bronze_metrics, bronze_logs, bronze_resource_metadata
Key behaviors:
- Schema inference with explicit type overrides for known columns.
- Append mode with deduplication using
_source_fileand_ingestion_timestampwatermarks. - Data quality checks: null key detection, row-count validation, schema-drift alerts.
02_silver_transformation.ipynb
Cleanses and transforms Bronze tables into an analysis-ready Silver layer.
Transformations:
- Costs: Normalizes raw billing data to the FOCUS cost schema — standardized column names, currency conversion, amortization of reservations and savings plans.
- Metrics: Pivots time-series metric records from long to wide format; interpolates missing intervals; aligns to 5-minute grain.
- Logs: Parses semi-structured log messages; extracts severity, category, operation, and correlation ID; filters noise.
- Resource Metadata: Flattens nested resource properties and tag maps; adds computed columns for resource age, region normalization, and service categorization.
Output: silver_costs, silver_metrics, silver_logs, silver_resource_metadata
03_gold_aggregation.ipynb
Creates analytical aggregates consumed by the semantic model.
Output tables:
| Table | Description |
|---|---|
gold_cost_summary |
Daily/monthly cost aggregates by subscription, resource group, service, and tag |
gold_capacity_usage |
Hourly capacity utilization (CPU, memory, DTU) with percentile bands |
gold_operational_metrics |
Error rates, latency percentiles (p50/p95/p99), availability per service |
gold_resource_inventory |
Current and historical resource state with SCD Type 2 tracking |
gold_agent_analytics |
Conversation counts, token usage, response times, satisfaction scores |
dim_date |
Standard date dimension (fiscal calendar, holidays, working days) |
dim_resource |
Conformed resource dimension with hierarchy (subscription → resource group → resource) |
04_cosmos_mirroring_transform.ipynb
Transforms mirrored Cosmos DB conversation data into agent analytics.
Input: Mirrored tables conversations, messages, feedback
Output: gold_agent_analytics, gold_conversation_details
Key behaviors:
- Sessionizes messages into conversation threads.
- Calculates per-conversation metrics: message count, total tokens, elapsed time, resolution status.
- Joins feedback scores and computes rolling satisfaction averages.
- Handles late-arriving mirrored records with merge-on-read reconciliation.
Pipeline Schedule
| Pipeline | Trigger | Scope |
|---|---|---|
| Load E2E Pipeline | Manual (workflow dispatch or Fabric UI) | Processes the last 3 months by default; configurable via start_date parameter |
| Daily Refresh Pipeline | Scheduled — daily at 06:00 UTC | Processes the current month with incremental append |
Both pipelines include:
- Dependency ordering: Bronze → Silver → Gold → Semantic Model refresh.
- Retry policy: 2 retries with 5-minute backoff.
- Failure notifications via Fabric alerts (email and Teams webhook).
Semantic Model
The Direct Lake semantic model connects Power BI directly to Delta tables in OneLake — no import or DirectQuery overhead.
Tables and Relationships
dim_date ──────────┐
│ 1:*
fact_costs ◄───────┤
│ 1:*
dim_resource ──────┤
│ 1:*
fact_metrics ◄─────┤
│ 1:*
fact_operations ◄──┘
fact_agent_analytics ──▶ dim_date
Key Measures
| Measure | Expression (DAX) |
|---|---|
| TotalCost | SUM(fact_costs[BilledCost]) |
| CostMoM% | Month-over-month cost change percentage |
| CapacityUtilization | AVERAGE(fact_metrics[CPUPercent]) |
| ErrorRate | DIVIDE(COUNTROWS(FILTER(fact_operations, [Severity] = "Error")), COUNTROWS(fact_operations)) |
| P95Latency | PERCENTILE.INC(fact_operations[DurationMs], 0.95) |
| AvgSatisfaction | AVERAGE(fact_agent_analytics[SatisfactionScore]) |
| ConversationCount | DISTINCTCOUNT(fact_agent_analytics[ConversationId]) |
Time Intelligence
All cost and metric measures include time-intelligence variants: YTD, MTD, QTD, prior period, and rolling 30-day averages. These are generated via a calculation group applied to dim_date.
Power BI Report
Connecting to the Semantic Model
- Open Power BI Desktop or the Power BI service.
- Select OneLake data hub → choose the semantic model published from this workspace.
- The connection uses Direct Lake mode — no data copy is created.
Suggested Report Pages
| Page | Key Visuals |
|---|---|
| Cost Overview | KPI cards (total cost, MoM trend), cost-by-service bar chart, daily cost line chart with forecast, top-10 cost drivers table |
| Capacity Utilization | Gauge charts per capacity metric, heatmap by resource and hour, utilization trend with threshold lines |
| Operational Health | Error-rate trend, P95 latency sparklines, availability scorecards, log-severity breakdown donut chart |
| Agent Performance | Conversation volume over time, avg response time, token consumption bar chart, satisfaction trend, resolution rate funnel |
| Resource Inventory | Resource count by type/region matrix, change timeline (SCD events), tag compliance percentage, orphaned resource list |
Design Guidelines
- Use the organization's brand palette for consistent theming.
- Apply row-level security (RLS) roles mapped to subscription or resource-group ownership.
- Enable paginated export for the Resource Inventory page.
Integration with Other Components
| Component | Integration Point |
|---|---|
| Agent Workload | AI-agent conversations are written to Cosmos DB. Fabric Mirroring replicates those records into the Lakehouse in near-real-time, where 04_cosmos_mirroring_transform processes them into gold_agent_analytics. |
| Observability Ingestion | Azure Monitor diagnostic settings export metrics, logs, and cost data to ADLS Gen2. Fabric Lakehouse shortcuts expose those files as if they were local, and the Bronze notebook ingests them into Delta tables. |
Project Structure
fabric-control-tower/
├── .github/
│ └── workflows/
│ └── deploy.yml # CI/CD pipeline
├── infra/
│ ├── main.bicep # Bicep entry point (storage, identity)
│ └── main.parameters.json # Default parameters
├── fabric/
│ ├── notebooks/
│ │ ├── 01_bronze_ingestion.ipynb
│ │ ├── 02_silver_transformation.ipynb
│ │ ├── 03_gold_aggregation.ipynb
│ │ └── 04_cosmos_mirroring_transform.ipynb
│ └── pipelines/
│ ├── pipeline_load_e2e.json
│ └── pipeline_daily_refresh.json
├── src/
│ └── setup/
│ ├── requirements.txt
│ ├── semantic_model.json # Direct Lake semantic model definition
│ ├── setup_fabric_workspace.py
│ └── setup_cosmos_mirroring.py
├── .gitignore
├── azure.yaml # azd manifest
└── README.md
Contributing
- Fork the repository and create a feature branch from
main. - Follow existing code style — run
ruff checkandruff formatbefore committing. - Add or update tests for any new setup scripts.
- Open a pull request with a clear description of your changes.
- Ensure the CI pipeline passes before requesting review.
License
This project is licensed under the MIT License.