> ## Content Index
> Fetch the complete content index at: https://www.azurebrasil.cloud/llms.txt
> Use this file to discover other available public pages before exploring further.

# Resposta a incidentes no Azure: automação de alertas, runbooks e integração com ferramentas de on-call
- URL: https://www.azurebrasil.cloud/blog/resposta-a-incidentes-no-azure-automacao-de-alertas-runbooks-e-integracao-com-ferramentas-de-on-call/
- Published: 2026-04-08T12:31:07.000Z
- Updated: 2026-04-08T12:31:07.000Z
- Author: Ricardo Martins

Você já validou a resiliência com [Engenharia de Caos](https://www.azurebrasil.cloud/blog/engenharia-de-caos-no-azure-validando-resiliencia-em-producao-com-azure-chaos-studio/), definiu SLIs, SLOs e Error Budgets. Mas quando o incidente real acontece , e vai acontecer, a pergunta que define o impacto não é "o que deu errado?", mas sim: **"quanto tempo levamos para detectar, responder e resolver?"**

Esse tempo tem nome: **MTTD** (Mean Time to Detect), **MTTE** (Mean Time to Engage) e **MTTR** (Mean Time to Recover). E a diferença entre um incidente de 5 minutos e um de 5 horas está diretamente ligada à qualidade do seu processo de resposta a incidentes e, principalmente, ao nível de **automação** que você tem.

Neste artigo, vamos explorar como construir um fluxo completo de resposta a incidentes no Azure: desde alertas inteligentes com Azure Monitor, passando por automação com Action Groups e Runbooks, até a integração com ferramentas de on-call e a prática de post-mortems blameless.

## Por que resposta a incidentes importa mais do que prevenção?

Parece contraintuitivo, mas é uma premissa fundamental de SRE: **você não pode prevenir todos os incidentes**. Sistemas distribuídos falham de formas imprevisíveis, é a natureza da complexidade.

O que separa organizações maduras das demais não é a ausência de incidentes, mas a **velocidade e qualidade da resposta**:

| Métrica                         | O que mede                                                                    | Meta típica          |
| ------------------------------- | ----------------------------------------------------------------------------- | -------------------- |
| **MTTD** (Mean Time to Detect)  | Quanto tempo até o sistema detectar a anomalia                                | < 5 minutos          |
| **MTTE** (Mean Time to Engage)  | Quanto tempo até uma pessoa qualificada ser notificada e começar a investigar | < 15 minutos         |
| **MTTR** (Mean Time to Recover) | Quanto tempo até o serviço voltar ao estado estável                           | < 60 minutos         |
| **MTTF** (Mean Time to Fix)     | Quanto tempo até a causa raiz ser corrigida permanentemente                   | Varia por severidade |

> **O objetivo não é eliminar incidentes, é reduzir MTTD, MTTE e MTTR continuamente.** Se você consegue detectar em 2 minutos, engajar em 5 e recuperar em 15, o impacto para o usuário é mínimo, mesmo que a falha seja séria.

## Anatomia de um fluxo de resposta a incidentes no Azure

Um fluxo maduro de incident response no Azure envolve quatro camadas:

```
┌────────────────────────────────────────────────────────────────┐
│  1. DETECÇÃO           Azure Monitor Alerts, Log Analytics,    │
│                        Application Insights, Service Health    │
├────────────────────────────────────────────────────────────────┤
│  2. NOTIFICAÇÃO        Action Groups (email, SMS, webhook,     │
│                        Azure Functions, Logic Apps)            │
├────────────────────────────────────────────────────────────────┤
│  3. AUTOMAÇÃO          Automation Runbooks, Azure Functions,   │
│                        Logic Apps, auto-remediation            │
├────────────────────────────────────────────────────────────────┤
│  4. GESTÃO             Integração com on-call tools,           │
│                        war rooms, post-mortems                 │
└────────────────────────────────────────────────────────────────┘

```

Vamos detalhar cada uma.

## Camada 1: Detecção | Alertas inteligentes com Azure Monitor

A primeira linha de defesa é a **detecção automática**. Alertas mal configurados são piores do que nenhum alerta, geram fadiga (*alert fatigue*) e fazem a equipe ignorar notificações reais.

### Tipos de alerta no Azure Monitor

| Tipo                      | Uso ideal                                                               | Latência típica             |
| ------------------------- | ----------------------------------------------------------------------- | --------------------------- |
| **Metric alerts**         | Métricas numéricas (CPU, memória, latência, taxa de erro)               | \~1 minuto                  |
| **Log search alerts**     | Queries KQL em Log Analytics ou Application Insights                    | 1-15 minutos (configurável) |
| **Activity log alerts**   | Eventos do plano de controle (VM deletada, role assignment, deployment) | \~1-5 minutos               |
| **Service Health alerts** | Incidentes do próprio Azure (outages, manutenções planejadas)           | Tempo real                  |
| **Smart Detection**       | Anomalias detectadas automaticamente pelo Application Insights          | Automático                  |

### Alertas baseados em SLOs

Se você já definiu SLOs (como no artigo anterior), seus alertas devem refletir isso. A ideia é alertar quando o **error budget está sendo consumido rápido demais**, não apenas quando uma métrica pontual ultrapassa um limiar.

```kusto
// SLI: taxa de sucesso das requisições (últimas 6 horas, janela deslizante)
let sloTarget = 99.9;
let windowSize = 6h;
requests
| where timestamp >= ago(windowSize)
| summarize
    totalRequests = count(),
    successfulRequests = countif(success == true)
| extend
    successRate = round(100.0 * successfulRequests / totalRequests, 3),
    sloTarget = sloTarget,
    errorBudgetTotal = round(100.0 - sloTarget, 3),
    errorBudgetConsumed = round(100.0 - (100.0 * successfulRequests / totalRequests), 3)
| extend
    errorBudgetRemainingPct = round(100.0 * (1 - errorBudgetConsumed / errorBudgetTotal), 2)
| where errorBudgetRemainingPct < 50

```

### Burn rate alerts, o padrão recomendado pelo Google SRE

Em vez de alertar quando o SLO é violado (reativo demais) ou quando qualquer erro acontece (barulhento demais), use **burn rate alerts**:

```kusto
// Burn rate: quantas vezes mais rápido que o normal o error budget está sendo consumido
// Burn rate = 1 significa consumo normal (o budget duraria exatamente a janela do SLO)
// Burn rate > 14 em 1h = alerta crítico (budget se esgota em ~2 dias)
// Burn rate > 6 em 6h = alerta de warning (budget se esgota em ~5 dias)
let sloTarget = 0.999;
let sloPeriod = 30d;
let shortWindow = 1h;
let longWindow = 6h;
let burnRateThresholdCritical = 14.0;
let burnRateThresholdWarning = 6.0;
let errorBudget = 1 - sloTarget;
// Janela curta (1h)
let shortWindowErrors = requests
| where timestamp >= ago(shortWindow)
| summarize
    total = count(),
    errors = countif(success == false)
| extend errorRate = 1.0 * errors / total
| extend burnRate = errorRate / errorBudget;
// Janela longa (6h)
let longWindowErrors = requests
| where timestamp >= ago(longWindow)
| summarize
    total = count(),
    errors = countif(success == false)
| extend errorRate = 1.0 * errors / total
| extend burnRate = errorRate / errorBudget;
shortWindowErrors
| extend windowType = "short", threshold = burnRateThresholdCritical
| union (longWindowErrors | extend windowType = "long", threshold = burnRateThresholdWarning)
| where burnRate > threshold

```

### Criando o alerta via CLI

```bash
# Criar um log search alert baseado em burn rate
az monitor scheduled-query create \
  --name "alert-slo-burn-rate-critical" \
  --resource-group meu-rg \
  --scopes "/subscriptions/<sub-id>/resourceGroups/meu-rg/providers/Microsoft.Insights/components/meu-appinsights" \
  --condition "count 'requests | where timestamp >= ago(1h) | summarize total=count(), errors=countif(success==false) | extend burnRate=(1.0*errors/total)/0.001 | where burnRate > 14' > 0" \
  --severity 0 \
  --evaluation-frequency 5m \
  --window-size 10m \
  --action-groups "/subscriptions/<sub-id>/resourceGroups/meu-rg/providers/Microsoft.Insights/actionGroups/ag-critical-oncall"

```

### Boas práticas para evitar alert fatigue

| Prática                               | Por que                                                                                            |
| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
| **Categorize por severidade**         | Sev0 (crítico) aciona on-call imediatamente. Sev3 (informativo) vai para um canal de Slack/Teams.  |
| **Use supressão temporal**            | Não alerte 50 vezes pelo mesmo problema. Configure autoMitigate e períodos de supressão.           |
| **Alerte sobre sintomas, não causas** | Alerte "taxa de erro acima de 1%" e não "CPU acima de 80%". CPU alta pode ser normal sob carga.    |
| **Revise alertas regularmente**       | Alertas que nunca disparam ou sempre disparam são igualmente inúteis. Faça *alert hygiene* mensal. |
| **Defina dono para cada alerta**      | Todo alerta precisa ter um time responsável. Alerta sem dono = alerta ignorado.                    |

## Camada 2: Notificação | Action Groups

Os **Action Groups** do Azure Monitor são o hub central de notificação. Eles definem **quem** e **como** será notificado quando um alerta dispara.

### Tipos de ação disponíveis

| Tipo                   | Uso                                                                     |
| ---------------------- | ----------------------------------------------------------------------- |
| **Email/SMS/Voz**      | Notificação direta a pessoas                                            |
| **Azure Function**     | Execução de código serverless para automação ou enriquecimento          |
| **Logic App**          | Orquestração de workflows complexos                                     |
| **Webhook**            | Integração com ferramentas externas (PagerDuty, OpsGenie, Slack, Teams) |
| **Automation Runbook** | Execução de scripts de remediação automática                            |
| **ITSM**               | Integração com ServiceNow, Provance, etc.                               |
| **Event Hub**          | Streaming de alertas para pipelines de dados                            |
| **Secure Webhook**     | Webhook com autenticação via Azure AD                                   |

### Criando um Action Group com múltiplas ações

```bash
# Criar action group que combina notificação + automação
az monitor action-group create \
  --name ag-critical-oncall \
  --resource-group meu-rg \
  --short-name CritOnCall \
  --action email oncall-team oncall@empresa.com \
  --action sms oncall-sms "+5511999999999" \
  --action webhook pagerduty-integration "https://events.pagerduty.com/integration/<key>/enqueue" \
  --action automation-runbook auto-restart-service \
    "/subscriptions/<sub-id>/resourceGroups/meu-rg/providers/Microsoft.Automation/automationAccounts/meu-automation/runbooks/Restart-UnhealthyService" \
    "/subscriptions/<sub-id>/resourceGroups/meu-rg/providers/Microsoft.Automation/automationAccounts/meu-automation" \
    true

```

### Estratégia de escalonamento por severidade

Uma boa prática é criar Action Groups diferentes por nível de severidade:

```
Sev0 (Crítico)     → ag-sev0: PagerDuty (on-call) + SMS + Runbook auto-remediação
Sev1 (Alto)        → ag-sev1: Teams channel + Email do time + Ticket ITSM
Sev2 (Médio)       → ag-sev2: Teams channel + Email
Sev3 (Informativo) → ag-sev3: Log centralizado + Dashboard

```

```bash
# Exemplo: Action Group para Sev1 com criação automática de ticket
az monitor action-group create \
  --name ag-sev1-high \
  --resource-group meu-rg \
  --short-name Sev1High \
  --action email platform-team platform@empresa.com \
  --action webhook teams-channel "https://outlook.office.com/webhook/<teams-webhook-url>" \
  --action logic-app create-ticket \
    "/subscriptions/<sub-id>/resourceGroups/meu-rg/providers/Microsoft.Logic/workflows/lapp-create-incident-ticket" \
    "https://<logic-app-trigger-url>"

```

## Camada 3: Automação | Runbooks e auto-remediação

Aqui é onde a mágica acontece. Em vez de apenas notificar uma pessoa para executar um procedimento manual, **automatize as ações de remediação mais comuns**.

### Azure Automation Runbooks

Runbooks são scripts (PowerShell ou Python) que rodam no Azure Automation e podem ser acionados automaticamente por alertas.

#### Exemplo 1: Reiniciar um App Service não saudável

```powershell
# Runbook: Restart-UnhealthyAppService.ps1
param(
    [Parameter(Mandatory=$true)]
    [object]$WebhookData
)

# Parsear o payload do alerta
$alertPayload = ConvertFrom-Json -InputObject $WebhookData.RequestBody
$alertContext = $alertPayload.data.alertContext
$resourceId = $alertPayload.data.essentials.alertTargetIDs[0]

# Extrair informações do recurso
$resourceParts = $resourceId -split '/'
$resourceGroupName = $resourceParts[4]
$appServiceName = $resourceParts[8]

Write-Output "Alerta recebido: $($alertPayload.data.essentials.alertRule)"
Write-Output "Recurso afetado: $appServiceName no RG $resourceGroupName"

# Conectar usando Managed Identity
Connect-AzAccount -Identity

# Verificar o estado atual
$app = Get-AzWebApp -ResourceGroupName $resourceGroupName -Name $appServiceName
Write-Output "Estado atual: $($app.State)"

if ($app.State -ne "Running" -or $alertContext) {
    Write-Output "Reiniciando App Service $appServiceName..."
    Restart-AzWebApp -ResourceGroupName $resourceGroupName -Name $appServiceName

    # Aguardar e verificar
    Start-Sleep -Seconds 30
    $app = Get-AzWebApp -ResourceGroupName $resourceGroupName -Name $appServiceName
    Write-Output "Estado após restart: $($app.State)"

    if ($app.State -eq "Running") {
        Write-Output "✅ App Service reiniciado com sucesso."
    } else {
        Write-Output "⚠️ App Service não voltou ao estado Running. Escalonando para equipe."
        # Aqui você poderia chamar outro webhook para escalonar
    }
}

```

#### Exemplo 2: Escalar um VMSS quando CPU está crítica

```powershell
# Runbook: Scale-OutVMSS.ps1
param(
    [Parameter(Mandatory=$true)]
    [object]$WebhookData
)

$alertPayload = ConvertFrom-Json -InputObject $WebhookData.RequestBody
$resourceId = $alertPayload.data.essentials.alertTargetIDs[0]

$resourceParts = $resourceId -split '/'
$resourceGroupName = $resourceParts[4]
$vmssName = $resourceParts[8]

Connect-AzAccount -Identity

$vmss = Get-AzVmss -ResourceGroupName $resourceGroupName -VMScaleSetName $vmssName
$currentCapacity = $vmss.Sku.Capacity
$maxCapacity = 20
$scaleIncrement = 2

Write-Output "VMSS: $vmssName | Capacidade atual: $currentCapacity"

if ($currentCapacity + $scaleIncrement -le $maxCapacity) {
    $newCapacity = $currentCapacity + $scaleIncrement
    Write-Output "Escalando de $currentCapacity para $newCapacity instâncias..."

    $vmss.Sku.Capacity = $newCapacity
    Update-AzVmss -ResourceGroupName $resourceGroupName `
                  -VMScaleSetName $vmssName `
                  -VirtualMachineScaleSet $vmss

    Write-Output "✅ VMSS escalado para $newCapacity instâncias."
} else {
    Write-Output "⚠️ Capacidade máxima ($maxCapacity) atingida. Escalonando para equipe."
}

```

#### Exemplo 3: Diagnosticar e coletar evidências automaticamente

Nem toda automação precisa remediar. Às vezes, o mais valioso é **coletar informações diagnósticas automaticamente** para acelerar a investigação humana:

```powershell
# Runbook: Collect-IncidentDiagnostics.ps1
param(
    [Parameter(Mandatory=$true)]
    [object]$WebhookData
)

$alertPayload = ConvertFrom-Json -InputObject $WebhookData.RequestBody
$resourceId = $alertPayload.data.essentials.alertTargetIDs[0]
$alertTime = $alertPayload.data.essentials.firedDateTime

Connect-AzAccount -Identity

# Coletar métricas dos últimos 30 minutos
$startTime = (Get-Date $alertTime).AddMinutes(-30)
$endTime = Get-Date $alertTime

Write-Output "=== Diagnóstico automático de incidente ==="
Write-Output "Recurso: $resourceId"
Write-Output "Hora do alerta: $alertTime"
Write-Output "Janela de análise: $startTime até $endTime"

# Coletar métricas
$metrics = Get-AzMetric -ResourceId $resourceId `
    -TimeGrain 00:01:00 `
    -StartTime $startTime `
    -EndTime $endTime `
    -MetricName "CpuPercentage","MemoryPercentage","Http5xx","HttpResponseTime"

foreach ($metric in $metrics) {
    Write-Output "`n--- $($metric.Name.Value) ---"
    $metric.Data | Where-Object { $_.Average -ne $null } |
        Select-Object TimeStamp, Average, Maximum |
        Format-Table -AutoSize
}

# Coletar logs recentes do Activity Log
$activityLogs = Get-AzActivityLog `
    -StartTime $startTime `
    -EndTime $endTime `
    -ResourceId $resourceId `
    -MaxRecord 20

Write-Output "`n=== Activity Log (últimos 30 min) ==="
$activityLogs | Select-Object EventTimestamp, OperationName, Status, Caller |
    Format-Table -AutoSize

# Salvar resultado em um blob para referência
$diagnosticReport = @{
    AlertRule = $alertPayload.data.essentials.alertRule
    Severity = $alertPayload.data.essentials.severity
    FiredAt = $alertTime
    Resource = $resourceId
    MetricsSummary = $metrics | ForEach-Object {
        @{ Name = $_.Name.Value; MaxValue = ($_.Data | Measure-Object -Property Maximum -Maximum).Maximum }
    }
    RecentActivity = $activityLogs | Select-Object EventTimestamp, OperationName, Status
}

$reportJson = $diagnosticReport | ConvertTo-Json -Depth 5
Write-Output "`n=== Relatório JSON ==="
Write-Output $reportJson

```

### Decisão: quando automatizar vs. quando escalonar

Nem tudo deve ser automatizado. Use esta heurística:

| Cenário                                                                 | Ação recomendada                                     |
| ----------------------------------------------------------------------- | ---------------------------------------------------- |
| Problema conhecido com solução determinística (restart, scale-out)      | ✅ Automatizar completamente                          |
| Problema que requer investigação mas tem passos diagnósticos conhecidos | ⚡ Automatizar coleta de dados, escalonar para humano |
| Problema raro ou com alto risco de efeito colateral                     | 🧑 Notificar humano diretamente                      |
| Falha em cascata afetando múltiplos serviços                            | 🚨 Escalonar para war room imediatamente             |

## Camada 4: Gestão | Integração com ferramentas de on-call

Alertas do Azure Monitor precisam chegar à pessoa certa, no momento certo. Isso requer integração com ferramentas de **on-call rotation e incident management**.

### Integração com PagerDuty

```bash
# Criar webhook no Action Group para PagerDuty
az monitor action-group create \
  --name ag-pagerduty-oncall \
  --resource-group meu-rg \
  --short-name PD-OnCall \
  --action webhook pagerduty \
    "https://events.pagerduty.com/integration/<integration-key>/enqueue"

```

A integração nativa do PagerDuty com Azure Monitor já faz o mapeamento de severidade:

| Azure Monitor Severity | PagerDuty Urgency |
| ---------------------- | ----------------- |
| Sev0 (Critical)        | High              |
| Sev1 (Error)           | High              |
| Sev2 (Warning)         | Low               |
| Sev3 (Informational)   | Low               |

### Integração com Microsoft Teams para war rooms

Use Logic Apps para criar canais dedicados de war room automaticamente quando um incidente Sev0 é declarado:

```json
{
  "definition": {
    "triggers": {
      "When_alert_fires": {
        "type": "Request",
        "kind": "Http",
        "inputs": {
          "schema": {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "essentials": {
                    "type": "object",
                    "properties": {
                      "alertRule": { "type": "string" },
                      "severity": { "type": "string" },
                      "firedDateTime": { "type": "string" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "actions": {
      "Create_Teams_Channel": {
        "type": "ApiConnection",
        "inputs": {
          "method": "post",
          "path": "/v1.0/teams/<team-id>/channels",
          "body": {
            "displayName": "🚨 INC-@{formatDateTime(utcNow(), 'yyyyMMdd-HHmm')}",
            "description": "War room para incidente: @{triggerBody()?['data']?['essentials']?['alertRule']}"
          }
        }
      },
      "Post_Initial_Message": {
        "type": "ApiConnection",
        "runAfter": { "Create_Teams_Channel": ["Succeeded"] },
        "inputs": {
          "method": "post",
          "path": "/v1.0/teams/<team-id>/channels/@{body('Create_Teams_Channel')?['id']}/messages",
          "body": {
            "body": {
              "contentType": "html",
              "content": "<h2>🚨 Incidente Declarado</h2><p><b>Alerta:</b> @{triggerBody()?['data']?['essentials']?['alertRule']}</p><p><b>Severidade:</b> @{triggerBody()?['data']?['essentials']?['severity']}</p><p><b>Hora:</b> @{triggerBody()?['data']?['essentials']?['firedDateTime']}</p><hr/><p><b>Próximos passos:</b></p><ul><li>Incident Commander: [a ser definido]</li><li>Comunicação: atualizações a cada 15 min</li><li>Runbook: consultar Wiki/Runbooks</li></ul>"
            }
          }
        }
      }
    }
  }
}

```

### Integração com Azure DevOps para tracking

Automatize a criação de Work Items para cada incidente:

```bash
# Usando Azure DevOps CLI para criar um bug/incident automaticamente
az boards work-item create \
  --title "INC-$(date +%Y%m%d) - Alerta: <alert-name>" \
  --type "Bug" \
  --org "https://dev.azure.com/minha-org" \
  --project "MeuProjeto" \
  --area "Operations\\Incidents" \
  --fields "System.Tags=incident;sev0" \
           "Microsoft.VSTS.Common.Severity=1 - Critical" \
           "System.Description=<detalhes do alerta>"

```

## Construindo runbooks operacionais eficazes

Além da automação, sua equipe precisa de **runbooks documentados** para cenários que exigem intervenção humana. Um bom runbook é a diferença entre um engenheiro de on-call resolvendo em 10 minutos e outro levando 2 horas.

### Estrutura recomendada para runbooks

```markdown
# Runbook: [Nome do Cenário]

## Resumo
- **Serviço afetado**: [nome do serviço]
- **Impacto típico**: [o que o usuário percebe]
- **Severidade**: Sev[0-3]
- **SLO relacionado**: [qual SLO é impactado]

## Detecção
- **Alerta**: [nome do alerta no Azure Monitor]
- **Query KQL para validar**:
  ```kusto
  [query para confirmar o problema]

```

## Diagnóstico

1. Verificar \[métrica/log/dashboard\]
2. Confirmar se \[condição\] é verdadeira
3. Checar dependências: \[lista de dependências\]

## Remediação

### Caminho 1: \[cenário mais comum\]

1. Executar: `[comando]`
2. Verificar: `[validação]`
3. Confirmar recuperação no dashboard

### Caminho 2: \[cenário alternativo\]

1. Se o Caminho 1 não funcionar, \[próxima ação\]

## Escalonamento

- Se não resolver em \[X minutos\], escalonar para \[time/pessoa\]
- Canal de comunicação: \[Teams channel / bridge call\]

## Post-incidente

- \[ \] Registrar timeline no ticket
- \[ \] Atualizar este runbook se necessário
- \[ \] Agendar post-mortem se Sev0/Sev1

```

### Vinculando runbooks a alertas

Uma prática poderosa é incluir o link do runbook diretamente na descrição do alerta:

```bash
az monitor metrics alert create \
  --name "alert-api-error-rate-high" \
  --resource-group meu-rg \
  --scopes "<app-insights-resource-id>" \
  --condition "avg requests/failed > 10" \
  --severity 1 \
  --action ag-sev1-high \
  --description "Taxa de erro da API acima do limiar. Runbook: https://wiki.empresa.com/runbooks/api-error-rate-high"

```

## Post-mortems blameless: aprendendo com incidentes

O ciclo de resposta a incidentes não termina quando o serviço volta ao normal. A etapa mais importante para **melhoria contínua** é o **post-mortem blameless,** uma análise estruturada do incidente focada em aprendizado, não em culpa.

### Por que "blameless"?

Se as pessoas têm medo de serem punidas, elas escondem informações. Se escondem informações, você nunca descobre a causa raiz real. A cultura blameless entende que:

> **Sistemas complexos falham por múltiplos fatores combinados. Culpar uma pessoa é simplificar demais e perder a chance de corrigir o sistema.**

### Template de post-mortem

```markdown
# Post-Mortem: INC-20260324

## Resumo executivo
- **Data do incidente**: 2026-03-24
- **Duração**: 47 minutos (14:03 - 14:50 UTC)
- **Severidade**: Sev1
- **Impacto**: 12% das requisições da API retornaram erro 503
- **Usuários afetados**: ~3.200
- **SLO impactado**: Disponibilidade (target: 99.9%, real na janela: 99.2%)
- **Error budget consumido**: 8.4% do budget mensal

## Timeline
| Hora (UTC) | Evento |
|------------|--------|
| 14:00 | Deploy v2.14.3 iniciado no slot de staging |
| 14:03 | Swap de slots executado (staging → production) |
| 14:05 | Alerta "API Error Rate > 1%" disparou (MTTD: 2 min) |
| 14:08 | On-call recebe notificação PagerDuty (MTTE: 5 min) |
| 14:12 | On-call confirma erro 503 no Application Insights |
| 14:15 | Identificada connection string incorreta no novo deployment |
| 14:18 | Rollback iniciado (swap reverso) |
| 14:22 | Rollback concluído, erros cessam |
| 14:50 | Métricas confirmam retorno ao estado estável (MTTR: 47 min) |

## Causa raiz
A variável de ambiente `COSMOS_CONNECTION_STRING` foi alterada no
App Configuration mas não foi atualizada no slot de staging. O swap
de slots carregou a configuração desatualizada em produção.

## Fatores contribuintes
1. Não havia validação automatizada de configurações pré-swap.
2. O health check do slot não testava conectividade com Cosmos DB.
3. O runbook de deploy não incluía verificação de App Configuration.

## O que funcionou bem
- ✅ Alerta disparou em 2 minutos (dentro do target de MTTD).
- ✅ On-call respondeu em 5 minutos (dentro do target de MTTE).
- ✅ Rollback foi rápido graças ao uso de deployment slots.

## O que pode melhorar
- ⚠️ Health check precisa validar dependências (DB, cache, etc.).
- ⚠️ Pipeline de deploy precisa validar configurações antes do swap.
- ⚠️ Faltava alerta de "configuração divergente entre slots".

## Ações corretivas (Action Items)
| # | Ação | Responsável | Prazo | Status |
|---|------|-------------|-------|--------|
| 1 | Adicionar health check que valida Cosmos DB | Time Backend | 1 semana | Pendente |
| 2 | Criar step no pipeline que compara App Config entre slots | Time DevOps | 2 semanas | Pendente |
| 3 | Adicionar alerta de drift de configuração | Time SRE | 1 semana | Pendente |
| 4 | Atualizar runbook de deploy com checklist pré-swap | Time DevOps | 1 semana | Pendente |

```

### KQL para análise de post-mortem

Durante o post-mortem, queries KQL ajudam a reconstruir a timeline com precisão:

```kusto
// Reconstruir o impacto do incidente minuto a minuto
let incidentStart = datetime(2026-03-24T14:00:00Z);
let incidentEnd = datetime(2026-03-24T15:00:00Z);
requests
| where timestamp between (incidentStart .. incidentEnd)
| summarize
    totalRequests = count(),
    failedRequests = countif(resultCode startswith "5"),
    avgDuration = avg(duration),
    p95Duration = percentile(duration, 95),
    p99Duration = percentile(duration, 99)
  by bin(timestamp, 1m)
| extend errorRate = round(100.0 * failedRequests / totalRequests, 2)
| order by timestamp asc

```

```kusto
// Identificar quais operações foram mais afetadas
let incidentStart = datetime(2026-03-24T14:03:00Z);
let incidentEnd = datetime(2026-03-24T14:22:00Z);
requests
| where timestamp between (incidentStart .. incidentEnd)
| where success == false
| summarize
    failedCount = count(),
    distinctUsers = dcount(user_Id)
  by name, resultCode
| order by failedCount desc
| take 10

```

```kusto
// Correlacionar com mudanças no Activity Log (deploys, config changes)
AzureActivity
| where TimeGenerated between (datetime(2026-03-24T13:30:00Z) .. datetime(2026-03-24T15:00:00Z))
| where OperationNameValue has_any ("Microsoft.Web/sites/slots/slotsswap",
                                      "Microsoft.Web/sites/config/write",
                                      "Microsoft.AppConfiguration")
| project TimeGenerated, OperationNameValue, ActivityStatusValue, Caller
| order by TimeGenerated asc

```

## Montando a operação: um framework completo

Juntando tudo, aqui está como organizar sua operação de resposta a incidentes no Azure:

### 1\. Antes do incidente (preparação)

- SLIs e SLOs definidos (com burn rate alerts configurados).
- Action Groups criados por severidade, com escalation path claro.
- Runbooks documentados e vinculados a cada alerta.
- Automação configurada para cenários conhecidos (restart, scale-out, diagnóstico).
- Rotação de on-call definida na ferramenta de incident management.
- Game Day periódico para testar o fluxo completo (veja nosso artigo sobre [Engenharia de Caos](https://www.azurebrasil.cloud/blog/engenharia-de-caos-no-azure-validando-resiliencia-em-producao-com-azure-chaos-studio/)).

### 2\. Durante o incidente (resposta)

```
Alerta dispara
    ↓
Action Group notifica on-call + executa automação
    ↓
On-call avalia: automação resolveu?
    ├── SIM → Verificar métricas, fechar alerta, registrar
    └── NÃO → Seguir runbook
                 ↓
              Resolveu?
              ├── SIM → Registrar e monitorar
              └── NÃO → Escalonar
                          ↓
                       War room (Teams channel automático)
                          ↓
                       Incident Commander coordena resposta
                          ↓
                       Resolução + comunicação para stakeholders

```

### 3\. Depois do incidente (aprendizado)

- Post-mortem blameless em até 48 horas (para Sev0/Sev1).
- Action items registrados e rastreados até conclusão.
- Runbooks atualizados com os aprendizados.
- Alertas revisados, precisa de novo alerta? Algum alerta precisa ser ajustado?
- Novo experimento de caos para validar as correções.

## Métricas operacionais: medindo a maturidade

Para saber se sua operação está melhorando, acompanhe estas métricas ao longo do tempo:

| Métrica                     | Como medir                                                 | Meta               |
| --------------------------- | ---------------------------------------------------------- | ------------------ |
| **MTTD**                    | Timestamp do alerta - timestamp do início real do problema | Diminuir mês a mês |
| **MTTE**                    | Timestamp do acknowledge - timestamp do alerta             | < 15 min para Sev0 |
| **MTTR**                    | Timestamp da recuperação - timestamp do início             | Diminuir mês a mês |
| **Incidentes/mês**          | Contagem de incidentes Sev0+Sev1                           | Diminuir mês a mês |
| **% de auto-remediação**    | Incidentes resolvidos por automação / total                | Aumentar mês a mês |
| **Action items concluídos** | Items de post-mortem fechados / abertos                    | \> 80% no prazo    |
| **Alert fatigue**           | Alertas que não resultaram em ação / total de alertas      | < 20%              |

```kusto
// Dashboard KQL: MTTR por mês (requer custom tracking table)
IncidentTracking_CL
| where TimeGenerated >= ago(180d)
| where Severity_s in ("Sev0", "Sev1")
| extend MTTR_minutes = datetime_diff('minute', ResolvedAt_t, DetectedAt_t)
| summarize
    avgMTTR = avg(MTTR_minutes),
    p50MTTR = percentile(MTTR_minutes, 50),
    p95MTTR = percentile(MTTR_minutes, 95),
    incidentCount = count()
  by bin(TimeGenerated, 30d)
| order by TimeGenerated asc

```

## Conclusão

Resposta a incidentes não é sobre ter um herói que acorda às 3h da manhã e resolve tudo sozinho. É sobre construir um **sistema** de alertas inteligentes, automação confiável, processos claros e cultura de aprendizado que minimiza o impacto dos incidentes inevitáveis.

No Azure, você tem todas as peças: Azure Monitor para detecção, Action Groups para notificação, Automation Runbooks e Logic Apps para automação, e integração nativa com ferramentas de on-call como PagerDuty e Microsoft Teams.

A jornada que construímos nos últimos artigos forma um ciclo completo:

1. **Engenharia de Caos** → Descubra fragilidades antes que elas virem incidentes.
2. **SRE (SLIs/SLOs/Error Budgets)** → Meça a confiabilidade com dados objetivos.
3. **Resposta a Incidentes** → Quando o incidente acontecer, detecte rápido, responda com automação e aprenda com cada ocorrência.

O resultado é um sistema que não apenas é resiliente por design, mas que **melhora continuamente** a cada incidente. E essa é a verdadeira essência de operações maduras na nuvem.