A la lliçó anterior vas configurar les configuracions de diagnòstic i tot va començar a fluir cap a log-contoso-pro. Ara hi ha dades: peticions HTTP del web de reserves, consultes lentes de db-reservas, accessos a kv-contoso-pro, registres dels contenidors d'aks-contoso-operaciones i el registre d'activitat de les dues subscripcions. Emmagatzemar-los no serveix de res si ningú no els sap interrogar, i aquest és exactament el punt on molts equips es queden: paguen la ingesta i no exploten la dada.
Aquesta lliçó ensenya KQL —el llenguatge de consulta de Kusto— des de zero i de manera progressiva, sempre sobre dades reals de Contoso Airlines. Acabaràs resolent-hi la queixa que va obrir el mòdul: «he pagat i no m'ha arribat la targeta d'embarcament». I aprendràs a controlar la factura, perquè la ingesta i la retenció a Log Analytics són la partida que més sorprèn quan arriba el mes següent.
Contingut
- Què és una àrea de treball de Log Analytics
- Disseny de l'àrea: una o diverses, i RBAC
- Les taules que t'hi trobaràs
- KQL des de zero: filtrar, projectar i estendre
- Agregar:
summarize,bin()i sèries temporals - Combinar i transformar:
join,union,let,parseimv-expand - La investigació completa d'una targeta que no va arribar
- Funcions desades i alertes de cerca de registres
- Consultes entre àrees i exportació de dades
- Plans de taula, retenció i les tres palanques del cost
- Errors Comuns i Consells
- Exercicis
- Conclusió
- Què és una àrea de treball de Log Analytics
Una àrea de treball és el contenidor on es guarden i es consulten els registres: un recurs d'Azure, en una regió concreta, amb el seu RBAC, la seva retenció i la seva factura. A dins hi ha taules, cadascuna amb un esquema fix de columnes tipades, i sobre elles es consulta amb KQL, un llenguatge de només lectura, d'estil canonada, pensat per a volums enormes de dades de sèries temporals.
log-contoso-pro viu a rg-contoso-seguridad-pro i és deliberadament el punt únic de convergència. Allà arriben els registres de recurs de tota la plataforma, la telemetria d'Application Insights (07-03), les dades de Container Insights d'AKS, el registre d'activitat i les alertes de Microsoft Defender for Cloud del mòdul 4. Aquesta convergència és el que permet escriure una sola consulta que creua la petició HTTP del passatger amb l'excepció de la funció i amb el missatge de la cua. Si aquestes dades estiguessin en quatre àrees diferents, la investigació seria un exercici de copiar i enganxar entre pestanyes.
- Disseny de l'àrea: una o diverses, i RBAC
La primera decisió d'arquitectura és quantes àrees crear:
| Motiu per separar | Motiu per unificar |
|---|---|
| Residència legal de la dada en una altra regió, o aïllament exigit per un client | Correlacionar entre serveis en una sola consulta |
| Costos que s'han de facturar a subscripcions diferents | Un sol conjunt de retenció i plans per mantenir |
| Retencions legalment incompatibles | Alertes i llibres que abasten tota la plataforma |
Contoso fa servir una sola àrea de producció. Abans de decidir-ho, l'argument en contra era el control d'accés: no tothom ha de veure els registres de kv-contoso-pro. La resposta és en els dos modes d'accés:
- Context d'àrea: qui té permís sobre l'àrea veu totes les taules i tots els recursos; és el que necessita l'equip central d'operacions.
- Context de recurs: l'usuari consulta des del full del recurs, o amb
resource(), i veu només els registres dels recursos sobre els quals té RBAC. Un desenvolupador ambLectorsobreapp-contoso-reservas-devveu aquests i cap més, encara que siguin a la mateixa àrea.
S'activa amb az monitor log-analytics workspace update --workspace-name log-contoso-pro --resource-group rg-contoso-seguridad-pro --set properties.features.enableLogAccessUsingOnlyResourcePermissions=true. Amb aquesta opció, el permís sobre el recurs governa i el de l'àrea deixa de donar accés universal: el grup Contoso-Desarrollo rep Lector sobre rg-contoso-reservas-dev i veu el que és seu; Contoso-Operaciones rep el rol Lector de Log Analytics sobre l'àrea i ho veu tot. Una sola àrea, permisos per recurs: exactament l'RBAC del mòdul 4 aplicat a l'observabilitat.
- Les taules que t'hi trobaràs
| Taula | Què conté | Origen |
|---|---|---|
AzureActivity |
Operacions del pla de control: qui va crear, canviar o esborrar | Registre d'activitat |
AzureDiagnostics / AppServiceHTTPLogs |
Registres de recurs en esquema genèric o en taula dedicada | Configuració de diagnòstic |
AppRequests |
Peticions vistes per l'aplicació, amb durada i resultat | Application Insights |
AppTraces / AppExceptions |
Missatges de registre del codi i excepcions amb la seva pila | Application Insights |
AppDependencies |
Crides sortints: SQL, HTTP, cues | Application Insights |
ContainerLogV2 |
Sortida estàndard dels contenidors d'AKS | Container Insights |
Heartbeat / SecurityAlert |
Batec de cada agent i alertes de Defender for Cloud | Agent / Defender |
Usage |
Quant ha ingerit cada taula: la taula dels diners | Interna, gratuïta |
Dues advertències. AzureDiagnostics és una taula ampla i compartida per molts serveis, amb columnes del tipus campo_s, campo_d o campo_b i un límit de columnes que pot provocar pèrdues: prefereix sempre les taules dedicades amb --export-to-resource-specific true, com vas fer a 07-01. I els noms App* són els d'un recurs d'Application Insights basat en àrea de treball: la telemetria viu a log-contoso-pro i es consulta al costat de la resta, que és justament el que fa possible l'apartat 7.
- KQL des de zero: filtrar, projectar i estendre
Una consulta KQL comença per una taula i encadena operadors amb la barra vertical |. Cada operador rep una taula i en retorna una altra.
AppServiceHTTPLogs
| where TimeGenerated > ago(1h)
| where CsHost == "reservas.contosoairlines.example" and ScStatus >= 500
| project TimeGenerated, CsUriStem, ScStatus, TimeTaken, CIp
| order by TimeGenerated desc
| take 20Línia a línia:
AppServiceHTTPLogs— la taula d'origen. Comença sempre per una taula concreta, mai persearch.where TimeGenerated > ago(1h)— filtre temporal; admet5m,7d,30d. Va sempre el primer: és el que redueix el volum escanejat i, per tant, el cost i el temps de la consulta.- Els
wheresuccessius filtren per lloc i per codi d'estat:==distingeix majúscules,=~no. projectselecciona columnes i descarta la resta, reduint el que viatja al navegador;order by ... descordena —sense això l'ordre no està garantit— itake 20retalla el resultat.
L'operador search "XR7742" busca un text a totes les taules: útil una vegada, quan no saps on és la dada, i caríssim perquè ho escaneja tot. Tan bon punt sàpigues la taula, fes-la servir directament. Per la seva banda, extend afegeix columnes calculades sense perdre les existents:
AppServiceHTTPLogs
| where TimeGenerated between (datetime(2026-08-14 08:00) .. datetime(2026-08-14 12:00))
| extend SegonsResposta = TimeTaken / 1000.0
| extend Familia = case(ScStatus < 400, "ok", ScStatus < 500, "error de client", "error de servidor")
| where SegonsResposta > 2
| project TimeGenerated, CsUriStem, SegonsResposta, Familiabetween (datetime(...) .. datetime(...))acota una finestra absoluta, per reconstruir un incident ja tancat. Altres operadors de temps freqüents:startofday(now()),startofweek(),now()-2d.extendcreaSegonsRespostaa partir de mil·lisegons; el.0força la divisió decimal.case(...)avalua condicions en ordre i retorna el primer encert; l'últim valor és el «si no».
- Agregar:
summarize, bin() i sèries temporals
summarize, bin() i sèries temporalssummarize és l'operador que converteix milions de files en una resposta.
AppRequests
| where TimeGenerated > ago(24h) and AppRoleName == "app-contoso-api-disponibilidad-pro"
| summarize Peticions = count(), Fallides = countif(Success == false), MitjanaMs = avg(DurationMs),
P95Ms = percentile(DurationMs, 95), UsuarisUnics = dcount(UserId) by Name
| extend PercentatgeError = round(100.0 * Fallides / Peticions, 2)
| order by P95Ms desccount()compta files;countif(condició)compta només les que compleixen alguna cosa, evitant una segona consulta.avg()dona la mitjana, que menteix amb les latències: unes poques peticions de 20 segons a penes mouen la mitjana.percentile(DurationMs, 95)és el valor per sota del qual queda el 95 % de les peticions: la mètrica honesta, i la que sosté l'SLO de 07-01.dcount()compta valors diferents de manera aproximada —algorisme probabilístic, error al voltant de l'1 %—, cosa que el fa rapidíssim sobre milers de milions de files;dcount(UserId, 4)puja la precisió a costa de recursos.by Nameagrupa per operació: una fila per punt de connexió.
Per veure l'evolució en el temps cal bin(), que arrodoneix cada marca temporal a un múltiple de l'interval:
AppRequests
| where TimeGenerated > ago(12h) and AppRoleName == "app-contoso-reservas-pro"
| summarize P95 = percentile(DurationMs, 95), Errors = countif(Success == false)
by bin(TimeGenerated, 5m)
| render timechartbin(TimeGenerated, 5m) agrupa tot el que ha passat al mateix tram de 5 minuts; el resultat és una sèrie temporal. render timechart la dibuixa al portal —també existeixen barchart, columnchart, piechart i areachart—. I top 10 by P95 desc és la drecera d'order by més take.
- Combinar i transformar:
join, union, let, parse i mv-expand
join, union, let, parse i mv-expandlet declara constants i subconsultes reutilitzables —let finestra = 2h; o let apps = dynamic(["app-contoso-reservas-pro", "app-contoso-api-disponibilidad-pro"]);, després utilitzable amb where AppRoleName in (apps)—: fa llegibles les consultes llargues i és imprescindible en la investigació de l'apartat 7. union apila taules amb esquemes diferents —les columnes que falten en una queden buides—: union AppExceptions, ContainerLogV2 barreja excepcions d'aplicació i sortida de contenidors en una sola línia de temps. Dins d'un union, $table retorna de quina taula venia cada fila i coalesce() pren el primer valor no buit entre diverses columnes equivalents.
join creua dos conjunts per una clau comuna. Els seus tipus:
| Tipus | Què retorna | Ús típic a Contoso |
|---|---|---|
innerunique (per defecte) |
Coincidències, deduplicant la clau del costat esquerre | Poques vegades el que vols |
inner |
Totes les combinacions coincidents | Peticions amb les seves dependències |
leftouter |
Tot el de l'esquerra, amb el de la dreta si existeix | Reserves amb o sense targeta emesa |
rightouter / fullouter |
Simètrics de l'anterior | Conciliacions |
leftanti |
El de l'esquerra que no té parella | Reserves sense targeta: el cas d'aquest mòdul |
leftsemi / rightsemi |
Filtra sense portar columnes de l'altre costat | Comprovar existència |
L'innerunique per defecte és la font número u de resultats desconcertants a KQL: deduplica silenciosament i els recomptes surten més baixos del que s'esperava. Escriu sempre el tipus de manera explícita.
let reserves = AppRequests
| where TimeGenerated > ago(6h) and Name == "POST /api/reservas" and Success == true
| project Localitzador = tostring(Properties["localizador"]), HoraReserva = TimeGenerated;
let targetes = AppTraces
| where TimeGenerated > ago(6h) and Message startswith "TarjetaEmitida"
| project Localitzador = tostring(Properties["localizador"]);
reserves
| join kind=leftanti targetes on Localitzador
| order by HoraReserva ascAquesta consulta respon a la pregunta del negoci amb una precisió que cap mètrica no podria donar: quins localitzadors s'han pagat i no tenen targeta. leftanti conserva exactament les files de l'esquerra sense parella a la dreta.
Text i estructures: parse i mv-expand
Finalment, parse extreu camps d'una cadena sense escriure expressions regulars:
ContainerLogV2
| where TimeGenerated > ago(1h) and ContainerName == "motor-disponibilidad"
| parse LogMessage with * "vol=" Vol:string " seients=" Seients:int " ms=" Duracio:int *
| where Duracio > 1500
| summarize Consultes = count(), MitjanaMs = avg(Duracio) by Vol
| top 10 by MitjanaMs descEl patró de parse es llegeix literalment: l'* inicial ignora el que hi hagi abans, després busca el text vol=, captura fins a seients= a Vol, i així successivament. Si el format del missatge canvia, la captura retorna buit en lloc de fallar, així que convé validar-ho.
El seu company és mv-expand, que converteix un camp amb diversos valors —normalment un JSON imbricat llegit amb todynamic()— en diverses files, una per element. Una reserva amb tres trams produeix tres files, i així es poden agregar rutes encara que la dada vingués imbricada; ho aplicaràs a l'exercici 3.
- La investigació completa d'una targeta que no va arribar
Aquest és el recorregut que va obrir el mòdul. El passatger dona el seu localitzador, XR7742. Cinc passos encadenats.
flowchart LR Q["Queixa: XR7742"] --> P1["1. AppRequests<br/>s ha registrat la compra?"] --> P2["2. AppDependencies<br/>s ha encuat?"] P2 --> P3["3. Funcio<br/>s ha executat?"] --> P4["4. AppExceptions<br/>quin error?"] --> P5["5. Key Vault<br/>causa arrel"]
Pas 1: trobar la compra i el seu identificador d'operació.
AppRequests
| where TimeGenerated > ago(3d) and Properties["localizador"] == "XR7742"
| project TimeGenerated, Name, Success, DurationMs, OperationId, AppRoleNameOperationId és la clau de tot: identifica l'operació de negoci completa i es propaga entre components. El veuràs en detall a 07-03.
Pas 2: seguir aquesta operació per tots els components.
let op = toscalar(AppRequests
| where TimeGenerated > ago(3d) and Properties["localizador"] == "XR7742"
| top 1 by TimeGenerated desc | project OperationId);
union AppRequests, AppDependencies, AppTraces, AppExceptions
| where TimeGenerated > ago(3d) and OperationId == op
| project TimeGenerated, Tipus = $table, AppRoleName, Detall = coalesce(Name, Message, ExceptionType)
| order by TimeGenerated asctoscalar() redueix una subconsulta a un valor únic reutilitzable, i el union ordenat per temps produeix la línia de temps completa d'aquella reserva: la petició web, la crida a sql-contoso-reservas-pro, l'escriptura a cola-emision-tarjetas i el que passés després.
Pas 3: comprovar si la funció va arribar a executar-se. N'hi ha prou de filtrar AppRequests per AppRoleName == "func-contoso-tarjetas-pro" i Name == "GenerarTarjetaEmbarque" amb el mateix localitzador. Si no retorna files, el missatge es va encuar però ningú no el va processar i el problema és al desencadenador; si les retorna amb Success == false, continua pel pas 4.
Passos 4 i 5: l'error i la seva causa arrel.
AppExceptions
| where TimeGenerated > ago(3d) and AppRoleName == "func-contoso-tarjetas-pro"
| summarize Ocurrencies = count(), Localitzadors = make_set(tostring(Properties["localizador"]), 10)
by ExceptionType, OuterMessage
| order by Ocurrencies descmake_set(columna, N) recull fins a N valors diferents en una llista: revela de cop si la fallada afecta només XR7742 o dues-centes reserves més. Si l'excepció és d'accés denegat, la causa és a un pas, als registres d'auditoria de Key Vault:
AzureDiagnostics
| where TimeGenerated > ago(3d) and ResourceProvider == "MICROSOFT.KEYVAULT"
| where OperationName == "SecretGet" and ResultSignature != "OK"
| project TimeGenerated, id_s, identity_claim_appid_g, ResultSignatureEl desenllaç real de Contoso: el certificat de signatura de PDF de kv-contoso-pro havia caducat, la identitat administrada id-contoso-api-pro rebia un error en recuperar-lo, la funció fallava després de cinc reintents i el missatge acabava a la cua de missatges amb problemes de lliurament. Cinc consultes, de la queixa a la causa arrel, sense obrir ni una sola sessió en un servidor.
- Funcions desades i alertes de cerca de registres
Aquest recorregut no s'ha de reinventar cada vegada. Una funció desada converteix una consulta en un operador nou, amb paràmetres, disponible per a tot l'equip:
// Cos desat a log-contoso-pro amb l alias SeguirLocalizador i parametres (loc:string, dies:int = 3)
let op = toscalar(AppRequests
| where TimeGenerated > ago(dies * 1d) and Properties["localizador"] == loc
| top 1 by TimeGenerated desc | project OperationId);
union AppRequests, AppDependencies, AppTraces, AppExceptions
| where TimeGenerated > ago(dies * 1d) and OperationId == op
| project TimeGenerated, Tipus = $table, AppRoleName, Detall = coalesce(Name, Message, ExceptionType)
| order by TimeGenerated ascAmb la funció desada a la categoria «Contoso - Operaciones», qualsevol del grup Contoso-Operaciones escriu SeguirLocalizador("XR7742") i obté el recorregut complet. És la diferència entre que la investigació depengui de la Marta Ríos i que la faci el primer que atengui la trucada. Aquestes funcions i les consultes d'exemple compartides es versionen al repositori contoso-infra, al costat dels llibres i les plantilles Bicep del mòdul 5.
Alertes de cerca de registres
Qualsevol consulta KQL que retorni files es pot convertir en una alerta. És el que permet alertar sobre coses que cap mètrica de plataforma no expressa:
az monitor scheduled-query create \
--name alerta-tarjetas-no-emitidas \
--resource-group rg-contoso-seguridad-pro --scopes "$LOG_ID" \
--condition "count 'Files' > 5" \
--condition-query Files='AppRequests | where Name == "POST /api/reservas" and Success == true | extend L = tostring(Properties["localizador"]) | join kind=leftanti (AppTraces | where Message startswith "TarjetaEmitida" | extend L = tostring(Properties["localizador"])) on L' \
--evaluation-frequency 15m --window-size 30m --severity 2 \
--action-groups ag-equipo-contoso \
--tags entorno=produccion proyecto=contoso-reservas centro-coste=CC-1042 propietario=marta.riosTres decisions. Una --window-size més gran que la freqüència dona marge a la latència d'ingesta —les dades triguen d'un a cinc minuts a estar disponibles, i una finestra ajustada genera falsos negatius—. --evaluation-frequency 15m en lloc d'1m perquè aquestes alertes es facturen per regla i freqüència. I gravetat 2 amb ag-equipo-contoso: cinc targetes sense emetre és un problema real, però no justifica un SMS de matinada.
- Consultes entre àrees i exportació de dades
Encara que Contoso faci servir una sola àrea, hi ha dues maneres de sortir-ne. workspace("log-contoso-millas").AppRequests apunta a una altra àrea per nom o identificador i es combina amb union per consultar-ne diverses alhora; resource("/subscriptions/.../sites/app-contoso-reservas-pro") consulta els registres d'un recurs concret sense anomenar l'àrea, i és la manera natural de treballar en context de recurs.
L'exportació de dades de l'àrea envia taules senceres i en continu a un compte d'emmagatzematge o a un Event Hubs, sense escriure codi. Contoso exporta AzureActivity i AppServiceHTTPLogs a stlagocontosopro, capa bronce: compliment a set anys a preu d'emmagatzematge en fred i disponibilitat per a Synapse (mòdul 3) sense tornar a pagar la ingesta. La combinació que cal interioritzar és aquesta: Log Analytics per als últims 30-90 dies, que és quan s'investiga; emmagatzematge barat per a la resta.
- Plans de taula, retenció i les tres palanques del cost
Aquí hi ha l'advertència central del mòdul. La ingesta i la retenció a Log Analytics és una de les factures que més sorprèn a Azure. No hi ha cap avís: actives uns registres de depuració durant una investigació, se t'oblida desactivar-los, i trenta dies després la línia de Log Analytics supera la del còmput que la genera. Cada taula té un pla que fixa què s'hi pot fer i quant costa:
| Pla | Preu d'ingesta | Consultes | Alertes | Retenció | Per a què |
|---|---|---|---|---|---|
| Analytics | El complet | KQL sense restriccions | Sí | Interactiva fins a 2 anys | El que investigues i vigiles |
| Basic | Molt reduït | KQL limitat, sobre una sola taula | No | Interactiva curta, 30 dies | Registres voluminosos i de poc valor |
| Auxiliary | El més baix | Molt limitades i més lentes | No | Llarga | Compliment i auditoria en volum |
La retenció, a més, es divideix en dos trams: la interactiva (consultable immediatament, més cara) i l'arxiu a llarg termini (molt més barat, fins a 12 anys, del qual cal «rehidratar» o consultar amb treballs de cerca). Amb això ja es poden accionar les tres palanques del cost, en ordre d'impacte:
- Què s'ingereix. La palanca dominant; els registres de depuració i de consola en són els grans culpables. Les transformacions a les DCR permeten descartar en el moment de la ingesta els batecs, els sondejos d'estat i les peticions a recursos estàtics, que no aporten res i són la meitat del volum.
- En quin pla. Moure
ContainerLogV2a Basic quan només es fa servir per llegir els últims dies retalla dràsticament la factura de la taula més voluminosa de Contoso. - Quant de temps es guarda. La retenció es fixa per taula, no només per àrea:
AzureActivitya 365 dies per compliment,AppTracesa 30.
La taula Usage és gratuïta i diu exactament on se'n van els diners:
Usage
| where TimeGenerated > ago(30d) and IsBillable == true
| summarize GB = round(sum(Quantity) / 1024, 2) by DataType
| extend EuroAprox = round(GB * 2.30, 2) // preu orientatiu per GB
| top 15 by GB descQuantity ve en megabytes, d'aquí la divisió. El cost estimat és orientatiu —el preu real depèn del pla i del compromís—, però n'hi ha prou per ordenar per impacte. A Contoso, aquesta consulta va revelar que AppServiceConsoleLogs era el 41 % del volum total i no el consultava ningú. Canviant el summarize per by bin(TimeGenerated, 1d), DataType i renderitzant en columnchart es veu, a més, el dia exacte en què alguna cosa es va disparar. Aplicar la retallada:
WS="--workspace-name log-contoso-pro --resource-group rg-contoso-seguridad-pro"
az monitor log-analytics workspace table update $WS --name AppTraces \
--retention-time 30 --total-retention-time 30 # 30 dies interactius, sense arxiu
az monitor log-analytics workspace table update $WS --name ContainerLogV2 --plan BasicFinalment, el model de preus de l'àrea: pagament per gigabyte davant de compromís de capacitat. A partir d'uns 100 GB al dia, comprometre un nivell diari fix aplica un descompte notable, i a partir d'aquí creix per esglaons. La regla de Contoso: mesurar tres mesos amb Usage, retallar primer el que no es consulta, i només després comprometre capacitat sobre el volum ja optimitzat. Comprometre capacitat sobre dades inútils és pagar un descompte per escombraries. Un límit diari d'ingesta actua a més com a xarxa de seguretat davant d'un bucle de registre descontrolat, encara que cal assumir que, assolit el sostre, es deixen de rebre dades fins l'endemà: no el posis a les taules de seguretat.
Errors Comuns i Consells
- No filtrar per temps al principi, o fer servir
searchen producció. Són els dos errors que més costen en rendiment: posa semprewhere TimeGenerated > ago(...)com a primer operador i parteix d'una taula concreta, perquèsearchles escaneja totes. - Deixar el
joinper defecte.inneruniquededuplica en silenci i produeix recomptes incorrectes. Escriukind=sempre. - Alertar sobre una finestra igual a la freqüència. La latència d'ingesta et farà perdre esdeveniments: la finestra ha de ser més gran.
- Confondre mitjana amb percentil. La mitjana de latència amaga la cua llarga, que és la que veu el passatger.
- Oblidar registres de depuració activats. L'origen número u de factures sorpresa: revisa
Usagecada mes i posa-ho al calendari. - Consell: fes servir
| take 10mentre desenvolupes i treu-lo al final; iterar sobre 10 files és instantani. I prefereix les taules dedicades (--export-to-resource-specific), que migren fora d'AzureDiagnosticsamb millor esquema i plans per taula. - Consell: desa com a funció tota consulta que hagis escrit dues vegades. El coneixement d'investigació ha d'estar a l'àrea, no a l'historial d'algú.
Exercicis
Exercici 1. Escriu una consulta KQL que, sobre l'última setmana, retorni per cada operació d'app-contoso-api-disponibilidad-pro el nombre de peticions, el percentatge d'error i el percentil 95 de la durada, mostrant només les operacions amb més de 1.000 peticions i p95 superior a 800 ms. Explica cada línia.
Exercici 2. La factura mensual de log-contoso-pro ha passat de 400 a 1.750 euros sense que s'hagi desplegat res nou. Descriu com investigar-ho amb KQL i proposa quatre mesures concretes, indicant quina palanca acciona cadascuna.
Exercici 3. La Nuria Peña vol un informe setmanal amb les cinc rutes més reservades i el seu ingrés mitjà, per al projecte Contoso Millas (centro-coste=CC-2077). Les dades són en esdeveniments personalitzats amb un camp tramos imbricat. Escriu la consulta i explica com la lliuraries de manera recurrent.
Solucions
Solució 1:
AppRequests
| where TimeGenerated > ago(7d) and AppRoleName == "app-contoso-api-disponibilidad-pro"
| summarize Peticions = count(), Fallides = countif(Success == false),
P95 = percentile(DurationMs, 95) by Name
| extend PercentatgeError = round(100.0 * Fallides / Peticions, 2)
| where Peticions > 1000 and P95 > 800
| order by P95 descEl filtre temporal va primer per reduir el volum escanejat. El segon where acota a l'API. summarize agrega per operació amb by Name, fent servir countif per no necessitar una segona consulta i percentile en lloc d'avg perquè la mitjana amaga la cua. extend calcula el percentatge amb 100.0 per forçar decimals. El filtre de volum i latència va després de summarize, perquè opera sobre columnes que abans no existien; posar-lo abans donaria error. order by deixa a dalt el que és més greu.
Solució 2: s'investiga amb Usage, agrupant per DataType i per bin(TimeGenerated, 1d) sobre 60 dies i renderitzant en columnes; el gràfic mostra el dia exacte del salt i quina taula el causa. Sol ser una de tres coses: registres de depuració activats en una investigació i oblidats, una configuració de diagnòstic nova desplegada per l'assignació diagnostico-app-service sobre recursos acabats de crear, o un bucle d'excepcions que genera milers de traces per minut. Contrastar amb AzureActivity què va canviar aquells dies. Mesures: (1) desactivar les categories de diagnòstic que ningú no consulta —palanca «què s'ingereix», la de més impacte—; (2) afegir una transformació a la DCR que descarti sondejos d'estat i batecs —mateixa palanca, a l'origen—; (3) passar ContainerLogV2 a pla Basic —palanca «en quin pla»—; (4) baixar la retenció d'AppTraces a 30 dies mantenint AzureActivity a 365 —palanca «quant de temps»—. I un límit diari d'ingesta com a xarxa de seguretat, mai sobre taules de seguretat.
Solució 3:
AppEvents
| where TimeGenerated > ago(7d) and Name == "ReservaConfirmada" and tostring(Properties["proyecto"]) == "contoso-millas"
| extend Trams = todynamic(tostring(Properties["tramos"])), Import = todouble(Properties["importe"])
| mv-expand Tram = Trams
| extend Ruta = strcat(tostring(Tram.origen), "-", tostring(Tram.destino))
| summarize Reserves = count(), IngresMitja = round(avg(Import), 2) by Ruta
| top 5 by Reserves descmv-expand desdobla cada tram a la seva pròpia fila i strcat compon la ruta llegible. Lliurament recurrent: la consulta es desa com a funció a log-contoso-pro, s'incrusta en un llibre parametritzat amb l'interval com a paràmetre, i aquest llibre s'envia automàticament cada dilluns. L'automatització de l'enviament es resol amb un runbook d'Azure Automation o una Logic App —la comparació entre totes dues opcions és exactament el tema de la lliçó 07-04—. Etiquetes del recurs implicat: entorno, proyecto=contoso-millas, centro-coste=CC-2077 i propietario.
Conclusió
Ja saps què és una àrea de treball de Log Analytics i per què log-contoso-pro és el punt únic on convergeix tot: registres de recurs, registre d'activitat, telemetria d'aplicació i alertes de seguretat, amb l'avantatge decisiu de poder creuar-los en una sola consulta. Coneixes el criteri per separar o unificar àrees, i la peça que fa viable l'àrea única —el context de recurs davant del context d'àrea, amb enableLogAccessUsingOnlyResourcePermissions, perquè cada equip vegi només el que és seu amb l'RBAC que ja té—, a més del mapa de les taules que t'hi trobaràs, amb la recomanació de preferir les dedicades a AzureDiagnostics. Sobretot, saps KQL: filtrar amb where i els operadors de temps, seleccionar amb project, calcular amb extend i case, agregar amb summarize fent servir count, countif, avg, percentile i dcount, construir sèries temporals amb bin() i dibuixar-les amb render, combinar amb union, let i els sis tipus de join —amb l'advertència sobre innerunique—, i extreure estructura amb parse i mv-expand. Ho has aplicat al recorregut d'investigació complet que va obrir el mòdul: de la queixa del localitzador XR7742 a un certificat caducat a kv-contoso-pro, en cinc consultes encadenades, i ho has convertit en la funció compartida SeguirLocalizador perquè la investigació no depengui d'una sola persona. Has construït una alerta de cerca de registres sobre una consulta, alerta-tarjetas-no-emitidas, i saps exportar dades a stlagocontosopro per conservar barat allò que ja no investigues.
I t'endus la lliçó de diners, que és la que més vegades s'aprèn tard: els plans de taula Analytics, Basic i Auxiliary, la retenció interactiva davant de l'arxiu a llarg termini, i les tres palanques —què s'ingereix, en quin pla i quant de temps es guarda— amb la taula Usage com a instrument per saber on se'n van els diners abans de tocar res, i el compromís de capacitat només després d'haver retallat. Queda un buit. Totes les consultes de l'apartat 7 es recolzaven en OperationId, en taules AppRequests i AppDependencies, i en propietats com localizador que algú va haver d'emetre des del codi. Aquesta dada no apareix per art de màgia: la genera Application Insights, i d'ell tracta la lliçó següent —el model de telemetria, la instrumentació d'app-contoso-reservas-pro i func-contoso-tarjetas-pro, la correlació distribuïda amb el context de traça del W3C, el mapa de l'aplicació, el mostreig i la telemetria personalitzada que converteix una reserva confirmada en una dada consultable—.
Curs d'Azure
Mòdul 1: Introducció a Azure
- Què és Azure?
- Models de servei, regions i zones de disponibilitat
- Crear i configurar el teu compte d'Azure
- Recorregut pel portal d'Azure
- Azure Resource Manager: subscripcions, grups de recursos i etiquetes
- Azure CLI, PowerShell i Cloud Shell
Mòdul 2: Serveis principals d'Azure
- Màquines virtuals d'Azure
- Escalat i alta disponibilitat del còmput
- Azure App Service
- Azure Storage: blobs, fitxers, cues i taules
- Xarxes a Azure: xarxes virtuals, subxarxes i NSG
- Connectivitat híbrida i lliurament global
Mòdul 3: Bases de dades d'Azure
- Triar el servei de dades adequat
- Azure SQL Database
- Azure Cosmos DB
- Azure Database for MySQL
- Azure Database for PostgreSQL
- Analítica de dades: Data Lake, Data Factory i Synapse
Mòdul 4: Seguretat a Azure
- Microsoft Entra ID i gestió d'identitats
- RBAC i identitats administrades
- Azure Key Vault
- Protecció DDoS i tallafoc d'aplicacions web
- Microsoft Defender for Cloud
- Governança i compliment amb Azure Policy
Mòdul 5: Azure DevOps
- Introducció a Azure DevOps
- Azure Repos
- Azure Pipelines: integració contínua
- Desplegament continu amb entorns i aprovacions
- Azure Artifacts
- Infraestructura com a codi amb Bicep
Mòdul 6: Serveis avançats d'Azure
- Contenidors a Azure: Container Registry i Container Apps
- Azure Kubernetes Service (AKS)
- Azure Functions
- Azure Logic Apps
- Missatgeria i esdeveniments: Service Bus, Event Grid i Event Hubs
- Serveis d'IA d'Azure
Mòdul 7: Monitoratge i gestió
- Azure Monitor: mètriques, alertes i taulers
- Log Analytics i consultes KQL
- Application Insights
- Azure Automation i runbooks
- Còpies de seguretat i recuperació davant desastres
Mòdul 8: Gestió i optimització de costos
- Calculadora de preus i estimació de costos
- Azure Cost Management: anàlisi, pressupostos i alertes
- Reserves, plans d'estalvi i Azure Hybrid Benefit
- Azure Advisor
- Estratègies d'optimització i cultura FinOps
