> ## 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.

# SRE no Azure: implementando SLIs, SLOs e Error Budgets com Azure Monitor
- URL: https://www.azurebrasil.cloud/blog/sre-no-azure-implementando-slis-slos-e-error-budgets-com-azure-monitor/
- Published: 2026-03-30T12:01:17.000Z
- Updated: 2026-03-30T12:01:17.000Z
- Author: Ricardo Martins

Você já configurou alta disponibilidade, implementou observabilidade, e até validou a resiliência com Engenharia de Caos. Mas como responder com confiança à pergunta mais importante que o negócio faz: **"nosso sistema é confiável o suficiente?"**

Essa é a pergunta central da **Site Reliability Engineering (SRE),** e a resposta não é "temos 99,9% de uptime no SLA". A resposta precisa ser baseada em **dados reais**, medidos do ponto de vista do usuário, com critérios objetivos que orientam decisões de engenharia.

Neste artigo, vamos explorar como implementar os pilares fundamentais de SRE no Azure: **SLIs (Service Level Indicators)**, **SLOs (Service Level Objectives)** e **Error Budgets**, usando Azure Monitor, Application Insights e KQL como base.

## O que é SRE e por que importa?

Site Reliability Engineering é uma disciplina criada pelo Google que aplica práticas de engenharia de software à operação de infraestrutura. O objetivo não é buscar 100% de disponibilidade, isso é impossível e economicamente inviável, mas sim **definir um nível aceitável de confiabilidade** e gerenciar o equilíbrio entre velocidade de entrega e estabilidade.

Os três conceitos fundamentais são:

| Conceito                          | Descrição                                                                                                                                 |
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| **SLI** (Service Level Indicator) | Uma métrica quantitativa que reflete a saúde do serviço do ponto de vista do usuário. Exemplos: latência, taxa de erro, throughput.       |
| **SLO** (Service Level Objective) | Um alvo interno para o SLI. Exemplo: "99,9% das requisições devem ter latência abaixo de 500ms em uma janela de 30 dias".                 |
| **Error Budget**                  | A margem de erro permitida pelo SLO. Se o SLO é 99,9%, o error budget é 0,1% — o quanto o sistema pode falhar antes de violar o objetivo. |

> **SLA vs. SLO**: O SLA (Service Level Agreement) é um contrato externo com penalidades. O SLO é um objetivo interno, tipicamente mais rigoroso que o SLA. Você define SLOs para garantir que nunca chegue perto de violar o SLA.

## Por que SLIs, SLOs e Error Budgets mudam o jogo?

Sem SLOs, as equipes operam com base em intuição:

- **Desenvolvimento** quer entregar features o mais rápido possível.
- **Operações** quer estabilidade máxima e resiste a mudanças.
- **Negócio** quer ambos, mas não tem como arbitrar.

Com SLOs e Error Budgets, essa tensão se resolve com dados:

- **Error Budget sobrando?** O time pode fazer deploys mais agressivos, experimentar, inovar.
- **Error Budget apertado?** Hora de desacelerar, focar em confiabilidade, corrigir debt técnico.
- **Error Budget esgotado?** Congelar mudanças até recuperar. Priorizar estabilidade.

Essa é a essência: **o error budget é a moeda que compra velocidade de entrega**.

## Definindo SLIs eficazes

O primeiro passo é escolher indicadores que reflitam genuinamente a experiência do usuário. Um SLI ruim leva a um SLO inútil.

### Princípios para bons SLIs

1. **Meça do ponto de vista do usuário**: não meça CPU do servidor — meça latência percebida pelo cliente.
2. **Use proporções**: "X% das requisições atendem o critério Y" é mais útil que médias.
3. **Seja específico**: "latência do endpoint `/api/orders`" é melhor que "latência geral da aplicação".
4. **Cubra as dimensões certas**: disponibilidade, latência, qualidade (correção) e throughput.

### SLIs recomendados por tipo de serviço

| Tipo de serviço                  | SLIs recomendados                                                                             |
| -------------------------------- | --------------------------------------------------------------------------------------------- |
| **API / Web Service**            | Disponibilidade (% de respostas não-5xx), Latência (P50, P95, P99), Taxa de erro              |
| **Pipeline de dados**            | Freshness (tempo desde última atualização), Completude (% de registros processados), Correção |
| **Storage / Banco de dados**     | Latência de leitura/escrita, Disponibilidade, Durabilidade                                    |
| **Serviço de streaming**         | Latência end-to-end, Taxa de mensagens perdidas, Throughput                                   |
| **Aplicação de IA / Inferência** | Latência de inferência (P95), Disponibilidade do endpoint, Taxa de erro do modelo             |

## Implementando SLIs no Azure com Application Insights e KQL

Vamos implementar SLIs concretos para uma API hospedada no Azure (App Service, AKS ou Container Apps) instrumentada com Application Insights.

### SLI de Disponibilidade

A disponibilidade é medida como a proporção de requisições bem-sucedidas (não-5xx) sobre o total de requisições.

```kusto
// SLI de Disponibilidade — janela de 30 dias
let janela = 30d;
requests
| where timestamp > ago(janela)
| summarize
    totalRequests = count(),
    successfulRequests = countif(toint(resultCode) < 500),
    sli_availability = round(100.0 * countif(toint(resultCode) < 500) / count(), 4)

```

### SLI de Latência

A latência é medida como a proporção de requisições abaixo de um limiar aceitável.

```kusto
// SLI de Latência — % de requisições abaixo de 500ms
let janela = 30d;
let limiar_ms = 500;
requests
| where timestamp > ago(janela)
| summarize
    totalRequests = count(),
    fastRequests = countif(duration < limiar_ms),
    sli_latency = round(100.0 * countif(duration < limiar_ms) / count(), 4)

```

### SLI de Latência por endpoint crítico

Nem todos os endpoints têm a mesma importância. Defina SLIs específicos para jornadas críticas:

```kusto
// SLI de Latência por endpoint
let janela = 30d;
let limiar_ms = 500;
requests
| where timestamp > ago(janela)
| where name in ("/api/orders", "/api/payments", "/api/auth/login")
| summarize
    totalRequests = count(),
    fastRequests = countif(duration < limiar_ms),
    sli_latency = round(100.0 * countif(duration < limiar_ms) / count(), 4)
  by name
| order by sli_latency asc

```

### SLI de Disponibilidade com dependências

Muitas vezes a falha não está na sua aplicação, mas em uma dependência (banco de dados, API externa, cache). Meça isso:

```kusto
// SLI de Disponibilidade de dependências
let janela = 30d;
dependencies
| where timestamp > ago(janela)
| summarize
    totalCalls = count(),
    successfulCalls = countif(success == true),
    sli_dependency = round(100.0 * countif(success == true) / count(), 4)
  by target, type
| order by sli_dependency asc

```

## Definindo SLOs

Com os SLIs implementados, o próximo passo é definir **objetivos** para cada um. Um SLO é a combinação de:

1. **O SLI** (o que medir)
2. **O alvo** (o valor aceitável)
3. **A janela de tempo** (o período de avaliação)

### Exemplos de SLOs bem definidos

| SLO                                       | SLI                                     | Alvo         | Janela            |
| ----------------------------------------- | --------------------------------------- | ------------ | ----------------- |
| Disponibilidade da API                    | % de respostas não-5xx                  | ≥ 99,9%      | 30 dias (rolling) |
| Latência da API                           | % de requisições < 500ms                | ≥ 95%        | 30 dias (rolling) |
| Latência P99 da API                       | Percentil 99 da latência                | ≤ 2000ms     | 30 dias (rolling) |
| Disponibilidade do endpoint de pagamentos | % de respostas não-5xx em /api/payments | ≥ 99,95%     | 30 dias (rolling) |
| Freshness do pipeline de dados            | Tempo desde última ingestão             | ≤ 15 minutos | Contínuo          |

### Como escolher o alvo certo?

Definir o alvo do SLO é uma decisão de negócio, não apenas técnica:

- **Analise dados históricos**: qual é o SLI atual? Se sua disponibilidade real é 99,95%, um SLO de 99,99% seria aspiracional demais.
- **Considere o impacto no usuário**: uma API interna pode ter SLO de 99,5%. Um sistema de pagamentos precisa de 99,99%.
- **Alinhe com o SLA**: o SLO deve ser mais rigoroso que o SLA externo. Se o SLA é 99,9%, o SLO deveria ser 99,95%.
- **Comece conservador**: é melhor ter um SLO que você consegue cumprir e apertar gradualmente.

### Consulta KQL para avaliar SLOs

```kusto
// Dashboard de SLOs — visão consolidada
let janela = 30d;
let slo_disponibilidade = 99.9;
let slo_latencia = 95.0;
let limiar_latencia_ms = 500;
requests
| where timestamp > ago(janela)
| summarize
    total = count(),
    // SLI de disponibilidade
    sucesso = countif(toint(resultCode) < 500),
    sli_disponibilidade = round(100.0 * countif(toint(resultCode) < 500) / count(), 4),
    // SLI de latência
    rapidas = countif(duration < limiar_latencia_ms),
    sli_latencia = round(100.0 * countif(duration < limiar_latencia_ms) / count(), 4),
    // Percentis
    p50 = round(percentile(duration, 50), 1),
    p95 = round(percentile(duration, 95), 1),
    p99 = round(percentile(duration, 99), 1)
| extend
    status_disponibilidade = iff(sli_disponibilidade >= slo_disponibilidade, "✅ Dentro do SLO", "🛑 Violação de SLO"),
    status_latencia = iff(sli_latencia >= slo_latencia, "✅ Dentro do SLO", "🛑 Violação de SLO"),
    // Error budget
    budget_total_disponibilidade = round(total * (100.0 - slo_disponibilidade) / 100.0, 0),
    budget_consumido_disponibilidade = total - sucesso,
    budget_total_latencia = round(total * (100.0 - slo_latencia) / 100.0, 0),
    budget_consumido_latencia = total - rapidas
| extend
    budget_restante_disponibilidade_pct = round(100.0 * (1 - (toreal(budget_consumido_disponibilidade) / budget_total_disponibilidade)), 2),
    budget_restante_latencia_pct = round(100.0 * (1 - (toreal(budget_consumido_latencia) / budget_total_latencia)), 2)

```

## Error Budgets: a moeda da confiabilidade

O Error Budget é o conceito mais transformador de SRE. Ele converte o SLO em algo acionável.

### Calculando o Error Budget

Se o SLO de disponibilidade é **99,9%** em uma janela de **30 dias**:

```
Error Budget = 100% - 99,9% = 0,1%

Em uma janela de 30 dias:
- Total de minutos: 30 × 24 × 60 = 43.200 minutos
- Error Budget em minutos: 43.200 × 0,001 = 43,2 minutos

Em requisições (supondo 1 milhão de requisições/mês):
- Error Budget em requisições: 1.000.000 × 0,001 = 1.000 requisições com erro permitidas

```

Isso significa que o sistema pode falhar **43 minutos por mês** ou **1.000 requisições** antes de violar o SLO.

### Monitorando o consumo do Error Budget ao longo do tempo

```kusto
// Consumo diário do Error Budget de disponibilidade
let janela = 30d;
let slo = 99.9;
requests
| where timestamp > ago(janela)
| summarize
    total = count(),
    falhas = countif(toint(resultCode) >= 500)
  by bin(timestamp, 1d)
| order by timestamp asc
| extend
    falhas_acumuladas = row_cumsum(falhas),
    total_acumulado = row_cumsum(total)
| extend
    budget_total = round(total_acumulado * (100.0 - slo) / 100.0, 0),
    budget_consumido = falhas_acumuladas
| extend
    budget_restante_pct = round(100.0 * (1.0 - toreal(budget_consumido) / toreal(budget_total)), 2)
| project
    timestamp,
    falhas_dia = falhas,
    falhas_acumuladas,
    budget_total,
    budget_consumido,
    budget_restante_pct

```

### Taxa de queima (Burn Rate)

O Error Budget sozinho diz quanto já foi consumido. A **burn rate** (taxa de queima) diz **quão rápido** está sendo consumido — e isso é fundamental para alertas.

```
Burn Rate = taxa_de_erro_atual / taxa_de_erro_permitida_pelo_SLO

Se burn rate = 1: o budget será consumido exatamente no fim da janela (normal).
Se burn rate = 10: o budget será esgotado 10x mais rápido que o esperado (urgente!).
Se burn rate = 0.5: o budget está sendo consumido pela metade da taxa — tudo tranquilo.

```

```kusto
// Burn rate das últimas 1h e 6h
let slo = 99.9;
let taxa_erro_permitida = (100.0 - slo) / 100.0;  // 0.001
// Burn rate da última 1 hora
let br_1h = toscalar(
    requests
    | where timestamp > ago(1h)
    | summarize taxa_erro = 1.0 * countif(toint(resultCode) >= 500) / count()
) / taxa_erro_permitida;
// Burn rate das últimas 6 horas
let br_6h = toscalar(
    requests
    | where timestamp > ago(6h)
    | summarize taxa_erro = 1.0 * countif(toint(resultCode) >= 500) / count()
) / taxa_erro_permitida;
print burn_rate_1h = round(br_1h, 2), burn_rate_6h = round(br_6h, 2),
      alerta = case(
          br_1h > 14.4, "🔴 CRÍTICO — budget esgota em ~1h",
          br_1h > 6, "🟠 ALTO — budget esgota em ~5h",
          br_6h > 3, "🟡 MÉDIO — budget esgota em ~10h",
          br_6h > 1, "🔵 BAIXO — consumo acima do ideal",
          "✅ Normal")

```

## Alertas baseados em Burn Rate

Alertas tradicionais baseados em thresholds estáticos (ex: "alerte se a taxa de erro > 1%") são problemáticos:

- **Threshold alto**: perde incidentes lentos que drenam o budget gradualmente.
- **Threshold baixo**: gera alertas excessivos para picos momentâneos que não impactam o SLO.

Alertas baseados em burn rate resolvem isso. O Google SRE Book recomenda uma abordagem com **múltiplas janelas**:

| Severidade     | Burn Rate | Janela curta | Janela longa | Budget consumido em | Ação                |
| -------------- | --------- | ------------ | ------------ | ------------------- | ------------------- |
| Crítico (page) | 14.4x     | 1 hora       | —            | \~1 hora            | Resposta imediata   |
| Alto (page)    | 6x        | —            | 6 horas      | \~5 horas           | Investigar urgente  |
| Médio (ticket) | 3x        | —            | 3 dias       | \~10 dias           | Planejar correção   |
| Baixo (log)    | 1x        | —            | 30 dias      | \~30 dias           | Monitorar tendência |

### Implementando alertas no Azure Monitor

```kusto
// Alert Rule — Burn Rate Crítico (>14.4x na última hora)
let slo = 99.9;
let taxa_erro_permitida = (100.0 - slo) / 100.0;
let burn_rate_threshold = 14.4;
requests
| where timestamp > ago(1h)
| summarize
    total = count(),
    erros = countif(toint(resultCode) >= 500)
| extend
    taxa_erro = 1.0 * erros / total,
    burn_rate = (1.0 * erros / total) / taxa_erro_permitida
| where burn_rate > burn_rate_threshold
| project
    alerta = "CRÍTICO: Burn rate de disponibilidade acima de 14.4x",
    burn_rate = round(burn_rate, 2),
    taxa_erro_pct = round(taxa_erro * 100, 4),
    total_requisicoes = total,
    total_erros = erros

```

Para criar o alerta via CLI:

```bash
# Criar scheduled query alert rule para burn rate crítico
az monitor scheduled-query create \
  --resource-group meu-rg \
  --name "slo-burn-rate-critico" \
  --scopes "/subscriptions/<sub-id>/resourceGroups/meu-rg/providers/Microsoft.Insights/components/meu-appinsights" \
  --condition "count 'BurnRateAlto' > 0" \
  --condition-query BurnRateAlto="requests | where timestamp > ago(1h) | summarize total=count(), erros=countif(toint(resultCode) >= 500) | extend burn_rate=(1.0*erros/total)/0.001 | where burn_rate > 14.4" \
  --severity 0 \
  --evaluation-frequency 5m \
  --window-size 5m \
  --action-groups "/subscriptions/<sub-id>/resourceGroups/meu-rg/providers/Microsoft.Insights/actionGroups/time-oncall"

```

---

## Criando um Workbook de SLO no Azure

Um dashboard de SLOs precisa responder três perguntas em segundos:

1. **Estamos dentro do SLO?** (sim/não, por serviço)
2. **Quanto error budget resta?** (% restante na janela atual)
3. **Qual é a tendência?** (burn rate — estamos melhorando ou piorando?)

### Estrutura recomendada do Workbook

| Seção                | Conteúdo                                                                      |
| -------------------- | ----------------------------------------------------------------------------- |
| **Resumo executivo** | Semáforo por serviço: 🟢 dentro do SLO, 🟡 budget < 30%, 🔴 SLO violado       |
| **SLIs atuais**      | Valores atuais de cada SLI vs. alvo do SLO                                    |
| **Error Budget**     | Gráfico de consumo acumulado do budget ao longo da janela de 30 dias          |
| **Burn Rate**        | Gráfico de burn rate nas últimas 24h com linhas de referência (1x, 6x, 14.4x) |
| **Histórico de SLO** | Compliance do SLO nos últimos 3-6 meses (tendência mensal)                    |
| **Incidentes**       | Correlação entre consumo de budget e incidentes/deploys                       |

### Query para o semáforo por serviço

```kusto
// Semáforo de SLOs por serviço
let janela = 30d;
let slo_disponibilidade = 99.9;
let slo_latencia = 95.0;
let limiar_latencia_ms = 500;
requests
| where timestamp > ago(janela)
| extend servico = tostring(split(cloud_RoleName, "-")[0])
| summarize
    total = count(),
    sli_disp = round(100.0 * countif(toint(resultCode) < 500) / count(), 3),
    sli_lat = round(100.0 * countif(duration < limiar_latencia_ms) / count(), 3)
  by servico
| extend
    budget_disp_restante = round(100.0 * (1.0 - (total * (1 - sli_disp/100.0)) / (total * (1 - slo_disponibilidade/100.0))), 1),
    budget_lat_restante = round(100.0 * (1.0 - (total * (1 - sli_lat/100.0)) / (total * (1 - slo_latencia/100.0))), 1)
| extend
    status_disp = case(
        budget_disp_restante <= 0, "🔴 Violado",
        budget_disp_restante < 30, "🟡 Atenção",
        "🟢 OK"),
    status_lat = case(
        budget_lat_restante <= 0, "🔴 Violado",
        budget_lat_restante < 30, "🟡 Atenção",
        "🟢 OK")
| project servico, sli_disp, status_disp, budget_disp_restante, sli_lat, status_lat, budget_lat_restante
| order by budget_disp_restante asc

```

## Error Budget Policies: transformando dados em decisões

Ter SLOs e Error Budgets sem uma política de ação é como ter um velocímetro sem limites de velocidade. A **Error Budget Policy** define o que acontece quando o budget atinge determinados níveis.

### Exemplo de Error Budget Policy

```
╔══════════════════════════════════════════════════════════════════╗
║                    ERROR BUDGET POLICY                          ║
║                    Serviço: API de Pedidos                      ║
╠══════════════════════════════════════════════════════════════════╣
║                                                                  ║
║  SLO: 99,9% de disponibilidade em janela rolling de 30 dias     ║
║                                                                  ║
║  Budget > 50%:                                                   ║
║    → Operação normal                                             ║
║    → Deploys liberados conforme pipeline padrão                  ║
║    → Experimentos de Chaos Engineering recomendados              ║
║                                                                  ║
║  Budget entre 30% e 50%:                                         ║
║    → Revisar incidentes recentes e ações corretivas              ║
║    → Reduzir frequência de deploys para 1x/dia                   ║
║    → Priorizar itens de confiabilidade no backlog                ║
║                                                                  ║
║  Budget entre 10% e 30%:                                         ║
║    → Feature freeze: apenas correções críticas e melhorias       ║
║      de confiabilidade                                           ║
║    → Postmortem obrigatório para qualquer novo incidente         ║
║    → Suspender experimentos de Chaos Engineering                 ║
║                                                                  ║
║  Budget < 10%:                                                   ║
║    → Deploy freeze total                                         ║
║    → Equipe focada exclusivamente em restaurar confiabilidade    ║
║    → Escalação para liderança de engenharia                      ║
║    → Revisão arquitetural obrigatória                            ║
║                                                                  ║
║  Budget esgotado (SLO violado):                                  ║
║    → Incident review com liderança                               ║
║    → Plano de ação documentado com prazos                        ║
║    → Revisão do SLO: o alvo é realista?                          ║
║                                                                  ║
╚══════════════════════════════════════════════════════════════════╝

```

> **Conexão com Chaos Engineering**: se você já leu o artigo sobre \[Engenharia de Caos com Azure Chaos Studio\], note como o Error Budget determina **quando** executar experimentos de caos. Com budget folgado, é o momento ideal para validar resiliência. Com budget apertado, o foco é estabilizar.

## Integrando SLOs no ciclo de engenharia

### SLOs e CI/CD

Integre a verificação de SLOs no pipeline de deployment:

```yaml
# GitHub Actions — gate de SLO antes do deploy em produção
- name: Verificar Error Budget
  uses: azure/cli@v2
  with:
    inlineScript: |
      # Consultar error budget via Log Analytics
      BUDGET=$(az monitor log-analytics query \
        --workspace ${{ env.WORKSPACE_ID }} \
        --analytics-query "
          requests
          | where timestamp > ago(30d)
          | summarize sli = 100.0 * countif(toint(resultCode) < 500) / count()
          | extend budget_restante = round(100.0 * (1.0 - ((100.0 - sli) / (100.0 - 99.9))), 2)
          | project budget_restante
        " \
        --query "[0].budget_restante" -o tsv)

      echo "Error Budget restante: ${BUDGET}%"

      # Bloquear deploy se budget está abaixo de 30%
      if (( $(echo "$BUDGET < 30" | bc -l) )); then
        echo "::error::Error budget abaixo de 30% (${BUDGET}%). Deploy bloqueado."
        echo "Priorize correções de confiabilidade antes de deployar novas features."
        exit 1
      fi

- name: Deploy para produção
  if: success()
  run: |
    echo "Error budget saudável. Prosseguindo com deploy..."

```

### SLOs e Postmortems

Todo incidente que consome error budget significativo deve gerar um postmortem. A estrutura recomendada:

1. **Impacto no SLO**: quanto error budget foi consumido?
2. **Timeline**: o que aconteceu, quando, e como foi detectado?
3. **Causa raiz**: por que aconteceu? (use os "5 porquês")
4. **Ações corretivas**: o que será feito para prevenir recorrência?
5. **Lições aprendidas**: o que aprendemos sobre nossos SLIs/SLOs?

## Armadilhas comuns ao implementar SLOs

### 1\. Medir o que é fácil, não o que é importante

**Errado**: usar CPU, memória ou health check como SLI. **Certo**: medir latência e taxa de erro das requisições reais dos usuários.

Health checks podem retornar 200 enquanto o endpoint de login está retornando 500\. CPU pode estar em 20% enquanto o banco de dados está com deadlock.

### 2\. Definir SLOs sem dados históricos

**Errado**: "nosso SLO será 99,99% porque isso soa bem". **Certo**: analisar os dados dos últimos 3-6 meses, entender o baseline real, e definir um SLO alcançável mas desafiador.

```kusto
// Analisar disponibilidade histórica por mês para definir SLO realista
requests
| where timestamp > ago(180d)
| summarize
    sli_disponibilidade = round(100.0 * countif(toint(resultCode) < 500) / count(), 4),
    total = count()
  by mes = startofmonth(timestamp)
| order by mes asc

```

### 3\. Não ter Error Budget Policy

SLOs sem política de ação são apenas números em um dashboard. O valor real vem de **decisões automatizadas ou semi-automatizadas** baseadas no estado do budget.

### 4\. Janela de tempo inadequada

- **Janela muito curta** (1 dia): gera volatilidade excessiva. Um pico de erros de 5 minutos pode "violar" o SLO do dia.
- **Janela muito longa** (90 dias): reage lentamente a degradações. Um mês ruim é diluído pelos meses bons.
- **Recomendação**: janela rolling de **30 dias** para a maioria dos cenários.

### 5\. SLOs uniformes para tudo

Nem todos os endpoints merecem o mesmo SLO:

```kusto
// Exemplo: SLOs diferenciados por criticidade
let janela = 30d;
requests
| where timestamp > ago(janela)
| extend criticidade = case(
    name has "/api/payments" or name has "/api/auth", "crítico",
    name has "/api/orders" or name has "/api/users", "alto",
    name has "/api/reports" or name has "/api/search", "médio",
    "baixo")
| extend slo_alvo = case(
    criticidade == "crítico", 99.95,
    criticidade == "alto", 99.9,
    criticidade == "médio", 99.5,
    99.0)
| summarize
    total = count(),
    sli = round(100.0 * countif(toint(resultCode) < 500) / count(), 3),
    take_any(slo_alvo)
  by criticidade
| extend
    dentro_slo = iff(sli >= slo_alvo, "✅", "🛑"),
    margem = round(sli - slo_alvo, 3)
| order by slo_alvo desc

```

## Exemplo completo: implementando SRE para uma aplicação no AKS

Vamos juntar tudo em um cenário prático. Considere uma aplicação de e-commerce rodando no AKS com os seguintes componentes:

- **API Gateway** (NGINX Ingress)
- **Serviço de Pedidos** (orders-api)
- **Serviço de Pagamentos** (payments-api)
- **Serviço de Catálogo** (catalog-api)
- **Banco de dados** (Azure SQL + Cosmos DB)

### Passo 1: Definir SLOs por serviço

| Serviço     | SLI                 | SLO      | Error Budget (30d, \~1M req) |
| ----------- | ------------------- | -------- | ---------------------------- |
| API Gateway | Disponibilidade     | ≥ 99,95% | 500 erros                    |
| Pedidos     | Disponibilidade     | ≥ 99,9%  | 1.000 erros                  |
| Pedidos     | Latência (< 800ms)  | ≥ 95%    | 50.000 req lentas            |
| Pagamentos  | Disponibilidade     | ≥ 99,99% | 100 erros                    |
| Pagamentos  | Latência (< 1000ms) | ≥ 99%    | 10.000 req lentas            |
| Catálogo    | Disponibilidade     | ≥ 99,5%  | 5.000 erros                  |
| Catálogo    | Latência (< 300ms)  | ≥ 90%    | 100.000 req lentas           |

### Passo 2: Implementar coleta de SLIs

Garanta que todos os serviços estejam instrumentados com o SDK do Application Insights (ou OpenTelemetry exportando para Application Insights):

```bash
# Para aplicações .NET no AKS, configurar via variáveis de ambiente
kubectl set env deployment/orders-api \
  APPLICATIONINSIGHTS_CONNECTION_STRING="InstrumentationKey=<key>;IngestionEndpoint=https://brazilsouth-1.in.applicationinsights.azure.com/"

# Para aplicações com OpenTelemetry, usar o Azure Monitor Exporter
# Isso garante que requests e dependencies sejam capturados automaticamente

```

### Passo 3: Criar alertas de burn rate

```bash
# Alerta crítico para payments-api (SLO 99,99%)
az monitor scheduled-query create \
  --resource-group meu-rg \
  --name "slo-payments-burn-rate-critico" \
  --scopes "/subscriptions/<sub-id>/resourceGroups/meu-rg/providers/Microsoft.Insights/components/meu-appinsights" \
  --condition "count 'BurnRate' > 0" \
  --condition-query BurnRate="requests | where timestamp > ago(1h) | where cloud_RoleName == 'payments-api' | summarize total=count(), erros=countif(toint(resultCode) >= 500) | extend burn_rate=(1.0*erros/total)/0.0001 | where burn_rate > 14.4" \
  --severity 0 \
  --evaluation-frequency 5m \
  --window-size 5m \
  --action-groups "/subscriptions/<sub-id>/resourceGroups/meu-rg/providers/Microsoft.Insights/actionGroups/payments-oncall"

```

### Passo 4: Conectar com Chaos Engineering

Com o error budget saudável, programe experimentos de caos para validar as hipóteses implícitas nos SLOs:

| SLO                  | Experimento de Caos            | Hipótese                                             |
| -------------------- | ------------------------------ | ---------------------------------------------------- |
| Pagamentos 99,99%    | Failover do Azure SQL          | O failover completa em < 30s sem perda de transações |
| Pedidos 99,9%        | Kill pods do orders-api        | HPA recria pods em < 60s, LB redistribui             |
| Catálogo P95 < 300ms | Latência de 200ms no Cosmos DB | Cache absorve o impacto, latência < 300ms            |
| Gateway 99,95%       | Shutdown de nó do AKS          | Pods são reagendados em < 2min                       |

## Conclusão

SRE não é um cargo — é uma **prática**. E os pilares de SLIs, SLOs e Error Budgets são o que transformam operações reativas em engenharia de confiabilidade proativa.

Com o Azure Monitor e Application Insights, você tem tudo o que precisa para implementar SRE sem ferramentas adicionais:

- **Application Insights** coleta os dados que alimentam seus SLIs.
- **KQL** permite calcular SLIs, SLOs e Error Budgets com precisão.
- **Azure Workbooks** visualiza o estado dos SLOs para toda a organização.
- **Scheduled Query Alerts** implementa alertas inteligentes baseados em burn rate.
- **Azure Chaos Studio** valida as hipóteses por trás dos SLOs (quando o budget permite!).

O caminho é claro:

1. **Comece com 1-2 SLOs** para o serviço mais crítico.
2. **Meça por 30 dias** antes de definir políticas.
3. **Implemente alertas de burn rate** para substituir alertas baseados em thresholds.
4. **Crie uma Error Budget Policy** e alinhe com o time.
5. **Expanda gradualmente** para outros serviços.

A confiabilidade não é um estado, é um processo contínuo de medição, aprendizado e melhoria. SLOs e Error Budgets dão a linguagem comum para que engenharia, produto e negócio tomem decisões juntos, baseados em dados, não em intuição.