Azure Monitor, Log Analytics & Application Insights
By the end of this lesson you will be able to explain metrics, logs and traces, create a Log Analytics workspace, send resource logs to it, add Application Insights to a Python app, write simple KQL queries, and create an alert that emails you before your users complain.
Why monitoring matters
Imagine Meera's online coaching app slows down every evening at 8 pm. Without monitoring she hears about it from angry students on WhatsApp. With monitoring, she sees CPU rise at 7:55, gets an email at 8:01, and can find the slow database query in minutes.
Azure Monitor is the umbrella name for Azure's monitoring features. It collects three kinds of data:
| Data | What it is | Example |
|---|---|---|
| Metrics | Numbers sampled over time | CPU percentage, HTTP 5xx count, database DTU usage |
| Logs | Records with many fields, stored in a Log Analytics workspace | Every request, every Key Vault secret read, every VM syslog line |
| Traces | The path of one request through several services | Web app called API, API called SQL, SQL took 900 ms |
Think of a hospital patient. Metrics are the heart-rate monitor beeping every second. Logs are the nurse's detailed notes. Traces are the record of one patient's journey from reception to X-ray to pharmacy.
The building blocks
- Platform metrics are collected automatically for most resources; you can chart them right away.
- The activity log records management operations (who created or deleted what), as you saw in the portal lesson.
- A Log Analytics workspace stores logs and lets you query them with KQL (Kusto Query Language).
- Diagnostic settings send a resource's detailed resource logs and metrics to a workspace, a storage account or an event hub. Resource logs are not collected until you create a diagnostic setting.
- Application Insights monitors application code: requests, dependencies, exceptions, traces and page views. Modern Application Insights resources store their data in a Log Analytics workspace.
- Alerts watch metrics or log queries and trigger action groups, which send email, SMS or push notifications, or call a webhook or function.
- For VMs, the Azure Monitor Agent with data collection rules collects OS logs and performance counters. It replaced the older Log Analytics agent, which you may still see in old guides.
Step by step: workspace and diagnostic settings
Step 1: create a workspace.
az group create --name rg-monitor-demo --location centralindia --output none
az monitor log-analytics workspace create --resource-group rg-monitor-demo \
--workspace-name log-coaching-cin --location centralindia --output none
lawId=$(az monitor log-analytics workspace show --resource-group rg-monitor-demo \
--workspace-name log-coaching-cin --query id --output tsv)Step 2: send a Key Vault's audit logs to the workspace, so you can see every secret read. categoryGroup audit selects the audit categories without listing them one by one.
kvId=$(az keyvault show --name kv-tiffin-cin-01 --query id --output tsv)
az monitor diagnostic-settings create --name to-law --resource "$kvId" --workspace "$lawId" \
--logs '[{"categoryGroup":"audit","enabled":true}]' --output noneApplication Insights for your code
Step 1: create a workspace-based Application Insights resource. These commands come from the application-insights CLI extension.
az monitor app-insights component create --app appi-coaching-cin --location centralindia \
--resource-group rg-monitor-demo --workspace "$lawId" \
--query connectionString --output tsvThe command prints a connection string that tells the SDK where to send data. It is not a password, but treat it as configuration, not something to post publicly. Older guides use an instrumentation key alone; Microsoft ended support for key-only ingestion, so always use the connection string.
Step 2: add the Azure Monitor OpenTelemetry Distro to a Python web app. OpenTelemetry is an open standard for collecting telemetry, so your instrumentation is not tied to one vendor.
# app.py
from azure.monitor.opentelemetry import configure_azure_monitor
from flask import Flask
configure_azure_monitor() # reads APPLICATIONINSIGHTS_CONNECTION_STRING
app = Flask(__name__)
@app.get("/")
def home():
return "Coaching timetable"Set the app setting APPLICATIONINSIGHTS_CONNECTION_STRING on the web app to the value from Step 1. Calling configure_azure_monitor() before creating the Flask app lets the distro instrument Flask automatically. Requests, failures and response times now flow into Application Insights. Open Application Map, Failures and Performance in the portal to explore them.
Querying logs with KQL
KQL reads like a pipeline: start from a table, then pass rows through steps separated by |. In a workspace, Application Insights requests are in the AppRequests table.
AppRequests
| where TimeGenerated > ago(1h)
| summarize Requests = count(), AvgMs = avg(DurationMs) by ResultCode
| order by ResultCode ascThis counts the last hour's requests by HTTP result code with the average duration. A query for the slowest pages:
AppRequests
| where TimeGenerated > ago(1d)
| top 5 by DurationMs desc
| project TimeGenerated, Name, DurationMs, ResultCodeYou can run KQL in the portal's Logs page, or from code with the Azure Monitor Query library:
from datetime import timedelta
from azure.identity import DefaultAzureCredential
from azure.monitor.query import LogsQueryClient
client = LogsQueryClient(DefaultAzureCredential())
query = "AppRequests | summarize Requests = count() by ResultCode | order by ResultCode asc"
result = client.query_workspace("<workspace-id>", query, timespan=timedelta(hours=1))
for row in result.tables[0].rows:
print(row["ResultCode"], row["Requests"])200 1520 404 12 500 3
The numbers are illustrative; yours depend on your traffic. <workspace-id> is the workspace's customer ID (a GUID), not its resource ID. You need at least the Log Analytics Reader role.
Step by step: alert on server errors
Step 1: create an action group that emails the on-call person.
az monitor action-group create --resource-group rg-monitor-demo --name ag-oncall \
--short-name oncall --action email meera meera@example.com --output noneStep 2: alert when the web app returns more than 5 server errors in 5 minutes.
appId=$(az webapp show --resource-group rg-web-demo --name app-tiffin-pune-01 --query id --output tsv)
az monitor metrics alert create --resource-group rg-monitor-demo --name alert-http5xx \
--scopes "$appId" --condition "total Http5xx > 5" \
--window-size 5m --evaluation-frequency 1m --action ag-oncall --severity 2 --output noneYou should receive an email when the condition fires, and another when it resolves.
Costs of monitoring
Log Analytics charges mainly for data ingested and retained. Sending every debug log from every service can cost more than the app itself. Collect what you will query, set sensible retention, and use sampling in Application Insights for very busy apps. Check the Azure Monitor pricing page for the current model.
Clean up: az group delete --name rg-monitor-demo --yes --no-wait.
Common mistakes
- Expecting resource logs without a diagnostic setting. Only metrics and the activity log are automatic.
- Using classic, non-workspace Application Insights in new guides. Create workspace-based resources.
- Logging secrets or personal data. Logs are read by many people and kept for a long time. Mask phone numbers and Aadhaar-like IDs.
- Alerts with no owner. Every alert should go to a person or team who knows what to do.
Key points
- Azure Monitor collects metrics, logs and traces; Log Analytics workspaces store logs queried with KQL.
- Diagnostic settings are needed to send resource logs to a workspace.
- Application Insights, set up with the Azure Monitor OpenTelemetry Distro and a connection string, monitors your code.
- Alerts watch metrics or queries and notify people through action groups.
- Control monitoring costs by collecting only useful data and setting retention.
Exercise
Write a KQL query that shows, for the last 24 hours, the five request names (Name) with the most failed requests (where Success == false), along with the failure count. Then write the CLI command for an alert called alert-cpu that fires when the average CpuPercentage of an App Service plan with ID stored in $planId is above 80 over 15 minutes, using the action group ag-oncall.
Show solution
AppRequests
| where TimeGenerated > ago(1d) and Success == false
| summarize Failures = count() by Name
| top 5 by Failures descaz monitor metrics alert create --resource-group rg-monitor-demo --name alert-cpu \
--scopes "$planId" --condition "avg CpuPercentage > 80" \
--window-size 15m --evaluation-frequency 5m --action ag-oncall --output noneThe query filters failures first, then groups and ranks them. The alert uses the plan's CpuPercentage metric averaged over a 15-minute window.
Quick Quiz
1. Where do you write KQL queries over collected logs?
Log Analytics workspaces store logs and run KQL queries.
2. A Key Vault's secret-read logs do not appear in your workspace. What is the likely cause?
Resource logs are collected only after you create a diagnostic setting.
3. What should a new app use to send data to Application Insights?
Connection strings are the supported method; key-only ingestion is retired.
Learn Microsoft Azure with a mentor
Free lessons get you started. Our Cloud & DevOps training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
