Monitoring and Observability
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. See the section bibliography for the reference material consulted while preparing these pages. |
Commands on this page are current for Azure CLI 2.90.0 (checked 2026-09-27); re-verify against az version and
the linked reference pages before relying on them in a pipeline. az monitor app-insights component ships in the
application-insights extension, which the CLI installs automatically the first time it is invoked.
Every other page in this section shows how to build one piece of Bookshelf — cae-bookshelf, aks-bookshelf,
afd-bookshelf, pg-bookshelf, and the rest. This page is the one that answers, once all of that exists, "is it
healthy, and what happened at 03:14 this morning": Azure Monitor as the platform that collects metrics and logs
from every one of those resources, a Log Analytics workspace as the place logs land and KQL as the language that
queries them, Application Insights as the application-level view of catalog-api, orders-api and notifier,
and alerts, workbooks, Service Health, Advisor and Network Watcher as the ways that data turns into something a
human or an on-call rotation actually acts on.
Azure Monitor: one platform, two kinds of data
Azure Monitor is not a separate resource to deploy — every Azure resource emits into it by default. It collects two fundamentally different kinds of telemetry:
- Metrics
-
Lightweight, numeric, time-stamped values (CPU percentage, request count, replica count) stored in a time-series database that Azure retains and indexes automatically. Platform metrics exist the moment a resource exists, need no configuration, and are cheap enough to evaluate every minute — which is why metric alerts (below) are the fast, near-real-time alerting path.
- Logs
-
Structured or free-text records (a request trace, a container’s stdout, a resource’s activity log entry) that only reach Azure Monitor once something is configured to send them there — most commonly a diagnostic setting pointing at a Log Analytics workspace. Logs are richer and queryable with KQL, but land with some delay (typically a few minutes) and cost per gigabyte ingested and retained.
A Log Analytics workspace is the Log Analytics query engine plus the storage for every log table sent to it.
Bookshelf uses one workspace, law-bookshelf, as the shared destination for `cae-bookshelf’s and
`aks-bookshelf’s container logs, `afd-bookshelf’s access logs, and the Application Insights component below — consolidating them lets a single KQL query join a request across every layer it passed through.
In the Azure portal
-
Search for Log Analytics workspaces and select Create.
-
On the Basics tab, choose
rg-bookshelf, name the workspacelaw-bookshelf, and pick the region (eastus2in Bookshelf’s examples). -
Leave the default pricing tier (Pay-as-you-go) and retention (30 days) unless a longer retention or a commitment tier is already justified by volume.
-
Select Review + create, then Create.
KQL: querying Bookshelf’s logs
Kusto Query Language (KQL) reads like a pipeline: a table name, then |-separated operators that filter,
project, summarize or join, each acting on the output of the one before it. Every example below can be run from
Logs on law-bookshelf itself, or from the Logs blade of the specific resource (which pre-scopes the query
to that resource).
Container Apps
Where `cae-bookshelf’s console output (`catalog-api’s and `orders-api’s stdout/stderr) and system logs (revision changes, scaling decisions) end up depends on the environment’s logs destination, and each destination writes to differently named tables with different columns:
log-analytics-
The environment streams logs straight to one workspace, with no diagnostic setting involved. They land in the custom-log tables
ContainerAppConsoleLogs_CLandContainerAppSystemLogs_CL, whose columns carry type suffixes (ContainerAppName_s,Log_s). azure-monitor-
Logs are routed by diagnostic settings (below) to a workspace, a storage account, or an event hub. In a workspace they land in the resource-specific tables
ContainerAppConsoleLogsandContainerAppSystemLogs, whose columns have no suffix (ContainerAppName,Log). none-
Nothing is stored; only live log streaming works.
Bookshelf routes every resource through diagnostic settings, so cae-bookshelf uses azure-monitor:
az containerapp env update \
--name cae-bookshelf \
--resource-group "$RG" \
--logs-destination azure-monitor
With that destination and the diagnostic setting below in place, `catalog-api’s recent errors are:
ContainerAppConsoleLogs
| where ContainerAppName == "catalog-api"
| where TimeGenerated > ago(1h)
| where Log contains "ERROR"
| project TimeGenerated, RevisionName, ContainerGroupName, Log
| order by TimeGenerated desc
On an environment using the log-analytics destination instead, the same query reads
ContainerAppConsoleLogs_CL and uses the suffixed columns (ContainerAppName_s, RevisionName_s, Log_s).
AKS
aks-bookshelf’s Container insights (enabled via `az aks enable-addons -a monitoring, covered on
AKS Clusters) writes pod stdout/stderr to ContainerLogV2 and pod/node inventory to
KubePodInventory:
ContainerLogV2
| where PodNamespace == "bookshelf"
| where PodName startswith "notifier"
| where LogMessage has "exception"
| project TimeGenerated, PodName, ContainerName, LogMessage
| order by TimeGenerated desc
KubePodInventory
| where ClusterName == "aks-bookshelf"
| summarize RestartCount = max(PodRestartCount) by Name, Namespace
| where RestartCount > 0
| order by RestartCount desc
Front Door
afd-bookshelf (Front Door Standard/Premium) sends its access, health probe, and WAF logs to the
AzureDiagnostics table, told apart by Category (FrontDoorAccessLog, FrontDoorHealthProbeLog,
FrontDoorWebApplicationFirewallLog). Fields are flattened into type-suffixed columns, and the status code
arrives as a string (httpStatusCode_s), so it’s converted before comparing:
AzureDiagnostics
| where Category == "FrontDoorAccessLog"
| where TimeGenerated > ago(24h)
| where toint(httpStatusCode_s) >= 500
| summarize ErrorCount = count() by requestUri_s
| order by ErrorCount desc
Diagnostic settings: wiring a resource to the workspace
A diagnostic setting is the explicit link between one resource’s logs/metrics and one or more destinations (a Log
Analytics workspace, an event hub, or a storage account for long-term archive). Without one, a resource’s logs
are never sent anywhere durable — platform metrics keep flowing regardless, but resource-log tables like
ContainerAppConsoleLogs or AzureDiagnostics stay empty. For cae-bookshelf specifically, the diagnostic
setting only takes effect once the environment’s logs destination is azure-monitor (see Container Apps).
In the Azure portal
-
Open the resource (
cae-bookshelf,aks-bookshelf, orafd-bookshelf) and select Diagnostic settings under Monitoring. -
Select Add diagnostic setting, name it (e.g.
send-to-law-bookshelf). -
Under Logs, select the categories to collect (all logs, or a specific category such as ContainerAppConsoleLogs).
-
Under Destination details, check Send to Log Analytics workspace and pick
law-bookshelf. -
Select Save.
With the Azure CLI
WORKSPACE_ID=$(az monitor log-analytics workspace show \
--resource-group "$RG" --workspace-name law-bookshelf --query id -o tsv)
CAE_ID=$(az containerapp env show \
--resource-group "$RG" --name cae-bookshelf --query id -o tsv)
az monitor diagnostic-settings create \
--name send-to-law-bookshelf \
--resource "$CAE_ID" \
--workspace "$WORKSPACE_ID" \
--logs '[{"category":"ContainerAppConsoleLogs","enabled":true},{"category":"ContainerAppSystemLogs","enabled":true}]' \
--metrics '[{"category":"AllMetrics","enabled":true}]'
Derived from Microsoft Learn — Azure CLI reference: az monitor diagnostic-settings and Microsoft Learn — Diagnostic settings in Azure Monitor.
The same command, pointed at `aks-bookshelf’s or `afd-bookshelf’s resource ID with that resource’s own log category names, wires up the AKS and Front Door queries above.
Application Insights: the application-level view
Application Insights is Azure Monitor’s application performance monitoring (APM) feature: request rates,
response times, dependency calls (catalog-api calling pg-bookshelf, orders-api calling docdb-bookshelf),
exceptions, and distributed traces that follow one request across catalog-api, orders-api and notifier. A
workspace-based Application Insights component — the only kind the portal creates today — stores its data as
extra tables inside a Log Analytics workspace (law-bookshelf), so KQL queries can join AppRequests,
AppExceptions and AppDependencies with the container and platform logs above in one query.
Connection strings, not instrumentation keys
Every Application Insights component exposes a connection string — an ingestion endpoint plus an
instrumentation key, e.g. InstrumentationKey=<app-insights-connection-string> — that an SDK or agent uses to
send telemetry. Support for ingesting telemetry using a bare instrumentation key (with no connection string)
ended on 2025-03-31; instrumentation-key-only configuration may still work but receives no further updates, so
every new integration should be configured with the full connection string from day one.
The Azure Monitor OpenTelemetry Distro
The Azure Monitor OpenTelemetry Distro is Microsoft’s current recommendation for instrumenting new applications — a Microsoft-maintained OpenTelemetry distribution that auto-collects traces, metrics, logs and exceptions and
exports them to Application Insights, rather than the older, now-legacy Application Insights SDKs. For
catalog-api and orders-api (Spring Boot), the distro is added as the Spring Cloud Azure Starter Monitor
dependency alongside the OpenTelemetry BOM:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-bom</artifactId>
<version>1.55.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-monitor</artifactId>
</dependency>
No application code changes are required beyond the dependency; the connection string is then supplied as an environment variable, never in code or a checked-in properties file:
APPLICATIONINSIGHTS_CONNECTION_STRING=$(az monitor app-insights component show \
--app appi-bookshelf --resource-group "$RG" --query connectionString -o tsv)
On cae-bookshelf, that variable is set as a Container App secret-backed environment variable (covered on
Container Apps); on aks-bookshelf, as a Kubernetes secret mounted into
catalog-api’s/`orders-api’s pod spec (covered on Runtime Configuration) — in neither
case does the connection string need to be a long-lived secret pulled from `kv-bookshelf, since it identifies a
telemetry destination rather than granting access to anything sensitive, but treating it as configuration rather
than a literal in source control still avoids leaking one Application Insights component’s data into another
environment’s.
In the Azure portal
-
Search for Application Insights and select Create.
-
Choose
rg-bookshelf, name itappi-bookshelf, and under Resource Mode leave Workspace-based selected. -
Under Log Analytics Workspace, pick
law-bookshelf. -
Select Review + create, then Create, then open the resource’s Overview pane and copy the Connection String.
Alerts and action groups
An action group is a reusable notification target — one or more email, SMS, voice, webhook, Azure Function,
Logic App or ITSM receivers, defined once and referenced by many alert rules. Bookshelf defines one,
ag-bookshelf-oncall, with an email receiver for the on-call rotation:
az monitor action-group create \
--name ag-bookshelf-oncall \
--resource-group "$RG" \
--short-name bookshelf \
--action email oncall oncall@example.com
A metric alert evaluates a metric-based condition on a fixed schedule (near-real-time, typically every one to
five minutes) and fires the action group when it is breached. This one watches catalog-api’s replica count on
`cae-bookshelf:
CATALOG_API_ID=$(az containerapp show \
--resource-group "$RG" --name catalog-api --query id -o tsv)
AG_ID=$(az monitor action-group show \
--resource-group "$RG" --name ag-bookshelf-oncall --query id -o tsv)
az monitor metrics alert create \
--name catalog-api-no-replicas \
--resource-group "$RG" \
--scopes "$CATALOG_API_ID" \
--condition "avg Replicas < 1" \
--window-size 5m \
--evaluation-frequency 1m \
--severity 1 \
--action "$AG_ID" \
--description "catalog-api has scaled to zero unexpectedly"
Derived from Microsoft Learn — Azure CLI reference: az monitor metrics alert and Microsoft Learn — Types of Azure Monitor alerts.
A log search alert is the log-data equivalent: instead of a built-in metric condition, it runs a KQL query on a
schedule and fires when the result set crosses a threshold — the natural way to alert on one of the KQL queries
above (e.g. "more than 10 ERROR lines from catalog-api in the last 5 minutes"). It is created with
az monitor scheduled-query create rather than metrics alert create, since it targets a Log Analytics
workspace and a query rather than a metric namespace.
Workbooks and dashboards
A workbook is an interactive report — text, KQL query results (tables, charts), and parameters the reader can change — authored once in the portal and reused across incidents, distinct from a one-off ad hoc query. Azure Monitor ships gallery templates for Container Apps, AKS and Application Insights that already chart request rate, failure rate, latency and dependency health; cloning one of those and adding a Bookshelf-specific KQL query (such as the Front Door error-count query above) is the usual starting point, rather than authoring a workbook from a blank canvas. A dashboard is the simpler, older alternative: a fixed grid of tiles (metric charts, a workbook, a static markdown tile) pinned from individual resource blades, better suited to an always-on big-screen view than to interactive investigation. Both are ARM resources under the hood and can be defined as Bicep/ARM templates for repeatable deployment rather than only clicked together in the portal, which is the practical way to keep a workbook’s definition in source control alongside the rest of Bookshelf’s infrastructure-as-code (covered on Infrastructure as Code).
Service Health, Advisor, and Network Watcher
These three sit next to Azure Monitor rather than inside it — each answers a different "is something wrong" question that resource-level metrics and logs cannot:
- Azure Service Health
-
Reports incidents and planned maintenance on the Azure platform itself — an outage affecting Container Apps in
eastus2, for instance — scoped to the resources actually deployed, with alerting of its own so a platform incident is known before Bookshelf’s own alerts start firing for the symptom. - Azure Advisor
-
Continuously analyzes configuration and usage across a subscription and recommends changes across five categories (Reliability, Security, Performance, Cost, Operational Excellence) — for example, flagging that
pg-bookshelfhas no configured high-availability standby, or thatstbookshelfallows public network access it does not use. Advisor’s cost recommendations are covered in more depth on Cost Management. - Network Watcher
-
A regional suite of network diagnostic tools — IP flow verify, next hop, connection troubleshoot, packet capture, and NSG/topology visualization — for the case metrics and logs narrow a problem down to "something between
vnet-bookshelfand a resource isn’t connecting" but not which hop. It complements rather than replaces Virtual Networks's NSG flow logs.
How it fits together
Clean up
az group delete --name "$RG" --yes --no-wait
This removes law-bookshelf, appi-bookshelf, ag-bookshelf-oncall, and every alert rule and diagnostic setting
created on this page, along with the rest of Bookshelf’s resources in $RG. Application Insights and Log
Analytics workspaces have no soft-delete purge step of their own to worry about (unlike Key Vault or API
Management), so deleting the resource group is sufficient.
Related pages
-
Container Apps and AKS Clusters cover the resources whose logs feed the KQL examples above.
-
Front Door and CDN covers the access and WAF logs queried in the Front Door example.
-
Runtime Configuration covers how the Application Insights connection string reaches a running Container App or AKS pod as configuration.
-
Cost Management covers Advisor’s cost recommendations and Log Analytics ingestion pricing in more depth.
-
Virtual Networks covers NSG flow logs, which Network Watcher’s tools complement.
-
Infrastructure as Code covers deploying workbooks and alert rules as Bicep/ARM templates instead of clicking them together in the portal.
References
-
Microsoft Learn — Azure CLI reference: az monitor log-analytics workspace
-
Microsoft Learn — Application logging in Azure Container Apps
-
Microsoft Learn — Monitor metrics and logs in Azure Front Door
-
Microsoft Learn — Azure CLI reference: az monitor diagnostic-settings
-
Microsoft Learn — Create a workspace-based Application Insights resource
-
Microsoft Learn — Connection strings in Application Insights
-
Microsoft Learn — Enable OpenTelemetry in Application Insights
-
Microsoft Learn — Azure CLI reference: az monitor app-insights component
-
Microsoft Learn — Azure CLI reference: az monitor action-group
-
Microsoft Learn — Azure CLI reference: az monitor metrics alert
-
Microsoft Learn — Create and share dashboards of Log Analytics data