This jumpstart deploys a Fabric capacity observability stack into your workspace β a one-cell setup notebook that subscribes every capacity you administer to the Fabric Capacity Events feed, an Eventstream that funnels those events into an Eventhouse-backed KQL database with three pre-built parsing functions and update policies, and a multi-page real-time KQL Dashboard that visualizes capacity utilization, throttling thresholds, overage, workload mix, and capacity state changes β all installed with one call.
β±οΈ Deploy time: ~2 minutes. Plan another ~5 minutes to run the setup notebook, watch the first events land, and open the dashboard.
What Gets Deployed
| Item | Type | Role |
|---|---|---|
Capacity Events Update Eventstream | Notebook | One-cell bootstrap. Pip-installs fabric-deployment-tool, then calls FabDeploymentTool().update_capcity_events_eventstream(workspace_name) to subscribe every Fabric capacity where the executing user is an Administrator to the CapacityEvents Eventstream's Capacity CustomEndpoint. |
Capacity Events Update Eventstream | DataPipeline | Wraps the setup notebook in a single TridentNotebook activity named Update Eventstream. Ships with a disabled daily schedule at 01:00 UTC β enable it if you want the capacity subscription to refresh automatically as admin assignments change. |
CapacityEvents | Eventstream | Source: a CustomEndpoint named Capacity that the setup notebook subscribes capacities to. Two destinations: CustomOutput (a CustomEndpoint for downstream consumers) and Eventhouse via DirectIngestion into the CapacityEventsRaw table using the CapacityEventsRaw_mapping JSON mapping. Stream properties: eventThroughputLevel: Low, retentionTimeInDays: 1 β sized for steady-state low-volume capacity events. |
Fabric Platform Monitoring | Eventhouse | Container for the KQL database below. The Eventhouse itself ships with default properties (EventhouseProperties.json is {}); per-database OneLake caching/storage on Capacity Utilization is P365000D (effectively unbounded) β actual aging is governed by the per-table retention policies described below. |
Capacity Utilization | KQLDatabase | All capacity telemetry lives here. Raw events land in CapacityEventsRaw; three update policies fan them out into typed tables. See "How It Works" below for the schema. |
Capacity Monitoring | KQLDashboard | Two-page real-time KQL Dashboard (auto-refresh every 30s) β Capacity Summary for the fleet-wide overview and Capacity Details for per-capacity drill-through. |
How It Works
Setup β subscribing your capacities to the Eventstream
The setup notebook is the entry point. It runs two cells:
%pip install fabric-deployment-tool --quiet.- Resolves the current workspace name via
sempy.fabric.get_notebook_workspace_id()andfabric.list_workspaces(...), then callsFabDeploymentTool().update_capcity_events_eventstream(workspace_name).
That single call discovers every Fabric capacity where the executing user is a Capacity Administrator, then reconfigures the CapacityEvents Eventstream's Capacity CustomEndpoint to subscribe to events for exactly that set β adding new capacities and removing any the user no longer administers.
Scheduling refresh with the pipeline
Capacity Events Update Eventstream (DataPipeline) wraps the notebook in a single TridentNotebook activity called Update Eventstream. The shipped .schedules config defines a daily 01:00 UTC trigger that is disabled by default β enable it once you've decided which identity should own ongoing capacity discovery. Once enabled, every admin reassignment is picked up within 24 hours without any manual edit.
Ingest β Eventstream to Eventhouse
CapacityEvents has:
- Source β one
CustomEndpointnamedCapacity. The Fabric Capacity Events service emits CloudEvents (Microsoft.Fabric.Capacity.Summary,Microsoft.Fabric.Capacity.State) for each subscribed capacity. - Destinations β
CustomOutput(aCustomEndpoint, in case you want to fan out to another consumer) andEventhousewithdataIngestionMode: DirectIngestion, writing toCapacityEventsRawusing theCapacityEventsRaw_mappingJSON mapping.
Every capacity event lands in CapacityEventsRaw within seconds, durably stored and KQL-queryable from the Capacity Utilization database.
Parse β raw events become typed, queryable tables
Capacity Utilization's DatabaseSchema.kql defines four tables and three parsing functions. The raw table has a short, hot retention; the parsed tables are tuned for two years of analytics.
| Table | What's in it | Retention | Hot cache |
|---|---|---|---|
CapacityEventsRaw | The raw CloudEvent envelope β specversion, source, time, id, subject, dataschemaversion, type, and a dynamic data payload. Folder Raw. | 1 hour | 1 day |
CapacitySummary | Typed projection of Microsoft.Fabric.Capacity.Summary events β base/timepoint CU, CU-ms and CU-seconds, interactive/background utilization, preview utilization, overage CU-ms (total / added / burndown / billing limit), throttling thresholds (interactive delay, interactive reject, background reject), and the capacityUnitUtilizationBreakdown payload. | 730 days | 90 days |
CapacityState | Typed projection of Microsoft.Fabric.Capacity.State events β transitionTime, capacityState, stateChangeReason. | 730 days | 90 days |
CapacityWorkloadSummary | mv-expanded workload-level breakdown extracted from the capacityUnitUtilizationBreakdown payload on summary events β workloadKind, interactiveCU, backgroundCU, interactivePreviewCU, backgroundPreviewCU per workload. | (uses database default) | (uses database default) |
The three parse functions live in the UpdatePolicyFunctions folder and are bound as transactional update policies on the three destination tables (CapacitySummary, CapacityState, CapacityWorkloadSummary), each with CapacityEventsRaw as the source:
parse_CapacityEventsSummary()β filterstype == "Microsoft.Fabric.Capacity.Summary", projects typed columns, and derivestimepointCapacityUnits = baseCapacityUnits * 30andcapacityUnitSecond = capacityUnitMs / 1000.0.parse_CapacityEventsState()β filterstype == "Microsoft.Fabric.Capacity.State"and projects the state-transition fields.parse_CapacityEventsWorkloadSummary()β filters summary events that have a non-emptycapacityUnitUtilizationBreakdown, thenmv-expands the per-workload utilization rows.
The result: anything you write into CapacityEventsRaw from the Eventstream is automatically and transactionally fanned out into the three typed tables β no orchestration needed.
Consume β the Capacity Monitoring dashboard
Capacity Monitoring is a two-page KQL Dashboard with auto-refresh every 30 seconds, sourced from the Capacity Utilization database.
Capacity Summaryβ fleet-wide view. Tiles:Capacities(count card),Capacity Overview(table with drill-through to per-capacity pages), andCapacity State.Capacity Detailsβ per-capacity drill-through. Tiles:Total CU in Time Range by Utilization Type,Utilization Type Distribution,Capacity Utilization,Overage,% Capacity Utilization (Current),Throttling Threshold,Capacity State(also appears here),Workspaces With Activity,Workload Breakdown,% Interactive Delay Threshold,% Interactive Reject Threshold,% Background Reject Threshold, andNΒΊ Workloads.
The dashboard exposes parameters for Capacity Sku, Capacity, Workspace Name Search, Workspace Name Exact (Limit 1000), Item, and Time range, with Capacity Id flowing through cross-filters and drill-through pairs.
Try It β A Five-Minute Walkthrough
- Install β
jumpstart.install("fpm-capacity-events")and wait for the ~2-minute deploy. - Bootstrap β open
Capacity Events Update Eventstream(the notebook) and run all cells. Make sure you're signed in as a Capacity Administrator on at least one capacity, otherwise the subscription will be empty. - Wait for ingestion β within a minute or two,
CapacityEventsRawshould start populating. OpenCapacity Utilizationand runCapacityEventsRaw | take 10andCapacitySummary | take 10to confirm raw events and typed projections. - Open the dashboard β launch
Capacity Monitoring, land on theCapacity Summarypage, and pick a capacity. Click into a row to drill through toCapacity Details. - Schedule the refresh (optional) β open the
Capacity Events Update Eventstreampipeline and enable the daily 01:00 UTC schedule so the capacity subscription tracks admin changes automatically.
Extending the Accelerator
| Extension | How |
|---|---|
| Track admin reassignments automatically | Enable the disabled daily schedule on Capacity Events Update Eventstream (pipeline). The pipeline executes the notebook under the pipeline owner's identity, so make sure that identity is a Capacity Administrator on the capacities you want to monitor. |
| Fan out to another consumer | The Eventstream already exposes a CustomOutput (CustomEndpoint) destination β point Reflex, Spark structured streaming, or any other consumer at that endpoint without touching the Eventhouse path. |
| Alert on capacity throttling | Add an Activator (Reflex) on a KQL query against CapacitySummary that fires when utilizationInteractive, utilizationBackground, or processedOverageCapacityUnitsMs cross a threshold β or against CapacityState for state-change notifications. |
| Re-parse history | The raw table only retains 1 hour by default. To re-parse historical events lower the SoftDeletePeriod on CapacityEventsRaw before ingestion, or replay from the CustomOutput endpoint into a side table. |
| Add per-workload chargeback views | Build a Power BI semantic model or KQL queryset over CapacityWorkloadSummary β it already breaks down interactiveCU / backgroundCU per workloadKind, which is the unit of chargeback most teams want. |
| Increase event throughput | The Eventstream is provisioned with eventThroughputLevel: Low. If you subscribe many capacities or emit higher-volume custom events, bump it via the Eventstream settings. |
Cost Notes
The setup notebook and pipeline cost almost nothing β they only run when triggered, and the pipeline schedule ships disabled. The KQL Dashboard's auto-refresh is the second cost item to watch: every 30 seconds it re-runs every visible tile's KQL against the database.
Requirements
- A Microsoft Fabric workspace with at least F2 capacity (Eventhouse + Real-Time Dashboard need it).
- The user running the setup notebook (and the identity owning the pipeline, if scheduled) must be a Capacity Administrator on every capacity you want to monitor β there is no manual capacity list.
- Permissions to create Eventstream, Eventhouse, KQL Database, KQL Dashboard, Notebook, and Data Pipeline items.
- Outbound internet from the notebook session β it pip-installs
fabric-deployment-toolon each run.