Azure

Azure Monitor and Application Insights: Complete Observability

Azure Monitor and Application Insights: Complete Observability

options.ConnectionString = builder.Configuration["ApplicationInsights:ConnectionString"];
options.EnableAdaptiveSampling = true;
options.EnableQuickPulseMetricStream = true;```
});

var app = builder.Build();

// Middleware for request tracking
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();


**Custom Telemetry:**

```csharp
public class OrderController : ControllerBase
{
```csharp
private readonly TelemetryClient _telemetry;

public OrderController(TelemetryClient telemetry)
{
    _telemetry = telemetry;
}

[HttpPost]
public async Task<IActionResult> CreateOrder(Order order)
{
    using var operation = _telemetry.StartOperation<RequestTelemetry>("CreateOrder");
    
    try
    {
        // Custom event
        _telemetry.TrackEvent("OrderCreated", new Dictionary<string, string>
        {
            ["OrderId"] = order.Id,
            ["CustomerId"] = order.CustomerId,
            ["Amount"] = order.Total.ToString()
        });

        // Custom metric
        _telemetry.TrackMetric("OrderValue", order.Total);

        // Dependency tracking (auto-captured for HTTP/SQL)
        await _repository.SaveOrderAsync(order);

        return Ok(order);
    }
    catch (Exception ex)
    {
        _telemetry.TrackException(ex);
        operation.Telemetry.Success = false;
        throw;
    }
}```
}

Node.js:

const appInsights = require('applicationinsights');
appInsights.setup('InstrumentationKey=...')
```text
.setAutoDependencyCorrelation(true)
.setAutoCollectRequests(true)
.setAutoCollectPerformance(true)
.start();

const client = appInsights.defaultClient;

app.post('/orders', async (req, res) => {

client.trackEvent({ name: 'OrderCreated', properties: { orderId: req.body.id } });
client.trackMetric({ name: 'OrderValue', value: req.body.total });

try {
    await saveOrder(req.body);
    res.json({ success: true });
} catch (error) {
    client.trackException({ exception: error });
    res.status(500).json({ error: error.message });
}```
});

Step 3: KQL Queries for Insights

Failed Requests Analysis:

requests
| where success == false
| where timestamp > ago(24h)
| summarize FailureCount = count() by operation_Name, resultCode
| order by FailureCount desc
| take 10

Slow Request Identification:

requests
| where timestamp > ago(1h)
| where duration > 5000  // milliseconds
| project timestamp, operation_Name, duration, url
| order by duration desc

Dependency Performance:

dependencies
| where timestamp > ago(24h)
| summarize 
```text
AvgDuration = avg(duration),
P95Duration = percentile(duration, 95),
FailureRate = countif(success == false) * 100.0 / count()
by target, type```
| order by P95Duration desc

User Journey Tracking:

customEvents
| where timestamp > ago(7d)
| where name in ("ProductViewed", "AddedToCart", "CheckoutStarted", "OrderCompleted")
| summarize EventCount = count() by name
| render piechart

Funnel Analysis:

let startDate = ago(30d);
let endDate = now();
customEvents
| where timestamp between (startDate .. endDate)
| where name in ("ProductViewed", "AddedToCart", "CheckoutStarted", "OrderCompleted")
| summarize Users = dcount(user_Id) by name
| order by Users desc

Step 4: Distributed Tracing

View End-to-End Transaction:

union requests, dependencies, exceptions
| where operation_Id == "abc123..."
| project timestamp, itemType, name, duration, success
| order by timestamp asc

Service Map Visualization:

Application Insights → Investigate → Application Map

Detect Anomalies:

requests
| where timestamp > ago(7d)
| make-series RequestCount = count() default = 0 on timestamp step 1h
| extend anomalies = series_decompose_anomalies(RequestCount, 1.5)
| mv-expand timestamp to typeof(datetime), RequestCount to typeof(long), anomalies to typeof(double)
| where anomalies != 0

Step 5: Infrastructure Monitoring

VM Metrics:

az monitor metrics list \
  --resource /subscriptions/.../resourceGroups/rg-vms/providers/Microsoft.Compute/virtualMachines/vm-web \
  --metric "Percentage CPU" \
  --start-time 2025-08-04T00:00:00Z \
  --end-time 2025-08-04T23:59:59Z \
  --interval PT1H

Expected output:

{ "value": [{ "name": { "value": "Requests" }, "timeseries": [{ "data": [{ "total": 1234 }] }] }] }

Terminal output for az monitor

Container Insights (AKS):

ContainerLog
| where TimeGenerated > ago(1h)
| where ContainerName == "api-orders"
| where LogEntry contains "error"
| project TimeGenerated, LogEntry

VM Insights:

InsightsMetrics
| where TimeGenerated > ago(1h)
| where Name == "AvailableMB"
| summarize AvgMemoryMB = avg(Val) by Computer
| order by AvgMemoryMB asc

Step 6: Alerting Strategies

Metric Alert (CPU Threshold):

az monitor metrics alert create \
  --name "High CPU Alert" \
  --resource-group rg-monitoring \
  --scopes /subscriptions/.../resourceGroups/rg-web/providers/Microsoft.Web/sites/myapi \
  --condition "avg Percentage CPU > 80" \
  --window-size 5m \
  --evaluation-frequency 1m \
  --action /subscriptions/.../actionGroups/ops-team

Expected output:

{ "value": [{ "name": { "value": "Requests" }, "timeseries": [{ "data": [{ "total": 1234 }] }] }] }

Terminal output for az monitor

Log Alert (Error Rate):

// Alert query
requests
| where timestamp > ago(5m)
| summarize 
```text
TotalRequests = count(),
FailedRequests = countif(success == false)```
| extend ErrorRate = (FailedRequests * 100.0) / TotalRequests
| where ErrorRate > 5
az monitor scheduled-query create \
  --name "High Error Rate" \
  --resource-group rg-monitoring \
  --scopes /subscriptions/.../components/myapi-insights \
  --condition "count > 0" \
  --condition-query "requests | where timestamp > ago(5m) | where success == false | count" \
  --window-size 5m \
  --evaluation-frequency 5m \
  --severity 2 \
  --action /subscriptions/.../actionGroups/ops-team

Expected output:

{ "value": [{ "name": { "value": "Requests" }, "timeseries": [{ "data": [{ "total": 1234 }] }] }] }

> **Architecture Overview:** ![Terminal output for az monitor]( images articles azure 2025 08 04 azure monitor application insights complete observability terminal 3.svg)

{
  "properties": {
```text
"lenses": [
  {
    "parts": [
      {
        "position": { "x": 0, "y": 0, "colSpan": 6, "rowSpan": 4 },
        "metadata": {
          "type": "Extension/Microsoft_Azure_Monitoring/PartType/MetricsChartPart",
          "settings": {
            "content": {
              "metrics": [
                {
                  "resourceId": "/subscriptions/.../components/myapi-insights",
                  "name": "requests/count",
                  "aggregationType": "Count"
                }
              ],
              "title": "Request Rate"
            }
          }
        }
      }
    ]
  }
]```
  }
}

Workbook for Executive Summary:

// Active users
customEvents
| where timestamp > ago(30d)
| summarize ActiveUsers = dcount(user_Id)

// Request success rate
requests
| where timestamp > ago(30d)
| summarize 
```text
TotalRequests = count(),
SuccessfulRequests = countif(success == true)```
| extend SuccessRate = (SuccessfulRequests * 100.0) / TotalRequests

Step 8: Cost Optimization

Sampling Configuration:

builder.Services.Configure<TelemetryConfiguration>(config =>
{
```text
config.DefaultTelemetrySink.TelemetryProcessorChainBuilder
    .UseAdaptiveSampling(maxTelemetryItemsPerSecond: 5)
    .Build();```
});

Data Retention:

az monitor log-analytics workspace update \
  --resource-group rg-monitoring \
  --workspace-name logs-workspace \
  --retention-time 90

Expected output:

{ "value": [{ "name": { "value": "Requests" }, "timeseries": [{ "data": [{ "total": 1234 }] }] }] }

Terminal output for az monitor

Cap Daily Ingestion:

az monitor app-insights component update \
  --app myapi-insights \
  --resource-group rg-monitoring \
  --cap 5  # GB per day

Expected output:

{ "value": [{ "name": { "value": "Requests" }, "timeseries": [{ "data": [{ "total": 1234 }] }] }] }

Terminal output for az monitor

Advanced Patterns

Pattern 1: Composite Alerts (Multiple Conditions)

Advanced Patterns

let errorRate = requests
```text
| where timestamp > ago(5m)
| summarize ErrorRate = countif(success == false) * 100.0 / count();```
let highCpu = performanceCounters
```text
| where timestamp > ago(5m)
| where counterName == "% Processor Time"
| summarize AvgCPU = avg(counterValue);```
errorRate
| join kind=inner highCpu on $left.timestamp == $right.timestamp
| where ErrorRate > 5 and AvgCPU > 80

Pattern 2: Proactive Autoscaling

az monitor autoscale create \
  --resource-group rg-web \
  --resource /subscriptions/.../sites/myapi \
  --min-count 2 \
  --max-count 10 \
  --count 2 \
  --scale-out-cooldown 5 \
  --scale-in-cooldown 5

az monitor autoscale rule create \
  --resource-group rg-web \
  --autoscale-name myapi-autoscale \
  --condition "Percentage CPU > 75 avg 5m" \
  --scale out 1

Expected output:

{ "value": [{ "name": { "value": "Requests" }, "timeseries": [{ "data": [{ "total": 1234 }] }] }] }

Terminal output for az monitor

Pattern 3: Live Metrics Stream

// Enable Live Metrics
builder.Services.AddApplicationInsightsTelemetry(options =>
{
```text
options.EnableQuickPulseMetricStream = true;```
});

Troubleshooting

Issue: No telemetry appearing
Solution: Verify connection string; check firewall rules; ensure SDK version compatibility

Troubleshooting

Issue: High ingestion costs
Solution: Enable adaptive sampling; filter noisy telemetry; reduce retention period

Issue: Missing dependency data
Solution: Ensure SQL/HTTP auto-instrumentation enabled; check dependency tracking configuration

Best Practices

  • Use structured logging (ILogger with scopes)
  • Implement custom events for business metrics
  • Set appropriate sampling rates (5-10 items/sec for most apps)
  • Create actionable alerts (avoid alert fatigue)
  • Use workbooks for stakeholder reporting
  • Regularly review and optimize KQL queries
  • Tag resources with environment/owner for filtering

Best Practices

Architecture Decision and Tradeoffs

When designing cloud infrastructure solutions with Azure, consider these key architectural trade-offs:

Approach Best For Tradeoff
Managed / platform service Rapid delivery, reduced ops burden Less customisation, potential vendor lock-in
Custom / self-hosted Full control, advanced tuning Higher operational overhead and cost

Recommendation: Start with the managed approach for most workloads and move to custom only when specific requirements demand it.

Validation and Versioning

  • Last validated: April 2026
  • Validate examples against your tenant, region, and SKU constraints before production rollout.
  • Keep module, CLI, and SDK versions pinned in automation pipelines and review quarterly.

Security and Governance Considerations

  • Apply least-privilege access using RBAC roles and just-in-time elevation for admin tasks.
  • Store secrets in managed secret stores and avoid embedding credentials in scripts or source files.
  • Enable audit logging, data protection policies, and periodic access reviews for regulated workloads.

Cost and Performance Notes

  • Define budgets and alerts, then monitor usage and cost trends continuously after go-live.
  • Baseline performance with synthetic and real-user checks before and after major changes.
  • Scale resources with measured thresholds and revisit sizing after usage pattern changes.

Official Microsoft References

Public Examples from Official Sources

Key Takeaways

  • Application Insights provides automatic instrumentation for .NET/Node.js/Java.
  • KQL enables powerful log analysis and correlation.
  • Smart Detection identifies anomalies without manual configuration.
  • Distributed tracing visualizes end-to-end request flows.

Key Takeaways

Next Steps

  • Implement SLA-based alerts with multi-resource queries
  • Explore Azure Monitor for containers (AKS insights)
  • Integrate with Azure DevOps for deployment tracking

Additional Resources


Is your system observable enough to debug production issues?
```

AI Assistant
AI Assistant

Article Assistant

Ask me about this article

AI
Hi! I'm here to help you understand this article. Ask me anything about the content, concepts, or implementation details.