Study guide
12.4 KQL for Metrics & Troubleshooting Scenarios
Exam AI-200: Developing AI Cloud Solutions on Azure Exam
Track your progress as you read
Finished sections get a check mark.
1 Introduction & Exam Overview
1.1 Current Exam Facts 1.2 Audience Profile & Study Path
2 Chapter 1: Container Registry & App Service Hosting
1.1 ACR: Build, Store, Version & Manage Images 1.2 ACR Tasks: Build & Run Images 1.3 Deploy Containers to Azure App Service
3 Chapter 2: Azure Container Apps & KEDA Scaling
2.1 Azure Container Apps: Environments, Config & Revisions 2.2 KEDA Event-Driven Scaling in Container Apps
4 Chapter 3: AKS Manifests & Container Troubleshooting
3.1 Deploy & Manage Apps on AKS with Manifests 3.2 Monitor & Troubleshoot AKS and Container Apps
5 Chapter 4: Cosmos DB for NoSQL Fundamentals
4.1 Cosmos DB for NoSQL: SDK Connect & Queries 4.2 Optimize RUs: Indexing Policies & Consistency Levels
6 Chapter 5: Cosmos DB Vectors & Change Feed
5.1 Embeddings & Vector Similarity Search in Cosmos DB 5.2 Change Feed Processor for New/Updated Items
7 Chapter 6: Azure PostgreSQL Foundations for AI
6.1 Azure Database for PostgreSQL: Connect & Query with SDKs 6.2 Schema Design, Data Types & Indexing Strategies 6.3 pgvector Indexing: Latency & Compute Overhead
8 Chapter 7: PostgreSQL Vector Workloads & RAG
7.1 Configure Compute, Memory & Storage for Vector Workloads 7.2 Vector Search, Semantic Retrieval & RAG with Metadata Filters 7.3 Connection Optimization for Throughput & Latency
9 Chapter 8: Azure Managed Redis for AI Solutions
8.1 Azure Managed Redis: Caching, Expiration & Invalidation 8.2 Redis Vector Indexing for Similarity Search
10 Chapter 9: Service Bus & Event Grid for AI Pipelines
9.1 Service Bus Queues & Message Processing 9.2 Topics, Subscriptions & Dead-Letter Queues 9.3 Event Grid: Custom Events & Filters 9.4 Event Grid Retries & Event-Driven Workflows
11 Chapter 10: Azure Functions for Serverless AI Back Ends
10.1 Azure Functions: Triggers & Bindings 10.2 Build Serverless APIs with Functions 10.3 Configure & Deploy Function Apps
12 Chapter 11: Key Vault & App Configuration
11.1 Azure Key Vault: Secret Storage & Retrieval 11.2 Key Vault Secret Rotation Patterns 11.3 Azure App Configuration for App Settings
13 Chapter 12: OpenTelemetry & KQL Observability
12.1 Distributed Tracing with OpenTelemetry SDKs 12.2 Correlating Traces into Azure Monitoring 12.3 Write KQL Queries to Analyze Logs 12.4 KQL for Metrics & Troubleshooting Scenarios
12.4 KQL for Metrics & Troubleshooting Scenarios
Key Takeaways Explain This Topic AI
Use KQL on AppMetrics and dependency/request duration aggregates to analyze metrics—not only raw log lines.
Troubleshoot AI pipelines by splitting latency across AppDependencies targets (retrieval vs model vs cache vs bus).
Percentiles (p95/p99), bin() timecharts, and countif error rates reveal systemic regressions after deployments.
Combine metrics signals with operation_Id drills when a spike needs a root-cause example.
Common AI failure modes—timeouts, 429s, cold starts, cache misses—have recognizable KQL signatures.
Last updated: July 2026
From logs to metrics-minded troubleshooting
Section 12.3 focused on log/trace tables. AI-200 also asks you to analyze metrics and apply KQL in realistic troubleshooting scenarios —especially latency and errors in multi-stage AI pipelines. Metrics tell you whether a problem is widespread; traces/logs tell you why a representative operation failed.
Metrics sources in Log Analytics
- Source What you query Good for
- AppMetrics Custom/OTel metrics exported to Application Insights Token usage, queue depth, cache hit ratio
- AppRequests aggregates avg , percentile on DurationMs API SLO burn
- AppDependencies aggregates Duration and success by Target / Type Model vs DB vs Redis contribution
Azure Monitor metrics (when in workspace) Platform metrics via specific tables/solutions CPU, replica count, KEDA scale signals
Even if a stem says “metrics,” duration percentiles from requests/dependencies are valid metric-style analysis.
- Core aggregations for latency
- Average alone hides tail latency. Prefer percentiles for user-facing AI APIs: AppRequests
- | where TimeGenerated > ago(4h)
- | where Name == "POST /chat"
- | summarize
- count(),
- avg(DurationMs),
- p50=percentile(DurationMs, 50),
- p95=percentile(DurationMs, 95),
- p99=percentile(DurationMs, 99),
- failures=countif(Success == false)
- Time-bin to see when the regression started: AppDependencies
- | where TimeGenerated > ago(6h)
- | where Target has "openai"
- | summarize p95=percentile(DurationMs, 95), errors=countif(Success == false) by bin(TimeGenerated, 10m)
- | order by TimeGenerated asc
A step-change at a deployment timestamp is a strong exam clue: correlate with revision change, model deployment update, or prompt size increase.
Split the AI pipeline by dependency target
Map stages to dependency targets (names vary by SDK instrumentation):
- Pipeline stage Typical dependency signal Failure signature
- Cache lookup Redis target Timeouts; sudden miss storms raising DB load
- Vector retrieval Postgres/Cosmos dependency Slow queries after index change; throttling
- Model inference Azure OpenAI / HTTP host 429 rate limits; 5xx; multi-second durations
- Messaging Service Bus / Event Grid Send failures; consumer lag (separate metrics)
- Downstream tools External HTTP APIs DNS/TLS/timeouts
- Example KQL: AppDependencies
- | where TimeGenerated > ago(2h)
- | summarize
- calls=count(),
- p95=percentile(DurationMs, 95),
- err=countif(Success == false)
- by Type, Target
- | order by p95 desc
If model Target p95 is 7s and Postgres is 50ms, do not “optimize the index” first—address model latency, quota, or prompt size.
Custom metrics (tokens, hits, queue depth)
When OTel meters export custom metrics into AppMetrics (schema fields vary slightly by ingestion path), summarize by metric name and dimensions: AppMetrics
- | where TimeGenerated > ago(1h)
- | where Name in ("gen_ai.client.token.usage", "cache_hit", "jobs_queue_depth")
- | summarize Total=sum(Sum), Samples=sum(Count) by Name, bin(TimeGenerated, 5m)
Exam takeaway: custom metrics are how you watch token burn and cache effectiveness —signals that raw HTTP status codes alone may not show.
- Troubleshooting playbooks
- 1) Sudden latency spike after deploy
Chart AppRequests p95 by bin(TimeGenerated, 5m) around the deploy time.
Split AppDependencies p95 by Target for the same window.
Pick one slow operation_Id from AppRequests ordered by DurationMs desc .
Join traces/exceptions for that ID.
Confirm whether a new revision, larger context window, or cold start pattern explains it.
- 2) Elevated error rate with 429s AppDependencies
- | where TimeGenerated > ago(3h)
- | where ResultCode == "429" or ResultCode == 429
- | summarize count() by bin(TimeGenerated, 5m), Target
Then verify request volume on AppRequests did not simply triple. Remediation themes: quota, concurrency limits, backoff, caching embeddings, batching.
3) Timeouts only on first requests (cold start)
Look for long durations on Functions or scale-from-zero Container Apps shortly after idle periods. Metrics may show instance count rising from zero; dependencies may be fine once warm. Solutions include min replicas, preload, or accepting warm-up SLOs—not blind Postgres scaling.
4) Cache miss amplification
If Redis dependency errors rise or cache hit custom metrics fall, Postgres/Cosmos dependency volume often rises in the same bins. Join the timeline: AppDependencies
| where TimeGenerated > ago(2h)
| summarize RedisCalls=countif(Type has "Redis"), DbCalls=countif(Type has "SQL" or Target has "postgres") by bin(TimeGenerated, 5m)
Inverse movement (Redis down, DB up) is a classic amplification signature.
5) Worker lag in async generation
API requests succeed quickly (enqueue only) while users wait on job status. Investigate worker AppRequests / AppDependencies separately by cloud role name , and check Service Bus metrics or custom jobs_queue_depth . Application Map should show both roles if propagation is correct.
Operator reminder for metric scenarios
- Need Operators
- Restrict window where TimeGenerated > ago(...)
- Aggregate summarize with avg , percentile , countif , sum
- Time series by bin(TimeGenerated, …)
- Compare stages by Target / by Name / by cloud_RoleName
- Attach evidence join to traces on operation_Id
- Lean output project columns stakeholders need
- Scenario: end-to-end AI incident
- Team Nova runs a RAG chat API on Container Apps with a Functions scoring worker. Users report “answers hang.”
AppRequests on the API role show normal p95—enqueue path is healthy.
Worker role AppRequests p95 jumped from 2s to 12s after 16:00.
AppDependencies shows Azure OpenAI p95 11s; pgvector stable.
ResultCode 429 counts rise on the model target.
One operation_Id join to AppTraces shows “insufficient quota” messages.
Root cause: quota exhaustion under a marketing traffic spike—not a vector index outage. The fix is quota/capacity plus backoff/cache, validated by watching 429 counts and p95 fall in the next time bins.
Exam decision habits
Separate symptom (API slow) from stage (which dependency).
Prefer percentile + bin over a single average.
Use operation_Id when you need proof, not only aggregates.
Include container console queries when telemetry stops entirely.
Choose remediations that match the signature (429 ≠ restart Postgres).
Chapter synthesis
OpenTelemetry SDKs create correlated traces and metrics; Azure Monitor/Application Insights store and visualize them; KQL turns both logs and metrics into diagnoses. Together they satisfy the Domain 4 skill to monitor and troubleshoot Azure solutions for AI backends—exactly the operational loop AI-200 expects you to demonstrate.