Su AZ-400 l’instrumentation non è “installare l’agente e guardare i grafici”. La domanda d’esame è sempre della forma: dato questo requisito diagnostico e questo vincolo di costo, quale segnale raccolgo, dove lo faccio atterrare e come lo interrogo. Diamo per acquisiti i meccanismi base — cosa sia un workspace, come si crea un alert — e concentriamoci sulle decisioni di design e sui trade-off fra le due metà della piattaforma dati di Azure Monitor: Metrics e Logs.
La prima decisione: metriche o log
Azure Monitor separa i dati in due store con proprietà molto diverse, e quasi ogni scenario si risolve capendo in quale dei due deve vivere il segnale.
Azure Monitor Metrics è un database time-series di soli valori numerici, preaggregati e arricchiti da dimensioni (coppie nome/valore che permettono filtro e splitting). Le platform metrics delle risorse Azure non richiedono alcuna configurazione, non hanno costo e sono raccolte con frequenza di un minuto salvo diversa indicazione nella definizione della metrica. La ritenzione di platform e custom metrics è di 93 giorni, ma un singolo grafico in Metrics Explorer può coprire al massimo 30 giorni di intervallo per volta.
Azure Monitor Logs accetta invece qualsiasi dato, anche non numerico, e si interroga in KQL. Il principio da tenere a mente in fase di design è netto: qualsiasi dato non numerico, come gli eventi, può stare solo nei Logs; un dato numerico può stare in entrambi, e quella duplicazione è una scelta, non un accidente.
Il trade-off che ne discende:
- Metriche — latenza bassa, costo assente per le platform metrics, ideali per alerting quasi in tempo reale su segnali noti in anticipo. Ma sono aggregate: non permettono join, non conservano il dettaglio per singola transazione e non si interrogano in KQL.
- Log — potere espressivo pieno (join, correlazione fra tabelle e risorse, aggregazioni arbitrarie), ma con costo di ingestione e ritenzione da governare.
Regola di design: alert sulle metriche, diagnosi sui log. Quando serve trending di lungo periodo o correlazione fra una metrica di piattaforma e i log applicativi, il pattern corretto è esportare le platform metrics verso un Log Analytics workspace tramite diagnostic settings — non attendersi che siano già interrogabili in KQL.
Infrastruttura: cosa vedi senza agente e cosa richiede una DCR
È la trappola più ricorrente del dominio. Per una VM Azure il namespace Virtual Machine Host raccoglie metriche automaticamente, senza configurazione: sono metriche dell’host, quindi CPU, disco e rete a quel livello. I contatori del sistema operativo guest, e la memoria è l’esempio citato esplicitamente dalla documentazione, non sono inclusi.
Per memoria, spazio libero sui volumi logici e in generale qualsiasi performance counter guest servono Azure Monitor Agent e una Data Collection Rule, che alimentano i namespace Virtual Machine Guest su Windows e azure.vm.linux.guestmetrics su Linux. La DCR è l’artefatto di design vero: decide quali contatori raccogliere, con quale intervallo e verso quale destinazione.
Qui si apre il secondo trade-off. L’Azure Monitor Agent può inviare i dati di performance del guest a Metrics, a Logs o a entrambi; VM insights li manda ai Logs.
- Destinazione Metrics se l’obiettivo è un metric alert reattivo ed economico su una soglia nota (memoria disponibile, spazio disco).
- Destinazione Logs se serve confrontare decine di macchine in un’unica query, correlare con eventi o conservare la serie oltre la finestra delle metriche.
- Entrambe solo quando entrambi i requisiti esistono davvero: si paga due volte lo stesso contatore.
Quando il requisito parla di dipendenze fra macchine e processi, la risposta non è una metrica ma la vista Map di VM insights, che espone processi e connessioni.
Telemetria applicativa e distributed tracing
Per le applicazioni il percorso raccomandato da Microsoft per la maggior parte degli scenari server-side instrumentati nel codice è l’Azure Monitor OpenTelemetry Distro; la telemetria del browser resta appannaggio dell’Application Insights JavaScript SDK, che non usa OpenTelemetry.
Il distributed tracing poggia su due campi di contesto che vanno conosciuti a memoria:
operation_Id— identificatore dell’operazione radice. Raggruppa la telemetria attraverso più componenti: lo creano una request o una page view, e tutti gli altri item ereditano quel valore.operation_ParentId— identificatore del genitore immediato dell’item, cioè ciò che ricostruisce l’albero delle chiamate e non solo il loro insieme.
Attenzione ai nomi delle tabelle, che sono storicamente asimmetrici: gli span del tracing distribuito finiscono in requests e dependencies, mentre traces conserva i log applicativi per ragioni di retrocompatibilità.
La decisione di design spesso trascurata è il cloud role name. L’Application map identifica i componenti proprio tramite la proprietà role name e ricostruisce la topologia seguendo le chiamate di dipendenza HTTP fra server instrumentati. Se i microservizi non impostano role name distinti, collassano in un unico nodo e la mappa perde valore diagnostico; cloud_RoleInstance serve poi a distinguere le singole istanze dietro un load balancer, scenario tipico dei container.
Sampling: il trade-off architetturale. Il Distro include un sampler proprietario, pensato per mantenere le tracce complete ed evitare quelle spezzate, e supporta due strategie: fixed-rate (una percentuale) e rate-limited (un tetto di tracce al secondo). L’ingestion sampling, che scarta i dati al punto di ingestione, è esplicitamente sconsigliato: non offre controllo su quali tracce vengano conservate e aumenta la probabilità di tracce spezzate. Resta un ripiego quando non si può toccare il codice o si deve tagliare il volume subito senza redeploy.
Due conseguenze operative da ricordare: le metriche non sono campionate, quindi sono la base affidabile per gli alert anche con sampling aggressivo; e le query devono tenere conto di itemCount, che rappresenta il numero di occorrenze associate al singolo item. Il daily cap va trattato come ultima linea di difesa, non come alternativa al sampling: quando scatta, si apre un buco nella telemetria fino al reset.
KQL: dalla query esplorativa all’asset riutilizzabile
KQL si scrive in Log Analytics, ma il punto di design è che la stessa query diventa poi log search alert rule, workbook o tile di dashboard. Vale quindi la pena scriverla bene una volta.
Forma canonica: filtrare per primo (tempo e predicati selettivi), poi proiettare, infine aggregare.
requests
| where timestamp > ago(1h)
| summarize
Chiamate = sum(itemCount),
P95 = percentile(duration, 95)
by cloud_RoleName, bin(timestamp, 5m)
| render timechart
Tre scelte deliberate: sum(itemCount) invece di count() per non sottostimare i volumi sotto sampling, percentile invece di avg perché la media nasconde la coda della latenza, bin() per il bucketing temporale esplicito.
Per la correlazione fra segnali diversi si usa join sulla chiave di correlazione:
exceptions
| where timestamp > ago(6h)
| join kind=inner (requests | project operation_Id, name) on operation_Id
| summarize Errori = count() by problemId, name
Verificare se il sampling è attivo è a sua volta una query, sulla stessa logica:
union requests, dependencies, pageViews, exceptions, traces
| where timestamp > ago(1d)
| summarize RetainedPercentage = 100/avg(itemCount) by bin(timestamp, 1h), itemType
Da conoscere anche gli operatori esclusivi di Azure Monitor, tra cui workspace(), app() e resource(), che permettono query cross-workspace e cross-risorsa.
Come cade all’esame
- “Serve un alert sulla memoria disponibile di un parco VM” → non basta la telemetria di default: Azure Monitor Agent + DCR, perché le host metrics non includono i contatori guest come la memoria.
- “Correlare una metrica di piattaforma con i log applicativi in un’unica query” → esportare la metrica al Log Analytics workspace via diagnostic settings; le metriche native non si interrogano in KQL.
- “Una chiamata attraversa cinque servizi: ricostruire l’intera transazione” → filtrare su
operation_Id; usareoperation_ParentIdquando serve la gerarchia padre-figlio, non il semplice raggruppamento. - “Nella Application map i microservizi appaiono come un nodo unico” → impostare cloud role name distinti per componente.
- “Ridurre il costo di ingestione mantenendo tracce diagnostiche complete” → sampling nel Distro (fixed-rate o rate-limited), non ingestion sampling né daily cap.
- “Dopo aver attivato il sampling i conteggi nelle query sono crollati” → aggregare con
sum(itemCount); e ricordare che le metriche non sono campionate, quindi gli alert restano affidabili. - “Individuare il degrado di latenza percepito dagli utenti” → percentile per ruolo e finestra temporale, non la media.