Skip to content

Azure Monitor & Application Insights

Key Points

  • Azure Monitor umbrella covers logs (Log Analytics), metrics, alerts. Application Insights = APM layer for .NET apps.
  • Modern integration: Azure Monitor OpenTelemetry DistroOTel-based, replaces classic ApplicationInsights SDK. Auto-instruments ASP.NET, HttpClient, EF, SQL, Service Bus.
  • KQL (Kusto Query Language) for log queries. SQL-ish; very powerful.
  • Live Metrics stream — real-time view of running app.
  • Alerts: metric, log, activity log. Action groups for notifications (email, Teams, webhook, Logic App).

Concepts (deep dive)

What Azure Monitor and Application Insights are

These names confuse everyone, and the relationship matters: Azure Monitor is the umbrella platform — the place every Azure resource sends its telemetry — and Application Insights is one specific feature inside it, focused on application-level APM (requests, dependencies, traces, exceptions for your .NET app code). They share storage (Log Analytics workspaces), share query language (KQL), share alerting, and increasingly share an ingestion path (OpenTelemetry).

   ┌────────────────────────────────────────────────────────────────┐
   │                       Azure Monitor                            │
   │                                                                │
   │   ┌──────────────────┐   ┌──────────────────┐                  │
   │   │  Metrics platform │   │  Logs (Log       │                  │
   │   │  (time-series)    │   │  Analytics       │                  │
   │   │                   │   │  workspace)      │                  │
   │   │   dashboards      │   │                  │                  │
   │   │   alerts          │   │   KQL queries    │                  │
   │   └──────────────────┘   └────────┬─────────┘                  │
   │                                   │                            │
   │     ┌─────────────────────────────┴─────────────────────────┐  │
   │     │            Application Insights                       │  │
   │     │            (APM for your app)                         │  │
   │     │                                                       │  │
   │     │   requests, dependencies, traces, exceptions,         │  │
   │     │   customMetrics, Live Metrics stream                  │  │
   │     │   ▲                                                   │  │
   │     │   │  ingested via OpenTelemetry (modern) or           │  │
   │     │   │  ApplicationInsights SDK (legacy)                 │  │
   │     └───┼───────────────────────────────────────────────────┘  │
   │         │                                                      │
   │         │                                                      │
   │    .NET app                                                    │
   └────────────────────────────────────────────────────────────────┘

The mental model: telemetry from resources (VMs, App Service plans, AKS clusters, the platform itself) flows into Azure Monitor as platform metrics + activity logs; telemetry from your code (HTTP requests, SQL calls, custom events) flows into Application Insights via OpenTelemetry. Both end up in the same workspace, queryable side-by-side in KQL — which is how a senior engineer correlates "the app's p99 spiked at 10:32" with "the VMSS scale event happened at 10:31."

From the classic SDK to OpenTelemetry

Application Insights had its own .NET SDK for years (Microsoft.ApplicationInsights.AspNetCore). The modern path is the Azure Monitor OpenTelemetry Distro — a thin layer over the standard OpenTelemetry SDK that configures the right exporter and the right semantic conventions for App Insights. You write OTel code; the distro ships it to Azure. Same telemetry shows up; same KQL queries work; but your code is now portable to any OTel backend (Jaeger, Honeycomb, Grafana Tempo) by swapping the exporter. For new code in 2026: OTel distro, not the classic SDK.

Setup with OTel distro

builder.Services.AddOpenTelemetry()
    .UseAzureMonitor(o => o.ConnectionString = "InstrumentationKey=...");

One line; auto-instruments traces, metrics, logs. Sends to Application Insights via OTLP.

Connection string

InstrumentationKey=<guid>;IngestionEndpoint=https://<region>.in.applicationinsights.azure.com/

Replaces the older InstrumentationKey alone. Connection string supports regional endpoints.

KQL basics

Kusto Query Language is the query language of Azure Monitor / Log Analytics / App Insights. It reads like a Unix pipe — start with a table, push it through filters, joins, aggregations, and visualizations. Learn three commands (where, summarize, join) and you can answer ~80% of operational questions. KQL is also what every alert and dashboard is built on, so understanding it is the difference between "I have observability" and "I have a dashboard nobody can read."

requests
| where timestamp > ago(1h)
| where success == false
| summarize count() by resultCode, bin(timestamp, 5m)
| render timechart
// p95 latency by endpoint
requests
| summarize percentiles(duration, 95, 99) by name
| order by percentile_duration_99 desc
// Slow queries with related traces
dependencies
| where type == "SQL" and duration > 1000
| join (traces) on operation_Id

Tables in App Insights

Table Content
requests Incoming HTTP requests
dependencies Outgoing calls (HTTP, DB, custom)
traces Logs
exceptions Errors
customEvents App-defined
customMetrics App-defined metrics
availabilityResults Synthetic monitoring
performanceCounters OS/CLR counters

Live Metrics

.UseAzureMonitor()   // includes Live Metrics

Real-time view: incoming/outgoing per-second, failures, dependencies. Browser dashboard updates ~1s.

Alerts

Three types: - Metric alerts: scalar thresholds (CPU > 80%). - Log alerts: KQL query results trigger. - Activity Log alerts: ARM events.

resource alert 'Microsoft.Insights/scheduledQueryRules@2023-12-01' = {
  name: 'high-failure-rate'
  properties: {
    severity: 2
    enabled: true
    evaluationFrequency: 'PT5M'
    windowSize: 'PT5M'
    criteria: {
      allOf: [{
        query: 'requests | where success == false | count'
        operator: 'GreaterThan'
        threshold: 100
      }]
    }
    actions: { actionGroups: [actionGroupId] }
  }
}

Action groups

  • Email
  • SMS
  • Voice
  • Webhook
  • Azure Function / Logic App
  • ITSM connector

Workspaces

Subscription → Log Analytics workspace → App Insights component

Modern: workspace-based App Insights. Logs land in shared workspace; cross-resource queries.

Sampling

.UseAzureMonitor(o =>
{
    o.SamplingRatio = 0.1f;   // 10%
});

Reduces ingestion cost. Errors usually always sampled.

Adaptive sampling: dynamically reduces under load.

Correlation

W3C TraceContext. Activity flows across services. AppInsights joins by operation_Id.

Dashboards & Workbooks

  • Dashboards: pinned tiles; Azure Portal.
  • Workbooks: rich, parameterized reports. KQL + visualizations.

Custom metrics & events

private static readonly Meter _meter = new("MyApp.Orders");
private static readonly Counter<long> _placed = _meter.CreateCounter<long>("orders.placed");

_placed.Add(1, new TagList { { "type", "online" } });

OTel meters automatically flow to App Insights.

Distributed tracing

Auto with OTel. Click a request → see all dependencies in tree:

GET /orders                 250ms
├─ SQL Server (orders)       30ms
├─ HTTP GET /products       180ms
│   └─ SQL Server          120ms
└─ Service Bus publish      20ms

Diagnostic settings

resource diag 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
  scope: cosmosDb
  properties: {
    logs: [{ category: 'DataPlaneRequests', enabled: true }]
    workspaceId: laWorkspaceId
  }
}

Stream Azure resource logs (Cosmos, Key Vault, Storage) to Log Analytics. KQL on top.

Cost management

  • Sampling reduces ingestion.
  • Daily cap on workspace.
  • Retention tier (interactive 30-90 days; archive cheaper).

Migration from classic SDK

Old:

builder.Services.AddApplicationInsightsTelemetry();

New:

builder.Services.AddOpenTelemetry().UseAzureMonitor();

Migrate for: vendor-neutral; cross-platform; better OTel ecosystem.

Synthetic monitoring (availability tests)

resource webTest 'Microsoft.Insights/webtests@2022-06-15' = { /* ... */ }

Periodic HTTP pings from global locations. Multi-step transaction tests. Alerts on failure.


Code: correct vs wrong

❌ Wrong: classic SDK in new app

builder.Services.AddApplicationInsightsTelemetry();

✅ Correct: OTel distro

builder.Services.AddOpenTelemetry().UseAzureMonitor();

❌ Wrong: no sampling at high volume

Cost spike on traffic burst.

✅ Correct: adaptive sampling

OTel distro applies it by default.


Design patterns for this topic

Pattern 1 — "OTel distro for new apps"

  • Intent: vendor-neutral; modern.

Pattern 2 — "Workspace-based App Insights"

  • Intent: cross-resource KQL.

Pattern 3 — "Sampling for cost"

  • Intent: scale ingestion.

Pattern 4 — "Workbooks for dashboards"

  • Intent: parameterized rich reports.

Pattern 5 — "Diagnostic settings to Log Analytics"

  • Intent: unified observability across Azure.

Pros & cons / trade-offs

Aspect Pros Cons
Azure Monitor All Azure native Azure-coupled
App Insights Rich .NET APM Cost at scale
KQL Powerful queries Learning curve
Adaptive sampling Cost control Some loss

When to use / when to avoid

  • Use for Azure-native apps.
  • Use OTel distro for new apps.
  • Avoid classic SDK in greenfield.
  • Avoid unbounded ingestion — sample.

Interview Q&A

Q1. Azure Monitor vs App Insights? Azure Monitor is the umbrella (logs/metrics/alerts/diagnostics). App Insights is the APM layer.

Q2. Modern .NET App Insights setup? AddOpenTelemetry().UseAzureMonitor(). OTel distro replaces classic SDK.

Q3. KQL? Kusto Query Language. SQL-ish but more powerful for time-series logs.

Q4. Live Metrics? Real-time per-second telemetry stream from running app.

Q5. Sampling? Reduce ingestion. Adaptive scales with load. Errors usually preserved.

Q6. Workbooks? Parameterized rich reports with KQL + visualization.

Q7. Tables in App Insights? requests, dependencies, traces, exceptions, customMetrics, availabilityResults.

Q8. Diagnostic settings? Stream Azure resource logs into Log Analytics. KQL across.

Q9. Alert types? Metric, log, activity log.

Q10. Cost optimization? Sampling, daily cap, archive tier, exclude noisy categories.

Q11. Synthetic monitoring? Periodic HTTP pings; multi-step tests. Availability monitoring.

Q12. Cross-resource queries? Workspace-based App Insights enables cross-resource KQL.


Gotchas / common mistakes

  • ⚠️ Classic SDK in new code.
  • ⚠️ No sampling — runaway ingestion.
  • ⚠️ High-cardinality custom metrics — series explosion.
  • ⚠️ No alerts — outages unnoticed.
  • ⚠️ Default 90-day retention — costly; tune.

Further reading