Coach Guide — Challenge 2: Build the Telemetry Landing Zone
Attendee challenge:
challenges/challenge-02-landing-zone.md
Snapshot
| Est. time | 1.5–2 h |
| Difficulty | ⭐⭐ (200) |
| They build | ADLS Gen2 landing zone for cost, metrics, logs, metadata, and diagnostics |
| Key services | ADLS Gen2, Azure Cost Management, Resource Graph, Log Analytics data export, Diagnostic Settings |
Coaching objectives
This challenge turns scattered Azure signals into a single landing zone that Fabric can read with OneLake shortcuts. Keep teams focused on the outcome: five domains landing in storage with enough proof that Challenge 3 can shortcut to them.
What good looks like: the team shows the five containers, validates FOCUS and Resource Graph Parquet, confirms the Log Analytics export rule, applies diagnostic settings to supported resources, and records the storage account name, resource ID, and DFS endpoint.
The reference path
Deploy the ingestion asset:
cd resources/observability-ingestion
azd auth login
azd up # env name, region (same as Challenge 0), subscription
azd up provisions ADLS Gen2 storage, five containers, Log Analytics workspace + data export rule,
Cost Management FOCUS export, Key Vault, and a user-assigned managed identity. Capture outputs:
azd env get-values
Install script dependencies:
cd resources/observability-ingestion/src/scripts
pip install -r requirements.txt
Preview diagnostic settings:
python setup_diagnostic_settings.py \
--subscription-id <SUBSCRIPTION_ID> \
--workspace-id <WORKSPACE_RESOURCE_ID> \
--storage-account-id <STORAGE_ACCOUNT_RESOURCE_ID> \
--dry-run
Apply diagnostic settings:
python setup_diagnostic_settings.py \
--subscription-id <SUBSCRIPTION_ID> \
--workspace-id <WORKSPACE_RESOURCE_ID> \
--storage-account-id <STORAGE_ACCOUNT_RESOURCE_ID>
Run Resource Graph export:
python resource_graph_export.py \
--subscription-id <SUBSCRIPTION_ID> \
--storage-account <STORAGE_ACCOUNT_NAME> \
--container metadata
Trigger the Cost Management export. The current Azure CLI costmanagement export group may not expose
a run command, so use the ARM action directly:
EXPORT_NAME=export-<env-name>-focus-daily
SCOPE="/subscriptions/<SUBSCRIPTION_ID>"
az rest --method post \
--url "https://management.azure.com${SCOPE}/providers/Microsoft.CostManagement/exports/${EXPORT_NAME}/run?api-version=2023-11-01"
Check export execution history:
az costmanagement export show \
--name "$EXPORT_NAME" \
--scope "$SCOPE"
Validate the landing zone:
python validate_exports.py \
--storage-account <STORAGE_ACCOUNT_NAME>
Checkpoint verification
Ask the team to show:
- Storage account with hierarchical namespace enabled and containers:
costs,metrics,logs,metadata,diagnostics. - FOCUS cost Parquet under
costs/focus/...after trigger/wait. - Resource Graph Parquet under
metadata/resource-graph/year=*/month=*/day=*/. - Log Analytics data export enabled for
AppRequests,AppDependencies,AppTraces,AppExceptions, andAppMetrics. - Diagnostic settings created on supported resources; unsupported types skipped gracefully.
validate_exports.pyoutput with file counts, sizes, latest timestamps, and sample schemas.- Recorded Fabric coordinates:
- storage account name
- storage account resource ID
https://<storage-account>.dfs.core.windows.net
✅ Pass when the storage landing zone is validated and the team can explain how Challenge 3 will shortcut to it.
Common pitfalls & fixes
| Pitfall | Fix |
|---|---|
| Missing Cost Management Reader | Grant at the billing/subscription scope; Contributor on the resource group is not enough for cost exports |
costs container empty |
Cost export is daily; trigger it manually with the ARM run action and wait for execution to complete |
| Cost export name unknown | It is export-<environmentName>-focus-daily from infra/main.bicep; confirm with az costmanagement export list --scope /subscriptions/<id> |
| Expecting Log Analytics export to backfill | Data export is continuous from enablement forward; generate Challenge 1 traffic after enabling it |
| Assuming data export requires a dedicated cluster | It does not for this reference path; verify the rule is enabled and treat it as continuous export |
| Diagnostic settings fail on some resources | Normal. The script skips known unsupported types and logs warnings for resources without categories |
| Storage access denied from scripts | Ensure the caller/identity has Storage Blob Data Contributor on the storage account or resource group |
| No metrics/log files yet | Confirm the data export rule is enabled, traffic exists in the workspace, and allow time for export latency |
Talking points (mini-briefing)
- FOCUS = FinOps lingua franca. It standardizes cost fields so spend can be joined to tags, resources, services, and agent namespaces.
- One landing zone beats five silos. Cost, logs, metrics, metadata, and diagnostics become queryable together instead of trapped in separate portals.
- Date partitions are Spark fuel. The storage layout is already shaped for Fabric notebooks and medallion processing.
- Continuous vs batch matters. Log Analytics and diagnostics stream continuously; cost and Resource Graph are scheduled/triggered snapshots.
- This is Challenge 3's shortcut target. The storage DFS endpoint is the bridge into OneLake with no data copy.
If they finish early
- Add tags (
team,agent,environment,costCenter) to Challenge 1 resources, rerun Resource Graph export, and prove tags appear in Parquet. - Generate more agent traffic and watch the
metrics/logscontainers grow. - Compare
ResourceIdin FOCUS withidin Resource Graph and sketch the futuredim_resourcejoin. - Review
docs/architecture.mdGold tables and map which raw container feeds each one.
Reference assets
resources/observability-ingestion/README.md— deployment, data layout, script usageresources/observability-ingestion/infra/main.bicep— outputs and resource namingresources/observability-ingestion/infra/modules/storage.bicep— five containers and ADLS Gen2 settingsresources/observability-ingestion/infra/modules/monitoring.bicep— Log Analytics data export tablesresources/observability-ingestion/infra/modules/cost-export.bicep— FOCUS Parquet exportresources/observability-ingestion/src/scripts/— Resource Graph, diagnostic settings, validationdocs/architecture.md— Ingest stage and Gold data products