Module 1 – Azure Monitor
Overview
Azure Monitor is the centralized monitoring platform for all Azure resources.
Data Sources
| Source | Description |
|---|---|
| Azure Resources | Metrics and logs from resources (VMs, Storage, Functions, etc.) |
| Applications | Traces, exceptions, requests via Application Insights |
| Operating System | Windows Event Logs, Linux Syslog (via agents) |
| Subscription | Azure Activity Log (who did what?) |
| Tenant | Entra ID audit logs, sign-in logs |
| Hybrid | On-premises servers, AWS/GCP via Azure Arc |
Types of Collected Data
| Type | Description | Examples |
|---|---|---|
| Metrics | Numeric time-series values | CPU%, memory, requests/sec, latency |
| Logs | Detailed events, text | Errors, audit, traces |
| Traces | End-to-end distributed tracing | Calls between microservices |
| Changes | Configuration modifications | ARM changes, OS changes |
Module 2 – Metrics and Metrics Explorer
Accessing Metrics
Azure Portal → Resource (e.g., VM) → Monitoring → Metrics
→ Metric: CPU Percentage
→ Aggregation: Average
→ Time range: Last 24 hours
Creating a Chart
- Choose one or more metrics.
- Configure time granularity (1min, 5min, 1h).
- Pin to dashboard.
Metric-Based Alerts
Azure Monitor → Alerts → Create
→ Scope: [Resource]
→ Condition: CPU Percentage > 80% (for 5 min)
→ Action Group: [email, SMS, webhook]
→ Alert rule name: "High CPU Alert"
Module 3 – Log Analytics and KQL
Log Analytics Workspace
- Stores logs from all configured sources.
- Queryable via KQL (Kusto Query Language).
Important Tables
| Table | Content |
|---|---|
Heartbeat | Azure Monitor agents (VMs) → check if the VM is alive |
AzureActivity | Activity Log → who created/modified/deleted what |
ContainerLog | AKS container logs |
AppRequests | HTTP requests (Application Insights) |
AppExceptions | Application exceptions (Application Insights) |
SecurityEvent | Windows security events |
KQL – Common Examples
// Check which VMs are active
Heartbeat
| summarize LastHeartbeat = max(TimeGenerated) by Computer
| order by LastHeartbeat desc
// Errors from the last 24 hours
AppExceptions
| where TimeGenerated > ago(24h)
| summarize count() by ExceptionType
| order by count_ desc
// Administrator activities
AzureActivity
| where Caller == "admin@contoso.com"
| where TimeGenerated > ago(7d)
| project TimeGenerated, OperationNameValue, ResourceGroup, ActivityStatus
// Average latency per endpoint
AppRequests
| where TimeGenerated > ago(1h)
| summarize AvgDuration = avg(DurationMs) by Url
| order by AvgDuration desc
Module 4 – Alerts and Action Groups
Alert Pipeline
Data source (Metric or Log)
↓ Condition
Alert triggered
↓
Action Group
├── Email notifications
├── SMS
├── Push notification (Azure app)
├── Voice call
├── Azure Function
├── Logic App
├── Webhook
└── ITSM (ServiceNow, Jira)
Action Groups
- Reusable notification group across multiple alert rules.
- A change to the group applies to all rules that use it.
Azure Monitor → Action groups → Create
→ Group name: "Ops Team Notifications"
→ Actions:
[Email] ops-team@contoso.com
[SMS] +1-555-0100
[Webhook] https://hooks.slack.com/...
Alert Severities
| Severity | Level |
|---|---|
| 0 | Critical |
| 1 | Error |
| 2 | Warning |
| 3 | Informational |
| 4 | Verbose |
Module 5 – Azure Workbooks and Dashboards
Workbooks
- Interactive reports with text, metrics, logs, parameters.
- Pre-built templates for common scenarios (VM insights, Application Insights, etc.).
Azure Monitor → Workbooks → + New
→ Add text (Markdown)
→ Add query (KQL query → Log Analytics)
→ Add metrics (Metrics chart)
→ Add parameters (dropdown, time range)
→ Save & Share
Azure Dashboards
- Custom views with metrics tiles, alerts, workbooks.
- Shareable with the team.
Module 6 – Application Insights
Features
| Feature | Description |
|---|---|
| Request tracking | All HTTP requests traced automatically |
| Dependency tracking | Calls to SQL, Cosmos DB, external HTTP, Queue |
| Exception tracking | Exceptions captured with full stack trace |
| Performance counters | Process CPU, memory, I/O |
| Live Metrics | Real-time view (latency, requests/sec, failed requests) |
| Application Map | Visualization of dependencies between components |
Summary
| Concept | Key Point |
|---|---|
| Azure Monitor | Central platform for all Azure metrics and logs |
| Metrics | Numeric values (CPU, latency) → Metrics Explorer, alerts |
| Logs | Detailed events → Log Analytics (KQL) |
| KQL | Query language for Log Analytics |
| Heartbeat | Table to check if Azure Monitor agent VMs are active |
| Alerts | Condition → Action Group (email, SMS, webhook, Logic App) |
| Action Groups | Reusable notification groups |
| Workbooks | Interactive reports with metrics + logs |
| Application Insights | APM for applications (requests, exceptions, dependencies) |
Advanced Deep-Dive – Azure Monitor In Depth
Section A – Azure Monitor: Complete Architecture
Platform Overview
Azure Monitor is the central nervous system of Azure observability. It ingests telemetry data from all Azure resources, on-premises environments, and hybrid clouds, then makes it available for analysis, visualization, and automated action.
Main Components
| Component | Role |
|---|---|
| Metrics Store | Time-series database for metrics (93-day retention by default) |
| Log Analytics Workspace | Storage for structured/semi-structured logs queryable in KQL |
| Activity Log | Subscription-level audit of control plane operations (who did what, when) |
| Diagnostic Settings | Configuration for sending logs/metrics to Log Analytics, Storage, Event Hub |
| Data Collection Rules (DCR) | Granular data collection rules per resource/agent |
| Application Insights | APM – traces, exceptions, availability, application map |
| Azure Monitor Agent (AMA) | Unified agent replacing MMA/OMS for VMs and Arc |
Detailed Data Sources
| Source | Data Type | Mechanism |
|---|---|---|
| Azure VMs | Host metrics, OS logs, Heartbeat | Azure Monitor Agent + DCR |
| Containers (AKS) | Pod logs, node metrics, Container Insights | Azure Monitor for containers |
| Applications (.NET/Java/Python) | Traces, exceptions, custom metrics | Application Insights SDK |
| Azure SQL | Query performance, DTU, deadlocks | Diagnostic Settings |
| Azure Functions | Invocations, durations, errors | Application Insights auto |
| Network infrastructure | NSG flow logs, connections | Network Watcher |
| Subscription | RBAC changes, policy violations | Activity Log |
| Entra ID | Sign-ins, audit logs | Diagnostic Settings → Log Analytics |
| On-premises / Arc | Syslog, Event Log, Perf counters | AMA + DCR |
Monitoring Pipeline Architecture
flowchart TD
subgraph Sources["Data Sources"]
VM["Azure VMs / Arc"]
APP["Applications\n(SDK / auto-instrumentation)"]
AKS["AKS / Containers"]
INFRA["Azure Infrastructure\n(SQL, Storage, VNet...)"]
SUB["Subscription / Entra ID"]
end
subgraph Collect["Collection"]
AMA["Azure Monitor Agent\n(AMA)"]
DCR["Data Collection Rules"]
DIAG["Diagnostic Settings"]
SDK["Application Insights SDK"]
end
subgraph Store["Storage"]
METRICS["Metrics Store\n(time-series 93d)"]
LAW["Log Analytics\nWorkspace"]
AI["Application Insights\nWorkspace"]
STG["Storage Account\n(long-term archiving)"]
EH["Event Hub\n(SIEM streaming)"]
end
subgraph Analyze["Analysis"]
ME["Metrics Explorer"]
KQL["KQL Queries"]
WB["Workbooks"]
DASH["Dashboards"]
end
subgraph Act["Action"]
ALERT["Alerts"]
AG["Action Groups"]
AS["Autoscale"]
LA["Logic Apps / Functions"]
end
VM --> AMA --> DCR --> LAW
APP --> SDK --> AI
AKS --> DCR --> LAW
INFRA --> DIAG --> LAW
INFRA --> DIAG --> STG
INFRA --> DIAG --> EH
SUB --> LAW
METRICS --> ME
LAW --> KQL
AI --> KQL
KQL --> WB
KQL --> DASH
ME --> ALERT
KQL --> ALERT
ALERT --> AG --> LA
Activity Log
The Activity Log is a subscription-level log that records all control plane operations:
- Creation / modification / deletion of resources
- RBAC changes
- Azure Policy operations
- Service health alerts
Default retention: 90 days. For longer retention → export to Log Analytics or Storage Account.
// All resource deletions in the last 7 days
AzureActivity
| where TimeGenerated > ago(7d)
| where OperationNameValue endswith "delete"
| where ActivityStatusValue == "Success"
| project TimeGenerated, Caller, ResourceGroup, Resource, OperationNameValue
| order by TimeGenerated desc
Diagnostic Settings
Diagnostic Settings allow sending resource logs and platform metrics to one or more destinations:
Azure Resource → Diagnostic Settings → + Add diagnostic setting
├── Logs: AllLogs / specific categories
├── Metrics: AllMetrics
└── Destinations:
├── Log Analytics Workspace (KQL queries)
├── Storage Account (archiving / compliance)
└── Event Hub (streaming to SIEM / Splunk)
Section B – Log Analytics and Advanced KQL
Workspace Architecture
A Log Analytics Workspace is an isolated data container with:
- Its own access control (RBAC)
- Its own retention (30 days by default, up to 730 days)
- Its own data tables
- Its own solution configuration
Workspace Design Strategies
| Strategy | Use Case |
|---|---|
| Single workspace | Small organization, consolidated view, simplified cost |
| Per environment | Strict prod/dev/test separation |
| Per region | Sovereign data compliance, reduced latency |
| Per team/BU | Strict RBAC, precise chargeback per department |
Data Retention
| Period | Behavior | Cost |
|---|---|---|
| 0 – 30 days | Default interactive retention included | Included in ingestion |
| 31 – 90 days | Extended interactive retention | Additional billing |
| 91 – 730 days | Archive (restore queries required) | Reduced cost |
| > 730 days | Export to Storage Account | Storage cost only |
KQL – Fundamental Operators
where – Filtering
// Filter HTTP 5xx errors from the last 24h
AppRequests
| where TimeGenerated > ago(24h)
| where ResultCode >= 500
| where Success == false
project – Column Selection
// Keep only useful columns
AppRequests
| where TimeGenerated > ago(1h)
| project TimeGenerated, Name, DurationMs, ResultCode, ClientIP
summarize – Aggregation
// Number of requests per HTTP code, sorted
AppRequests
| where TimeGenerated > ago(24h)
| summarize RequestCount = count(), AvgDuration = avg(DurationMs)
by ResultCode
| order by RequestCount desc
// Error rate per hour
AppRequests
| where TimeGenerated > ago(7d)
| summarize
Total = count(),
Errors = countif(Success == false)
by bin(TimeGenerated, 1h)
| extend ErrorRate = round(100.0 * Errors / Total, 2)
join – Table Joins
// Correlate exceptions with the requests that generated them
AppRequests
| where TimeGenerated > ago(1h)
| join kind=leftouter (
AppExceptions
| where TimeGenerated > ago(1h)
| project ExceptionType, OperationId
) on OperationId
| project TimeGenerated, Name, DurationMs, ExceptionType
extend – Computed Columns
// Categorize latency
AppRequests
| where TimeGenerated > ago(1h)
| extend LatencyCategory = case(
DurationMs < 200, "Fast",
DurationMs < 1000, "Normal",
DurationMs < 3000, "Slow",
"Critical"
)
| summarize count() by LatencyCategory
render – Inline Visualization
// Latency chart over time
AppRequests
| where TimeGenerated > ago(24h)
| summarize AvgDuration = avg(DurationMs) by bin(TimeGenerated, 15m)
| render timechart
// HTTP status code pie chart
AppRequests
| where TimeGenerated > ago(24h)
| summarize count() by ResultCode
| render piechart
KQL – Useful Advanced Queries
// Top 10 IPs with the most failed requests
AppRequests
| where TimeGenerated > ago(24h)
| where Success == false
| summarize FailedRequests = count() by ClientIP
| top 10 by FailedRequests desc
// Latency percentiles (p50, p95, p99)
AppRequests
| where TimeGenerated > ago(1h)
| summarize
p50 = percentile(DurationMs, 50),
p95 = percentile(DurationMs, 95),
p99 = percentile(DurationMs, 99)
by Name
| order by p99 desc
// CPU anomaly detection on VMs
Perf
| where TimeGenerated > ago(24h)
| where ObjectName == "Processor" and CounterName == "% Processor Time"
| summarize AvgCPU = avg(CounterValue) by Computer, bin(TimeGenerated, 5m)
| where AvgCPU > 85
| order by TimeGenerated desc
// VMs with no heartbeat for more than 10 minutes (potentially down)
Heartbeat
| summarize LastHeartbeat = max(TimeGenerated) by Computer, ComputerIP
| extend TimeSinceHeartbeat = now() - LastHeartbeat
| where TimeSinceHeartbeat > 10m
| project Computer, ComputerIP, LastHeartbeat, TimeSinceHeartbeat
Log Analytics Solutions
| Solution | Description |
|---|---|
| VM Insights | Health, performance, network dependencies of VMs (dependency map) |
| Container Insights | AKS monitoring: pods, nodes, container logs |
| Microsoft Sentinel | SIEM/SOAR – threat detection, security incidents |
| Network Performance Monitor | Latency, packet loss between network hubs |
| Key Vault Analytics | Audit of secret, certificate, and key access |
| SQL Insights | SQL Server and Azure SQL performance |
Saved Searches and Log Alerts
Log Analytics Workspace → Logs → [Write KQL query]
→ Save → Save as query
→ Category: "Performance", "Security", etc.
→ Query name: "High CPU VMs"
// Create alert from a query
→ New alert rule
→ Condition: result count > 0 (or custom threshold)
→ Evaluation frequency: Every 5 minutes
→ Action Group: [Ops Team]
Section C – Application Insights In Depth
Integration Modes
| Mode | Description | Use Case |
|---|---|---|
| Manual SDK | NuGet/pip/Maven package in code | Full control, custom events |
| Auto-instrumentation | Agent without code modification | Quick migration, legacy apps |
| OpenTelemetry (OTEL) | Open standard, Azure Monitor exporter | Multi-cloud, microservices |
SDK Integration by Language
.NET / ASP.NET Core
// Program.cs – ASP.NET Core 8
builder.Services.AddApplicationInsightsTelemetry(
options => options.ConnectionString = builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]
);
// Custom event
private readonly TelemetryClient _telemetry;
_telemetry.TrackEvent("OrderPlaced", new Dictionary<string, string> {
{ "OrderId", orderId },
{ "UserId", userId }
});
// Custom metric
_telemetry.TrackMetric("CartItemCount", items.Count);
// Custom exception
try { ... }
catch (Exception ex) {
_telemetry.TrackException(ex, new Dictionary<string, string> {
{ "OrderId", orderId }
});
throw;
}
Python
from applicationinsights import TelemetryClient
tc = TelemetryClient(os.environ["APPLICATIONINSIGHTS_CONNECTION_STRING"])
# Event
tc.track_event("UserLogin", {"UserId": user_id, "Method": "OAuth"})
# Metric
tc.track_metric("ProcessingTimeMs", processing_time)
# Exception
try:
process_order()
except Exception as e:
tc.track_exception()
raise
tc.flush()
Java (Spring Boot)
<!-- pom.xml -->
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>applicationinsights-spring-boot-starter</artifactId>
<version>2.6.4</version>
</dependency>
# applicationinsights.json (Java agent auto-instrumentation)
{
"connectionString": "InstrumentationKey=...",
"sampling": { "percentage": 100 },
"customDimensions": {
"Environment": "Production",
"AppVersion": "2.4.1"
}
}
Availability Tests
| Type | Description | Min Frequency |
|---|---|---|
| URL ping test | Simple HTTP GET request, status verification | 5 minutes |
| Standard test | GET/POST with response content validation | 5 minutes |
| Multi-step web test | Sequence of requests simulating a user workflow | 5 minutes |
| Custom availability | C# code or TrackAvailability() API | Custom |
Application Insights → Availability → + Add test
→ Test name: "Homepage Health Check"
→ URL: https://app.contoso.com
→ Test frequency: Every 5 minutes
→ Test locations: East US, West Europe, Southeast Asia
→ Success criteria: HTTP 200, response < 2000ms
→ Alert: Yes → Action Group: Ops Team
Live Metrics (Real-Time Metrics Stream)
Live Metrics provides a real-time window with less than 1 second delay:
| Metric | Description |
|---|---|
| Incoming requests | Requests/sec in progress |
| Outgoing requests | Outbound calls (dependencies) |
| Overall health | Green/red/orange color code |
| Failed requests | Real-time errors |
| Exceptions | Live stack traces |
| Server CPU / Memory | Process resources |
Application Map
The Application Map automatically detects components and their dependencies:
[React Frontend]
↓ HTTP
[API Gateway]
↓ HTTP ↓ HTTP
[Orders Service] [Users Service]
↓ SQL ↓ Redis
[Azure SQL DB] [Azure Cache]
↓ Event
[Service Bus]
↓
[Fulfillment Worker]
- Each node shows: error rate, average latency, request volume.
- Red edges indicate dependency issues.
- Clicking a node opens the component’s detailed metrics/logs.
Distributed Tracing
Distributed tracing allows following a request across all microservices:
// Retrieve all calls for a specific operation
union AppRequests, AppDependencies, AppExceptions
| where OperationId == "a1b2c3d4e5f6"
| order by TimeGenerated asc
| project TimeGenerated, itemType, Name, DurationMs, Success, Target
Sampling – Reducing Ingestion Costs
| Sampling Type | Behavior |
|---|---|
| Adaptive sampling (default) | Automatically adjusts the rate to maintain ~5 req/sec |
| Fixed-rate sampling | Fixed percentage (e.g., 10% of all requests) |
| Ingestion sampling | Filtering at the Application Insights service level |
// applicationinsights.json – Fixed rate 25%
{
"sampling": {
"percentage": 25
}
}
Important: Sampling is consistent – if a request is sampled, all its related dependencies and exceptions are too (same
OperationId).
Section D – Advanced Azure Monitor Metrics
Metric Dimensions
Dimensions allow segmenting a metric by attribute:
| Example | Metric | Dimension |
|---|---|---|
| Requests by HTTP code | Requests (App Service) | HttpStatusCode |
| CPU per VM in a VMSS | Percentage CPU | VMName |
| Latency by region | ServerResponseLatency | GeoType |
| Transactions by type | Transactions (Storage) | ApiName, GeoType |
Metrics Explorer → [Select a metric]
→ + Add filter → Dimension: HttpStatusCode → Value: 5xx
→ + Split by → Dimension: InstanceName
Available Aggregations
| Aggregation | Usage |
|---|---|
| Average | Average value over the period (CPU, latency) |
| Maximum | Peak value (memory spike, CPU burst) |
| Minimum | Floor value (inactivity detection) |
| Sum | Cumulative total (number of requests, bytes transferred) |
| Count | Number of measured data points |
Custom Metrics
// Publish a custom metric via SDK
var metric = telemetryClient.GetMetric("OrderProcessingTime", "Region");
metric.TrackValue(processingMs, "EastUS");
// Via Azure Monitor REST API
POST https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/
Microsoft.Insights/metrics
Authorization: Bearer {token}
{
"time": "2025-01-15T14:30:00Z",
"data": {
"baseData": {
"metric": "ActiveConnections",
"namespace": "MyApp/Performance",
"dimNames": ["ServiceName"],
"series": [{ "dimValues": ["OrderAPI"], "sum": 142, "count": 1, "min": 142, "max": 142 }]
}
}
}
Prometheus Integration
Azure Monitor can ingest Prometheus metrics via Azure Monitor managed service for Prometheus:
# Prometheus scraping configuration for AKS
apiVersion: v1
kind: ConfigMap
metadata:
name: ama-metrics-prometheus-config
namespace: kube-system
data:
prometheus-config: |-
global:
scrape_interval: 30s
scrape_configs:
- job_name: myapp
static_configs:
- targets: ["myapp-service:8080"]
// Query Prometheus metrics in Log Analytics
InsightsMetrics
| where Namespace == "prometheus"
| where Name == "http_requests_total"
| summarize sum(Val) by bin(TimeGenerated, 5m), Tags
Cross-Resource Queries
// Compare metrics from multiple workspaces
union workspace("workspace-prod").AppRequests,
workspace("workspace-staging").AppRequests
| where TimeGenerated > ago(1h)
| summarize count() by bin(TimeGenerated, 5m), _ResourceId
| render timechart
Section E – Advanced Azure Monitor Alerts
Alert Types
flowchart LR
subgraph AlertTypes["Alert Types"]
MA["Metric Alerts\n(static/dynamic thresholds)"]
LA["Log Alerts\n(KQL queries)"]
AA["Activity Log Alerts\n(ARM operations)"]
SA["Smart Detection\n(Application Insights anomalies)"]
end
subgraph Processing["Processing"]
SG["Smart Groups\n(AI grouping)"]
DEDUP["Deduplication\nsingle alert"]
end
subgraph Actions["Actions"]
EMAIL["Email / SMS / Push"]
WH["Webhook / HTTP"]
FUNC["Azure Function"]
LOGICAPP["Logic App"]
ITSM["ITSM (ServiceNow, Jira)"]
AS["Autoscale"]
end
MA --> SG
LA --> SG
AA --> SG
SA --> SG
SG --> DEDUP --> EMAIL
DEDUP --> WH
DEDUP --> FUNC
DEDUP --> LOGICAPP
DEDUP --> ITSM
DEDUP --> AS
Metric Alerts – Static vs Dynamic Threshold
Static Threshold
Condition: CPU Percentage > 80%
Evaluation: Every 1 minute, looking back 5 minutes
Severity: Warning (Sev 2)
Dynamic Threshold
Dynamic thresholds use machine learning to detect anomalies without defining a fixed threshold:
Metric: Requests per second
Threshold: Dynamic
Sensitivity: Medium (reduces false positives)
Look-back period: 4 days (learns weekly patterns)
Aggregation period: 5 minutes
Advantage: automatically adapts to seasonal variations (higher traffic on Fridays, month-end spikes, etc.).
Log Alerts (KQL)
Azure Monitor → Alerts → Create → Log search
→ KQL Query:
AppExceptions
| where TimeGenerated > ago(5m)
| summarize ExceptionCount = count() by ExceptionType
| where ExceptionCount > 10
→ Evaluation frequency: Every 5 minutes
→ Lookback: Last 5 minutes
→ Threshold: Result count > 0
→ Severity: Error (Sev 1)
Activity Log Alerts
// Alert if someone deletes a Key Vault
AzureActivity
| where OperationNameValue == "Microsoft.KeyVault/vaults/delete"
| where ActivityStatusValue == "Success"
Activity Log Alert Condition:
→ Category: Administrative
→ Operation: Delete Key Vault
→ Status: Succeeded
→ Resource Type: Microsoft.KeyVault/vaults
Action Groups – Complete Configuration
| Action Type | Configuration | Typical Delay |
|---|---|---|
| Email address (max 1000 per group) | < 1 minute | |
| SMS | International number (+1-555-…) | < 1 minute |
| Azure app push | Azure mobile app notification | < 1 minute |
| Voice | Voice phone call | 1-2 minutes |
| Webhook | HTTP POST to URL (e.g., Slack, Teams) | < 1 minute |
| Azure Function | HTTP trigger Function call | < 1 minute |
| Logic App | Complex automated workflow | 1-2 minutes |
| Event Hub | Alert event streaming | < 1 minute |
| ITSM | ServiceNow / Jira (ITSM connector) | 2-5 minutes |
| Automation Runbook | Automated PowerShell / Python script | 1-3 minutes |
Smart Groups
Smart Groups cluster correlated alerts to reduce noise:
- Grouping by resource, subscription, alert type, or AI-detected patterns.
- A single incident represents multiple correlated alerts.
- Significantly reduces alert fatigue.
Azure Monitor → Alerts → Smart Groups
→ Smart group: "Production API Degradation"
→ 14 alerts grouped
→ Resources: api-gateway, orders-svc, users-svc
→ Pattern: HTTP 503 errors + latency spikes
Section F – Advanced Azure Dashboards and Workbooks
Azure Dashboards – Tile Types
| Tile Type | Description |
|---|---|
| Metrics chart | Azure Monitor metrics chart |
| Log query | KQL result as table, chart, or list |
| Application Insights | APM data (requests, failures, latency) |
| Resource health | Real-time health status |
| Markdown | Formatted text, links, inline documentation |
| Azure Workbook | Full Workbook embedded in the dashboard |
| Clock | Clock with timezone |
Dashboard Sharing
Dashboard → Share → Publish dashboard
→ Resource group: monitoring-rg
→ Share with: All users in tenant / Specific RBAC role
// RBAC access control for dashboards
Role: "Reader" → View only
Role: "Contributor" → Edit and share
Azure Workbooks – Advanced Features
Workbooks are parameterizable interactive reports:
Available Parameter Types
| Parameter Type | Example |
|---|---|
| Time range | Selector: last 1h / 24h / 7d / custom |
| Dropdown | Select a subscription, region, or environment |
| Multi-select | Select multiple resources |
| Text input | Filter by name, IP, etc. |
| Resource picker | Select Azure resources directly |
Workbook → + Add parameter
→ Parameter type: Drop down
→ Data source: KQL query
→ Query:
Heartbeat
| distinct Computer
→ Display as: dropdown
→ Parameter name: SelectedVM
Operational Workbook Example
[Title]: Production Health Overview
[Parameter]: Time range (last 4h)
[Section 1]: Services Status
→ KQL: Heartbeat | summarize LastSeen = max(TimeGenerated) by Computer
[Section 2]: Error Rate Trend
→ KQL: AppRequests | summarize Errors=countif(!Success), Total=count()
by bin(TimeGenerated, 15m)
→ Render: Area chart
[Section 3]: Top Slowest Endpoints
→ KQL: AppRequests | top 10 by DurationMs desc
→ Render: Grid (table)
[Section 4]: Active Alerts
→ Alert data source: critical + error severity
Power BI Integration
// Export a Log Analytics query to Power BI
// In Log Analytics → Export → Export to Power BI
// Query optimized for Power BI (avoid large aggregations)
AppRequests
| where TimeGenerated > ago(30d)
| summarize
DailyRequests = count(),
DailyErrors = countif(Success == false),
AvgLatency = avg(DurationMs)
by Date = bin(TimeGenerated, 1d), Name
Section G – Azure Service Health
Service Health Components
flowchart TD
SH["Azure Service Health"]
SH --> SI["Service Issues\n(ongoing incidents affecting my resources)"]
SH --> PM["Planned Maintenance\n(Microsoft planned maintenance)"]
SH --> HA["Health Advisories\n(recommendations & breaking changes)"]
SH --> RH["Resource Health\n(individual health of each resource)"]
SH --> SHA["Service Health Alerts\n(proactive notifications)"]
| Component | Description |
|---|---|
| Service Issues | Active Azure incidents impacting your services (e.g., regional outage) |
| Planned Maintenance | Microsoft-planned maintenance with time window |
| Health Advisories | Feature retirements, breaking changes, required migrations |
| Resource Health | Individual resource state (Available / Degraded / Unavailable / Unknown) |
Service Health Alerts
Service Health → Health alerts → + Create service health alert
→ Services: Virtual Machines, App Service, SQL Database
→ Regions: East US, West Europe
→ Event types: Service issue, Planned maintenance, Health advisory
→ Action Group: Executive Notifications
Best practice: Always configure Service Health alerts for critical production services. This is the only way to be proactively informed of an Azure outage before users complain.
Resource Health vs Service Health
| Criterion | Resource Health | Service Health |
|---|---|---|
| Scope | Individual resource | Entire Azure service (region) |
| Cause | Issue with your specific resource | Microsoft infrastructure issue |
| Action | You must act | Microsoft must act |
| Example | VM unexpectedly restarted | Azure DNS outage in East US |
Section H – Network Watcher Monitoring
Network Watcher Tools
| Tool | Description |
|---|---|
| Connection Monitor | Continuously checks connectivity between VMs, endpoints, regions |
| NSG Flow Logs | Records all network traffic traversing NSGs (accept/deny) |
| Traffic Analytics | Analysis and visualization of NSG Flow Logs (hotspots, threats) |
| Topology | Visual map of Azure network infrastructure |
| IP Flow Verify | Tests whether an IP packet would be accepted/denied by the NSG |
| Next Hop | Identifies the next network hop from a VM |
| Packet Capture | Network packet capture (advanced network debugging) |
NSG Flow Logs and Traffic Analytics
Network Watcher → NSG flow logs → [Select NSG]
→ Status: On
→ Flow Log version: Version 2
→ Storage Account: flow-logs-storage
→ Retention: 30 days
→ Traffic Analytics: Enabled
→ Traffic Analytics workspace: [Log Analytics Workspace]
→ Processing interval: Every 10 minutes
// Top source IPs in Traffic Analytics
AzureNetworkAnalytics_CL
| where TimeGenerated > ago(24h)
| where SubType_s == "FlowLog"
| summarize TotalFlows = count() by SrcIP_s
| top 10 by TotalFlows desc
// Traffic blocked by NSG
AzureNetworkAnalytics_CL
| where TimeGenerated > ago(1h)
| where AllowedInFlows_d == 0 and DeniedInFlows_d > 0
| project TimeGenerated, NSGRule_s, SrcIP_s, DestIP_s, DestPort_d
Connection Monitor
Network Watcher → Connection Monitor → + Create
→ Name: "Prod-DB-Connectivity"
→ Sources: [VM: api-server-01]
→ Destinations: [Azure SQL Endpoint: sql.contoso.com:1433]
→ Test configuration:
→ Protocol: TCP
→ Destination port: 1433
→ Probe interval: 30 seconds
→ Alerts: Latency > 50ms or packet loss > 5%
Section I – ITSM Integration
Available ITSM Connectors
| Tool | Protocol | Capabilities |
|---|---|---|
| ServiceNow | ITSM Connector (REST API) | Incident creation, bidirectional updates |
| Jira | Webhook + Automation | Issue creation, labels, priorities |
| PagerDuty | Webhook / Events API v2 | Incident escalation, on-call routing |
| Freshservice | ITSM Connector | Automatic incident tickets |
| BMC Remedy | ITSM Connector | Full ITIL management |
ServiceNow Configuration
Azure Monitor → Action Groups → + Add action
→ Action type: ITSM
→ Connection: ServiceNow-Production
→ Work Item Type: Incident
→ Template:
short_description: "Azure Alert: {AlertName}"
description: "{AlertDetails}"
urgency: "2 - High"
impact: "2 - Medium"
assignment_group: "Azure Operations"
Complete Alert → ITSM Ticket Pipeline
sequenceDiagram
participant AM as Azure Monitor
participant AG as Action Group
participant SN as ServiceNow
participant OPS as Ops Team
AM->>AM: Alert condition triggered\n(CPU > 90% for 5min)
AM->>AG: Triggers Action Group
AG->>AG: Deduplication\n(avoids duplicates)
AG->>SN: POST /api/now/table/incident\n(HTTP POST with JSON payload)
SN->>SN: Creates incident INC0123456\nAssigns to "Azure Operations"
SN->>OPS: Email + mobile notification
OPS->>AM: Acknowledge the alert
AM->>SN: Update: status = "In Progress"
OPS->>SN: Resolves the incident
SN->>AM: Feedback: incident resolved
Generic Webhook Configuration
// Azure Monitor webhook payload (common format)
{
"schemaId": "AzureMonitorMetricAlert",
"data": {
"version": "2.0",
"status": "Activated",
"context": {
"alertRuleName": "High CPU Alert",
"severity": "2",
"monitorCondition": "Fired",
"resourceName": "prod-vm-01",
"resourceGroupName": "production-rg",
"subscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": "2025-01-15T14:30:00Z"
},
"properties": {
"metricValue": "92.4",
"metricName": "Percentage CPU",
"threshold": "80"
}
}
}
Section J – Monitoring Best Practices
The 4 Golden Signals (Google SRE)
The 4 golden signals are the most important metrics to monitor for any service:
| Signal | Definition | Example Metrics |
|---|---|---|
| Latency | Time to process a request | p50, p95, p99 of DurationMs |
| Traffic | Load on the system | Requests/sec, messages/sec, bytes/sec |
| Errors | Rate of failed requests | HTTP 5xx rate, exceptions/min |
| Saturation | Resource utilization | CPU %, memory %, connection pool |
quadrantChart
title Monitoring priority by impact and complexity
x-axis Low complexity --> High complexity
y-axis Low impact --> High impact
quadrant-1 "Do first"
quadrant-2 "Plan"
quadrant-3 "Deprioritize"
quadrant-4 "Automate"
HTTP Error Rate: [0.2, 0.9]
CPU Alerts: [0.15, 0.7]
Latency p99: [0.3, 0.85]
Log Retention: [0.5, 0.4]
Distributed Tracing: [0.75, 0.8]
Custom Dashboards: [0.6, 0.5]
Prometheus Integration: [0.8, 0.6]
NSG Flow Logs: [0.55, 0.35]
SLI / SLO / SLA – Definitions
| Term | Definition | Example |
|---|---|---|
| SLI (Service Level Indicator) | Concrete measured metric | HTTP request success rate |
| SLO (Service Level Objective) | Internal reliability target | 99.9% of requests succeed |
| SLA (Service Level Agreement) | Contractual customer commitment | 99.9% uptime guaranteed (with penalties) |
| Error Budget | Remaining downtime tolerance | 8.7 hours/year for SLO 99.9% |
// Real-time SLI calculation (success rate)
AppRequests
| where TimeGenerated > ago(24h)
| summarize
TotalRequests = count(),
SuccessfulRequests = countif(Success == true)
by bin(TimeGenerated, 1h)
| extend SLI = round(100.0 * SuccessfulRequests / TotalRequests, 3)
| extend SLO_Target = 99.9
| extend WithinSLO = SLI >= SLO_Target
| render timechart
Preventing Alert Fatigue
Alert fatigue occurs when a team receives too many irrelevant alerts and starts ignoring them.
Causes and Solutions
| Cause | Solution |
|---|---|
| Thresholds too aggressive | Use dynamic thresholds (machine learning) |
| Non-actionable alerts | Every alert must have an associated runbook |
| Alert duplication | Enable Smart Groups |
| No priority levels | Define severities (Sev 0 = wake up at 3am) |
| Alerts without context | Add description + runbook link + custom properties |
Recommended Severity Hierarchy
| Severity | Level | Expected Response | Example |
|---|---|---|---|
| Sev 0 | Critical | Immediate 24/7 intervention | Total production outage |
| Sev 1 | Error | Response < 15 min (extended business hours) | Error rate > 5% |
| Sev 2 | Warning | Response < 1h during business hours | CPU > 80% for 10 min |
| Sev 3 | Informational | Daily review | Successful deployment |
| Sev 4 | Verbose | Weekly review | Backup completed |
Monitoring Checklist for a New Application
□ Application Insights enabled (SDK or auto-instrumentation)
□ Log Analytics Workspace configured
□ Diagnostic Settings enabled on all resources
□ Metric alerts: CPU, memory, HTTP errors
□ KQL log alerts: critical exceptions, error patterns
□ Availability tests (URL ping at minimum)
□ Operational dashboard shared with the team
□ Action Groups configured (email + Teams/Slack webhook)
□ Service Health Alerts enabled
□ Log retention defined according to compliance requirements
□ Runbooks documented for each Sev 0/1 alert
□ SLOs defined and SLI/Error Budget dashboard created
Recommended Monitoring Architecture
flowchart TD
subgraph Prod["Production"]
APP["Application\n(Application Insights SDK)"]
VM["VMs / AKS\n(Azure Monitor Agent)"]
DB["Azure SQL / Cosmos"]
NET["Virtual Network\n(NSG Flow Logs)"]
end
subgraph Monitoring["Monitoring Platform"]
AI_WS["Application Insights\nWorkspace"]
LAW["Log Analytics\nWorkspace"]
METRICS["Azure Monitor\nMetrics Store"]
end
subgraph Alerting["Alerts & Actions"]
RULES["Alert Rules\n(Metric + Log + Activity)"]
SG["Smart Groups"]
AG_OPS["Action Group\nOps Team"]
AG_EXEC["Action Group\nExec / Stakeholders"]
end
subgraph Visualize["Visualization"]
WB["Azure Workbooks\n(Ops Dashboard)"]
DASH["Shared Dashboard\n(Executive View)"]
PBI["Power BI\n(Monthly Reporting)"]
end
subgraph Respond["Response"]
SN["ServiceNow\nIncident"]
RUNBOOK["Automation\nRunbook"]
AS["Autoscale"]
end
APP --> AI_WS
VM --> LAW
DB --> LAW
NET --> LAW
APP --> METRICS
VM --> METRICS
AI_WS --> RULES
LAW --> RULES
METRICS --> RULES
RULES --> SG --> AG_OPS --> SN
SG --> AG_OPS --> RUNBOOK
METRICS --> AS
AI_WS --> WB
LAW --> WB
WB --> DASH
LAW --> PBI
Section K – Review Questions
KQL and Monitoring Questions
Q1. What KQL query finds the 5 most time-consuming operations in Application Insights?
Answer
AppRequests
| where TimeGenerated > ago(24h)
| top 5 by DurationMs desc
| project TimeGenerated, Name, DurationMs, ResultCode, ClientIP
Q2. How do you calculate the hourly error rate over the last 24 hours with KQL?
Answer
AppRequests
| where TimeGenerated > ago(24h)
| summarize
Total = count(),
Errors = countif(Success == false)
by bin(TimeGenerated, 1h)
| extend ErrorRate = round(100.0 * Errors / Total, 2)
| render timechart
Q3. What is the difference between a metric alert and a log alert in Azure Monitor?
Answer
| Criterion | Metric alert | Log alert |
|---|---|---|
| Source | Metrics Store (time-series) | Log Analytics (KQL) |
| Latency | Near real-time (< 1 min) | Log ingestion delay (2-5 min) |
| Thresholds | Static or dynamic (ML) | Based on KQL results |
| Complexity | Simple (1 condition) | Complex (joins, aggregations) |
| Cost | Less expensive | More expensive to evaluate frequently |
Q4. What is a Data Collection Rule (DCR) and why use it?
Answer
A DCR is a rule that defines what data to collect, how to transform it, and where to send it from a source (VM, container, etc.). Advantages:
- Fine-grained granularity per resource (different rules per VM type)
- Filtering and transforming data before ingestion (cost reduction)
- Associatable with multiple different workspaces
- Centralized management via ARM/Bicep/Terraform
Q5. You want to be alerted if an Azure VM has not sent a heartbeat for more than 15 minutes. Write the KQL query and describe the alert configuration.
Answer
// KQL query for the alert
Heartbeat
| summarize LastHeartbeat = max(TimeGenerated) by Computer
| extend TimeSinceLast = now() - LastHeartbeat
| where TimeSinceLast > 15m
| project Computer, LastHeartbeat, TimeSinceLast
Alert configuration:
- Type: Log alert
- Evaluation frequency: every 5 minutes
- Lookback: last 20 minutes
- Threshold: Result count > 0 (at least one VM without heartbeat)
- Severity: Error (Sev 1)
- Action Group: Ops Team (email + Teams webhook)
Q6. What is the difference between Azure Service Health and Azure Resource Health?
Answer
- Azure Service Health: Issues on Microsoft’s side affecting Azure services globally or regionally (outages, planned maintenance, advisories). Microsoft must act.
- Azure Resource Health: Health state of your specific resource. Can be “Available”, “Degraded”, “Unavailable”, “Unknown”. You or Microsoft must act depending on the case.
Example: An Azure SQL outage in East US = Service Health issue. Your specific Azure SQL instance being degraded = Resource Health.
Q7. How do you configure Application Insights to reduce ingestion costs while maintaining data representativeness?
Answer
Use adaptive sampling (enabled by default) which automatically maintains ~5 requests/second. For more control:
// applicationinsights.json
{
"sampling": {
"percentage": 10
}
}
Or via SDK:
builder.Services.AddApplicationInsightsTelemetry(options => {
options.EnableAdaptiveSampling = true;
options.MaxTelemetryItemsPerSecond = 5;
});
Important: Sampling is consistent by OperationId, so a request and all its associated dependencies/exceptions are sampled together.
Q8. Explain the concept of Error Budget in the SRE/SLO context.
Answer
The Error Budget is the amount of downtime tolerated over a given period without violating the SLO.
Calculation: $$\text{Error Budget} = (1 - \text{SLO}) \times \text{Period}$$
Example with SLO = 99.9% over 30 days: $$\text{Error Budget} = 0.001 \times 30 \times 24 \times 60 = 43.2 \text{ minutes}$$
Usage:
- Budget available → team can take risks (deployments, experiments)
- Budget exhausted → deployment freeze, focus on reliability only
Q9. What KQL command joins Application Insights exceptions with the HTTP requests that generated them?
Answer
AppRequests
| where TimeGenerated > ago(1h)
| where Success == false
| join kind=inner (
AppExceptions
| where TimeGenerated > ago(1h)
| project ExceptionType, Message, OperationId, SeverityLevel
) on OperationId
| project TimeGenerated, Name, DurationMs, ResultCode, ExceptionType, Message
| order by TimeGenerated desc
Q10. How do you pin an Azure Monitor metrics chart to a shared dashboard?
Answer
- Go to Metrics Explorer → Configure the chart (metric, aggregation, time range).
- Click Pin to dashboard (pin icon at the top right).
- Select the target dashboard (existing or new).
- Go to Dashboard → Share to share with colleagues via RBAC.
Or via Azure Workbooks: create a Workbook with the chart → the entire Workbook can be pinned as a tile in a dashboard.
Q11. What is distributed tracing in Application Insights and how does it work?
Answer
Distributed tracing allows following a user request across all microservices it traverses.
Mechanism:
- Each request receives a unique
OperationId(W3C Trace Context:traceparentheader). - This header is propagated automatically between services (HTTP, Service Bus, Event Hub).
- All chain components (requests, dependencies, exceptions) share the same
OperationId. - The Application Map visualizes these relationships graphically.
// See the full call chain for a transaction
union AppRequests, AppDependencies, AppExceptions, AppTraces
| where OperationId == "abc123def456"
| order by TimeGenerated asc
| project TimeGenerated, itemType, Name, DurationMs, Success, Target
Q12. Your team receives 200 alerts per day and has started ignoring them. What are the 5 priority actions to address alert fatigue?
Answer
- Enable Smart Groups: Azure Monitor automatically groups correlated alerts, reducing noise by up to 90%.
- Review thresholds: Switch to dynamic thresholds (machine learning) to eliminate false positives based on normal variations.
- Relevance audit: For each alert, ask “Can we act immediately?” If not, remove it or downgrade to Sev 3/4.
- Deduplication: Check for overlapping evaluation periods that create duplicates. Use alert suppression during maintenance windows.
- Mandatory runbooks: Every Sev 0/1 alert must have a documented runbook. Alerts without a runbook indicate they are not yet production-ready.
Final Summary – Key Enriched Concepts
| Concept | Key Points |
|---|---|
| Azure Monitor | Central hub: collects metrics + logs from all Azure/hybrid sources |
| Diagnostic Settings | Bridge between Azure resource and destination (Log Analytics / Storage / Event Hub) |
| Data Collection Rules | Granular collection and transformations before ingestion |
| Log Analytics KQL | where → project → summarize → join → extend → render |
| Application Insights | Full APM: traces, availability, live metrics, application map, sampling |
| Distributed Tracing | End-to-end tracking by OperationId across all microservices |
| Metric Alerts | Real-time, static or dynamic (ML) thresholds, low latency |
| Log Alerts | Flexible KQL, complex detection, slightly slower |
| Smart Groups | AI alert correlation → reduces alert fatigue |
| Action Groups | Reusable: email, SMS, webhook, ITSM, Function, Logic App |
| Service Health | Proactive Microsoft incidents → mandatory alert configuration |
| Resource Health | Individual resource health (you may need to act) |
| Network Watcher | NSG Flow Logs, Traffic Analytics, Connection Monitor, Topology |
| Workbooks | Parameterizable interactive reports with KQL + metrics + text |
| 4 Golden Signals | Latency · Traffic · Errors · Saturation |
| SLI/SLO/SLA | SLI = measured metric, SLO = internal target, SLA = customer contract |
| Error Budget | $(1 - SLO) \times \text{period}$ = downtime tolerance |
| Alert Fatigue | Smart Groups + dynamic thresholds + runbooks + severity hierarchy |
Search Terms
azure · fundamentals · monitoring · core · infrastructure · microsoft · alerts · log · kql · alert · analytics · integration · metrics · monitor · application · architecture · dashboards · data · groups · health · service · types · workbooks · action