Workbooks and Dashboards¶
Azure Monitor workbooks provide parameterized operational analysis, while Azure dashboards provide at-a-glance status views for shared audiences. This runbook focuses on maintaining both assets as reusable, versioned operational artifacts.
flowchart TD
Data[Metrics and logs] --> Workbook[Azure Monitor workbook]
Workbook --> Query[KQL and metric visuals]
Workbook --> Dashboard[Azure dashboard pinning or summary]
Dashboard --> NOC[Operations viewers]
Workbook --> Ops[Investigators] Prerequisites¶
- Azure CLI authenticated with
az login. - A Log Analytics workspace with queryable data.
- Workbook JSON or serialized content stored in source control.
- If dashboards are used, a dashboard definition JSON file available for deployment.
- Permissions:
Workbook Contributorfor workbook changes.Contributoron the resource group for portal dashboard changes.
- Variables used below:
RG="rg-monitoring-prod" WORKBOOK_NAME="wb-ops-health-report" WORKBOOK_DISPLAY_NAME="Operations Health Report" WORKBOOK_FILE="./docs/examples/workbook-ops-health-report.json" DASHBOARD_NAME="dashboard-monitoring-overview" DASHBOARD_FILE="./docs/examples/dashboard-monitoring-overview.json" LOCATION="eastus"
When to Use¶
- You need a reusable operational view for incident triage.
- A workbook query or parameter set needs an update after schema changes.
- A NOC dashboard must be standardized across subscriptions.
- Visual content drifted from the version-controlled baseline.
- A workbook needs to be verified after alert or DCR changes.
- A central team needs the same monitoring view deployed across environments.
Procedure¶
Step 1: Inventory existing workbooks and dashboards¶
Check what already exists before you create a duplicate artifact.
az monitor workbook list \
--resource-group $RG \
--query "[].{name:name,displayName:displayName,location:location,kind:kind}" \
--output table
Name DisplayName Location Kind
--------------------- ------------------------- ---------- ------------------
wb-ops-health-report Operations Health Report eastus shared
az portal dashboard list \
--resource-group $RG \
--query "[].{name:name,location:location,tags:tags}" \
--output table
Name Location Tags
------------------------------ ---------- --------------------------------
dashboard-monitoring-overview eastus {'owner':'monitoring','tier':'ops'}
Step 2: Create or update the workbook from a checked-in file¶
Use a versioned source file rather than editing only in the portal.
az monitor workbook create \
--name $WORKBOOK_NAME \
--resource-group $RG \
--location $LOCATION \
--display-name "$WORKBOOK_DISPLAY_NAME" \
--kind shared \
--serialized-data @$WORKBOOK_FILE \
--output json
{
"displayName": "Operations Health Report",
"kind": "shared",
"location": "eastus",
"name": "wb-ops-health-report",
"provisioningState": "Succeeded"
}
az monitor workbook update \
--name $WORKBOOK_NAME \
--resource-group $RG \
--serialized-data @$WORKBOOK_FILE \
--output json
{
"displayName": "Operations Health Report",
"name": "wb-ops-health-report",
"revision": "1d2f7d4c-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
Step 3: Read back workbook metadata and serialized content¶
Confirm that the workbook saved as a shared resource and still contains the expected definition.
az monitor workbook show \
--name $WORKBOOK_NAME \
--resource-group $RG \
--query "{name:name,displayName:displayName,kind:kind,location:location,version:version}" \
--output json
{
"displayName": "Operations Health Report",
"kind": "shared",
"location": "eastus",
"name": "wb-ops-health-report",
"version": "Notebook/1.0"
}
Step 4: Create or update the Azure dashboard definition¶
Dashboards are best treated like infrastructure definitions for team-wide operational views.
az portal dashboard create \
--resource-group $RG \
--name $DASHBOARD_NAME \
--location $LOCATION \
--input-path $DASHBOARD_FILE \
--tags owner=monitoring tier=ops \
--output json
{
"location": "eastus",
"name": "dashboard-monitoring-overview",
"provisioningState": "Succeeded",
"tags": {
"owner": "monitoring",
"tier": "ops"
}
}
Step 5: Validate workbook queries and dashboard presence¶
Operational views are only useful if the underlying queries still return data.
az monitor log-analytics query \
--workspace "/subscriptions/<subscription-id>/resourceGroups/rg-monitoring-prod/providers/Microsoft.OperationalInsights/workspaces/law-ops-central" \
--analytics-query "Heartbeat | where TimeGenerated > ago(1h) | summarize ActiveAgents=dcount(Computer)" \
--output table
az portal dashboard show \
--resource-group $RG \
--name $DASHBOARD_NAME \
--query "{name:name,location:location,tags:tags}" \
--output json
{
"location": "eastus",
"name": "dashboard-monitoring-overview",
"tags": {
"owner": "monitoring",
"tier": "ops"
}
}
Verification¶
Verify workbook presence:
az monitor workbook list \
--resource-group $RG \
--query "[].{name:name,displayName:displayName}" \
--output table
Name DisplayName
--------------------- -------------------------
wb-ops-health-report Operations Health Report
az portal dashboard list \
--resource-group $RG \
--query "[].{name:name,location:location}" \
--output table
az monitor workbook show \
--name $WORKBOOK_NAME \
--resource-group $RG \
--query "{name:name,kind:kind,displayName:displayName}" \
--output json
Rollback / Troubleshooting¶
Delete a broken workbook:
Delete a broken dashboard: Common problems: - Workbook loads but visual is empty - Run the underlying KQL manually and validate parameters. - Workbook update fails - Confirm the serialized JSON is valid and not truncated. - Dashboard tiles show authorization errors - Verify viewer access to the underlying resources, not only the dashboard object. - Duplicate assets appear - Standardize naming, tags, and source-controlled definitions. - Dashboard exists in the wrong subscription or resource group - Re-check deployment scope before assuming the JSON definition is broken. - Shared workbook was replaced by a private draft - Re-deploy the shared workbook from source control and confirm thekind value. Automation¶
Treat workbook JSON and dashboard JSON as deployable artifacts.
az monitor workbook list \
--query "[].{name:name,resourceGroup:resourceGroup,displayName:displayName}" \
--output json
See Also¶
- Operations index
- Alert Rule Management
- Workspace Management
- Troubleshooting KQL query packs
- Export and Integration
- Reference KQL quick reference