Monitoring workbook
The Foundation Health workbook is a starter Azure Monitor workbook that ships with the foundation. It deploys into the monitoring resource group and is scoped to the foundation Log Analytics workspace.
Itâs opt-in and off by default â the workbook resource itself is free, but the queries inside it run against your LAW data. That data is already paid for by the foundation, but the workbook may surface ingestion you didnât realise you had.
TL;DR. Set
workbook_enabled = true(Terraform) orworkbookEnabled = true(Bicep), redeploy, then open Azure Monitor â Workbooks â Foundation Health in the portal. Works in bothsingleandmultideployment modes (it lands in the management sub in multi-sub mode).
Where it lands
flowchart LR
subgraph MgmtSub["Management subscription<br/>(or single sub if mode=single)"]
RG["rg-monitor-<prefix>-<region>"]
LAW["Log Analytics workspace"]
WB["Workbook<br/>'Foundation Health'<br/>kind: shared"]
RG --- LAW
RG --- WB
WB -- "queries" --> LAW
end
Foundation["foundation resources<br/>(firewall, KV, RSV, ...)"]
Foundation -- "diagnostic settings" --> LAW
In multi mode, the workbook lands in the management sub â the same sub the LAW lives in. The workbook can only query the LAW it was deployed against, so co-location is required.
What it deploys
One Microsoft.Insights/workbooks resource (kind: shared) in rg-monitor-<prefix>-<region>, with four tabs and a TimeRange parameter at the top that lets you pivot from 1h to 7d.
| Tab | KQL source | Empty when⌠| What to look for |
|---|---|---|---|
| Workspace ingestion | Usage table grouped by DataType | Brand-new LAW (give it ~15 min) | Which diagnostic settings are actually emitting GB/day |
| Firewall denies | AZFWNetworkRule where Action == "Deny" | baseline / vpn (no firewall) | Top denied src/dst â usually misconfigured app rules |
| Key Vault operations | AzureDiagnostics filtered to MICROSOFT.KEYVAULT | KV diag setting wasnât auto-applied (rare) | Last 50 ops with caller â useful for audit + RCA |
| Backup job status | AddonAzureBackupJobs summarised by JobStatus | No backup item is being protected yet | Job success rate over the time window |
Why opt-in?
Two reasons:
- Doesnât fit every team. Some shops bring their own workbooks, Grafana, or Datadog. We donât want to leave behind orphaned Azure resources for those teams.
- Editable starter, not a finished product. This is intentionally minimal â itâs meant to be cloned and extended, not used as-is.
Enable it
Terraform
Whether youâre in single or multi mode, the toggle is the same:
# wizard.auto.tfvars (or terraform.tfvars)workbook_enabled = trueThen terraform apply. The output workbook_id will be populated with the new workbookâs resource ID.
Bicep
// scenarios/<your>.bicepparamparam workbookEnabled = trueThen az deployment sub create --parameters scenarios/<your>.bicepparam. The output workbookId will be populated.
Multi-sub Bicep
The workbook is part of the management layer template, so flip the param in scenarios/management.bicepparam and re-run only the management step of scripts/deploy-multi-sub.sh â or re-run the whole wrapper (itâs idempotent, the connectivity and landing-zone passes will be no-ops):
./scripts/deploy-multi-sub.sh \ --connectivity-sub $CONN_SUB \ --management-sub $MGMT_SUB \ --landingzone-sub $LZ_SUB \ --scenario full \ --name-prefix contoso \ --region westcentralus \ --region-short wcusEditing the workbook content
The workbook content is two JSON files (one for each IaC tree) â keep them in sync if you edit one:
infra/terraform/foundation/workbooks/foundation-health.workbook.jsoninfra/bicep/foundation/workbooks/foundation-health.workbook.json
The easiest workflow:
- Open the deployed workbook in the Azure portal.
- Edit visually until you like it.
- Click Advanced editor (
</>icon) â copy the JSON. - Paste into both
foundation-health.workbook.jsonfiles. - Commit. Next
terraform apply/az deployment sub createwill diff-update the deployed workbook.
Resource name is a GUID. The workbookâs
nameis a deterministic GUID derived from your naming suffix (Terraform:uuidv5("dns", "azure-launchpad-workbook-<suffix>"); Bicep:guid('azure-launchpad-workbook', suffix)). The display name (Foundation Health) is what you see in the portal â the GUID is just the resource ID, so editing in the portal wonât create a duplicate on the next deploy.
Suggested extensions
Common additions teams reach for once theyâve enabled the starter:
| Add a tab for⌠| KQL starting point |
|---|---|
| Firewall app rule hits | AZFWApplicationRule | summarize count() by Fqdn, Action |
| NSG flow log denies | AzureNetworkAnalytics_CL | where SubType_s == "FlowLog" and FlowStatus_s == "D" |
| Heartbeat misses | Heartbeat | summarize LastSeen=max(TimeGenerated) by Computer | where LastSeen < ago(15m) |
| Sign-in failures (Entra) | SigninLogs | where ResultType != 0 (requires Entra â LAW diagnostic setting; not deployed here) |
| Cost anomaly | AzureActivity | where OperationNameValue startswith "MICROSOFT.CONSUMPTION/BUDGETS" |
The repo only ships the four core tabs to keep the starter readable. Add tabs in the portal, then export.
Validation
cd infra/terraform/foundationterraform test -filter=tests/workbook.tftest.hcl# Success! 2 passed, 0 failed.The plan-mode tests cover the disabled-by-default and enabled paths without needing Azure auth, and run as part of the standard CI matrix.
Troubleshooting
Workbook doesnât appear in Azure Monitor â Workbooks
It does deploy as kind: shared (visible to anyone with Reader on the RG). Check Workbooks â Browse â Subscription filter â the workbook lives in the management sub in multi-sub mode, not the connectivity or landing-zone sub.
Tabs are empty
Most often the diagnostic settings on the source resources didnât take. Verify with:
az monitor diagnostic-settings list --resource <resource-id> -o tableThe foundation auto-creates a diagnostic setting on every relevant resource (firewall, KV, RSV, NAT GW) pointing at the LAW resource ID. If that shows nothing, the resource hasnât been redeployed since you enabled the diagnostic settings â terraform apply again.
âFailed to resolve workspaceâ on a tab
The hardcoded LAW reference in the workbook JSON points at a different LAW than the one in your deploy. The workbook content uses a {Workspace} parameter so this shouldnât happen, but if you imported a hand-edited workbook, check the parameters section of the JSON for a baked-in workspace ID and replace it with {Workspace}.
Removal
Set workbook_enabled = false (or workbookEnabled = false) and re-apply. The workbook resource will be deleted; the LAW it queried is untouched.