Skip to content

App Insights Workbook Export

ContributorsMyles Henaghan

Contributors 🕹️ Myles Henaghan

When to use: Export Application Insights values deterministically when the user needs either a known-default payload, an explicit KQL payload, or workbook-derived query execution with reliable subscription checks and Cloud Shell fallback.

Tested on: Azure Cloud Shell and the Azure REST API (ARM query path) only. Not yet tested with a locally installed Azure CLI (az) — treat local runs as unverified.

Instructions

Intent

Use this skill to collect reproducible telemetry outputs from Application Insights when local environments can be unreliable, permissions vary by subscription, or workbook definitions differ between environments.

Cloud Shell validation note: in this environment, direct az monitor app-insights query frequently requires a data-plane audience token (https://api.applicationinsights.io) that may not be available to the default Cloud Shell credential. The script now auto-falls back to ARM query execution when this occurs.

Windows/Git Bash validation note: if running from Git Bash on Windows, resource IDs beginning with /subscriptions/... can be path-converted unless MSYS_NO_PATHCONV=1 is set. The script examples below include the safe invocation.

Subscription confirmation first (Cloud Shell and local)

Before running any example command, select the intended Azure account context:

az account list --output table
az account set --subscription dev-subscription
az account show --query "{name:name,id:id,isDefault:isDefault}" --output table

If you need a different subscription, replace dev-subscription explicitly.

Deterministic collection flow

flowchart TB
  A[Parse explicit flags] --> B[Azure CLI preflight]
  B --> C{Subscription queryable?}
  C -- No --> D[Stop with Cloud Shell fallback steps]
  C -- Yes --> E[Resolve appId from component]
  E --> F[Probe minimal query]
  F --> G{Mode}
  G -- default-query --> H[Run built-in Apdex payload]
  G -- custom-query --> I[Run caller-provided KQL]
  G -- workbook-query --> J[Extract KQL from saved workbook]
  H --> K[Return deterministic output]
  I --> K
  J --> K

Modes to use

Mode Use when Required options
default-query Need a baseline, controlled payload and cannot save workbook changes --component-id (use --subscription explicitly for deterministic environment control)
custom-query Query is provided by caller --component-id, one of --query-text or --query-file (use --subscription explicitly for deterministic environment control)
workbook-query Workbook is already configured and should define the payload --component-id, one of --workbook-id or --workbook-name (use --subscription explicitly for deterministic environment control)

Script path

Run script from:

  • library/skills/collect-app-insights-azure/scripts/collect-app-insights.sh
  • library/skills/collect-app-insights-azure/scripts/check-role-health.sh — cross-environment cloud_RoleName health check (see below)

Local execution prerequisites

  • Required CLIs: az and jq
  • Recommended: run from Cloud Shell for cleanest dependency/runtime parity
  • Local Windows option: run via Git Bash

Quick checks:

az account show --output table
jq --version

If jq is missing on Windows:

winget install --id jqlang.jq -e --accept-source-agreements --accept-package-agreements

Windows-safe Git Bash invocation

Use this wrapper when running locally on Windows to avoid /subscriptions/... path conversion:

& "C:\Program Files\Git\bin\bash.exe" -lc '
  export MSYS_NO_PATHCONV=1
  cd "/c/<repo-root>"
  bash ./library/skills/collect-app-insights-azure/scripts/collect-app-insights.sh \
    --subscription <subscription-name-or-id> \
    --component-id /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Insights/components/<app-insights-name> \
    --mode default-query \
    --timespan P30D
'

Minimum required identifiers

  • Component ID: full Application Insights resource ID
  • Workbook ID for strict workbook mode, or workbook display name for lookup

Subscription can be supplied explicitly with --subscription (recommended), or inherited from script defaults/environment.

The portal blade URL ending in /components/<app-id>/workbooks is not itself a saved workbook resource ID. Use --workbook-id for deterministic selection, or --workbook-name for a lookup scoped by sourceId and display name.

Command examples

Baseline deterministic payload:

bash library/skills/collect-app-insights-azure/scripts/collect-app-insights.sh \
  --subscription dev-subscription \
  --component-id /subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/rg-dev/providers/Microsoft.Insights/components/appi-dev \
  --mode default-query \
  --timespan P30D \
  --apdex-threshold-ms 3000 \
  --operation-types pageViews,requests,dependencies \
  --output-format json \
  --output-file apdex.json

Force ARM execution mode (useful when az monitor app-insights query is unavailable locally):

bash library/skills/collect-app-insights-azure/scripts/collect-app-insights.sh \
  --subscription <subscription-name-or-id> \
  --component-id /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Insights/components/<app-insights-name> \
  --mode default-query \
  --query-exec-mode arm \
  --timespan P30D \
  --output-format json

Starter template for permission-constrained contexts (send explicit query with execution):

bash library/skills/collect-app-insights-azure/scripts/collect-app-insights.sh \
  --subscription dev-subscription \
  --component-id /subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/rg-dev/providers/Microsoft.Insights/components/appi-dev \
  --mode custom-query \
  --timespan P30D \
  --query-text "requests | where timestamp > ago(30d) | summarize Total=count(), Successes=countif(tobool(success)), Failures=countif(not(tobool(success)))"

Caller-provided query payload:

bash library/skills/collect-app-insights-azure/scripts/collect-app-insights.sh \
  --subscription dev-subscription \
  --component-id /subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/rg-dev/providers/Microsoft.Insights/components/appi-dev \
  --mode custom-query \
  --query-file ./query.kql \
  --timespan P7D

Workbook-derived query execution (when a workbook is already saved and trusted):

bash library/skills/collect-app-insights-azure/scripts/collect-app-insights.sh \
  --subscription dev-subscription \
  --component-id /subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/rg-dev/providers/Microsoft.Insights/components/appi-dev \
  --mode workbook-query \
  --workbook-name "App Performance Index (Apdex)" \
  --workbook-item-title "Apdex Score" \
  --timespan P30D

Cloud Shell fallback policy

If any of the following checks fail locally, stop and move to Cloud Shell:

  • az not installed
  • jq not installed
  • az account show fails
  • az account set --subscription ... fails
  • subscription read probe fails
  • App Insights query probe fails

Cloud Shell run path:

  1. Open Azure Portal and start Cloud Shell.
  2. Upload script via Manage files.
  3. Confirm account context with az account list --output table.
  4. Set account context with az account set --subscription dev-subscription.
  5. Run the same command with explicit flags.

Output behavior

  • Use --output-format json for table payloads.
  • Use --output-format value to return a scalar cell; when an Apdex column exists, the script prefers that value.
  • Use --output-file - for stdout (default) or a file path for reproducible artifacts.

Interpreting output quickly

  • Watch console summary lines first: table count, row count, and the Result summary block.
  • If Result summary includes Apdex, use that value as the 30-day score for the selected operation types.
  • Keep full payload output in a file for auditability (for example, apdex-30d.json).

Validated example artifact from Cloud Shell dev run:

  • references/example-apdex-30d.json

Cross-environment role health check

Use scripts/check-role-health.sh when the question is "is this app healthy right now in dev, test and prod?" rather than "give me this one metric". It resolves each environment from references/environments.json, delegates execution to collect-app-insights.sh (so the CLI/ARM fallback is shared), and folds requests, dependencies, exceptions and traces into one verdict per environment.

Environment config

references/environments.json maps a friendly environment name to a subscription and App Insights component ID. The file in this skill is a placeholder — replace the subscription names and component IDs before a real run:

{ "environments": [ { "name": "dev", "subscription": "dev-subscription", "componentId": "/subscriptions/.../components/..." } ] }

Point at a different portfolio with --config <path>.

Interactive wizard

Run with no flags on a terminal and the script prompts for scope using the bash select builtin:

  1. Environment menu — each configured environment plus all.
  2. Window menu — 1h / 3h / 12h / 24h / 3d / 7d / 30d or a custom ISO-8601 duration. Enter accepts the default of the last 3 hours.
  3. Role menu — unique cloud_RoleName values actually observed in the chosen window, aggregated across the selected environments and sorted by signal volume. Accepts a single number, a comma-separated list (1,3), or all.
bash library/skills/collect-app-insights-azure/scripts/check-role-health.sh

Pass --env, --timespan and/or --role to skip the matching prompt. --role takes a comma-separated list and is repeatable. Prompts auto-disable when stdout/stderr are not a TTY; force with --interactive or suppress with --non-interactive (which falls back to --env all and the PT3H default window).

Non-interactive examples

# All three environments, last 30 hours
bash library/skills/collect-app-insights-azure/scripts/check-role-health.sh \
  --role pricing-engine --env all --timespan PT30H

# Several roles at once, results grouped per environment then per role
bash library/skills/collect-app-insights-azure/scripts/check-role-health.sh \
  --role pricing-engine,report-builder --env dev,test --timespan PT12H

# Subset, machine-readable
bash library/skills/collect-app-insights-azure/scripts/check-role-health.sh \
  --role pricing-engine --env dev,prod --output-format json --output-file role-health.json

# Discover role names only
bash library/skills/collect-app-insights-azure/scripts/check-role-health.sh \
  --list-roles --env all --timespan P7D

# Gate on freshness as well as errors
bash library/skills/collect-app-insights-azure/scripts/check-role-health.sh \
  --role pricing-engine --env prod --max-staleness-minutes 60 --error-rate-threshold 0.02

Status model

Status Icon Meaning
healthy ✅ Signals present and error rate at or below --error-rate-threshold (default 0.05)
degraded ❌ Error rate above threshold
no-data ❓ No signals for the role in the timespan
stale 🕒 Newest signal older than --max-staleness-minutes (disabled by default)
error ⛔ Collection failed for that environment; re-run with --verbose

Error rate is errors / total summed across all four signals for that role, where errors are failed requests, failed dependencies, every exception, and traces with severityLevel >= 3. Each environment takes the worst status of its roles, and the overall status takes the worst of the environments.

Icons render on a TTY and fall back to ASCII labels when piped; override with --icons / --no-icons. LAST SEEN is paired with a relative AGE column, and blocks are blank-line separated per environment/role.

Exit codes: 0 all healthy, 1 anything not healthy, 2 usage or config error — so the script drops straight into a pipeline gate.


References

  • references/workbook-discovery.md — workbook ID discovery patterns and caveats
  • references/environments.json — dev/test/prod App Insights components used by the role health check

Troubleshooting

Symptom Cause Action
Missing command: az Azure CLI not available locally Run in Cloud Shell or install Azure CLI
Missing command: jq jq not available locally Install jq (for example via winget on Windows) or run in Cloud Shell
Cannot set subscription Wrong subscription value or insufficient access Verify with az account list --output table, then retry
/subscriptions/... becomes C:/Program Files/Git/subscriptions/... Git Bash path conversion on Windows Run with MSYS_NO_PATHCONV=1 before invoking script
unrecognized arguments: --timespan Extension version expects --offset/--start-time/--end-time instead Use latest script; it auto-detects supported query time flags
'app-insights' is misspelled or not recognized by the system Local Azure CLI lacks app-insights query command group Use latest script; it auto-falls back to ARM query execution (or force --query-exec-mode arm)
not a supported MSI token audience Cloud Shell credential cannot get App Insights data-plane token Use latest script; it auto-falls back to ARM query execution
Workbook query extraction returns empty Item title not matched or workbook has no KQL tile Use --workbook-item-title or switch to custom-query
Query returns empty table Time range or filter too restrictive Expand --timespan and test with requests | take 1
Output not machine-readable Wrong output mode selected Use --output-format json for deterministic parsing