Imagine o painel de controle de um carro. Os contadores (velocidade, rotação do motor, nível de combustível) dão um valor numérico a cada instante: são as métricas. A caixa-preta, o gravador de eventos de um carro moderno, anota o que aconteceu, linha por linha, com a hora exata: são os logs (os registros). Os avisos luminosos (óleo, bateria, motor) se acendem sozinhos quando um valor monitorado sai da faixa normal, sem que você precise ficar olhando cada contador o tempo todo: são os alertas. O GPS, que retraça o trajeto completo que você seguiu com o tempo passado em cada trecho, é um traço. Essa imagem volta ao longo de todo o módulo: cada serviço do labo desempenha o papel de uma dessas quatro peças.
| Peça do painel | O que ela representa | Serviço do labo que desempenha esse papel |
|---|---|---|
| Contadores | Métricas | Prometheus (que lê node-exporter, cadvisor e a API) |
| Caixa-preta | Logs | Loki, alimentado pelo Alloy |
| Avisos luminosos | Alertas | Alertmanager, que avisa o webhook |
| GPS que retraça o trajeto | Traços | Nenhum neste labo (mencionado no módulo 7) |
| O para-brisa | O que você observa | Grafana |
Não se observa um sistema por prazer. Observa-se porque um dia algo quebra, e é preciso entender o quê, onde e desde quando, antes que isso custe caro. Os três incidentes abaixo são públicos: cada empresa escreveu e publicou seu próprio post-mortem. Eles mostram o que a observabilidade permite, e o que ela nem sempre permite de primeira.
Cloudflare, 18 de novembro de 2025: quando as métricas não bastam por si só. Às 11h20 UTC, a rede da Cloudflare deixa de rotear corretamente boa parte do tráfego mundial: os visitantes dos sites de seus clientes recebem uma página de erro. A causa: uma mudança de permissões em um cluster de banco de dados ClickHouse faz dobrar o tamanho de um arquivo de configuração interno (o arquivo de "características" do sistema antibot), que ultrapassa um limite fixado no código e derruba o proxy central. As métricas de erros HTTP 5xx são visíveis já no primeiro minuto, em um pico bem nítido no gráfico. Mas o arquivo só era gerado de forma defeituosa de forma intermitente, em apenas parte do cluster: o tráfego se restabelecia e voltava a cair a cada cinco minutos. Essa oscilação inicialmente fez a equipe acreditar que se tratava de um ataque de negação de serviço, não de uma falha interna. Foi preciso cruzar as métricas com os logs do módulo antibot para identificar a causa real. O tráfego principal é restabelecido às 14h30, todos os sistemas voltam ao normal às 17h06: quase 5 horas e 46 minutos entre o início e o fim completo do incidente. Fonte oficial: Cloudflare outage on November 18, 2025.
AWS S3, 28 de fevereiro de 2017: quando a própria ferramenta de supervisão depende do sistema que ela monitora. Às 9h37 (horário do Pacífico), um engenheiro da Amazon S3 executa um comando de manutenção que deveria remover alguns servidores de um subsistema de faturamento, na região Virgínia do Norte (us-east-1). Um erro de digitação remove um número de servidores muito maior do que o previsto e derruba dois subsistemas críticos do S3: o índice (os metadados e a localização dos objetos) e o placement (a alocação de novo armazenamento). O S3 fica incapaz de processar requisições GET, LIST, PUT e DELETE, e junto com ele caem os novos lançamentos de instâncias EC2, o EBS, o Lambda, e o próprio painel oficial de status da AWS, que dependia do S3 para se atualizar. A AWS teve que comunicar o estado da falha no seu perfil do Twitter. O índice é totalmente restabelecido às 13h18, o placement às 13h54: cerca de 4 horas e 17 minutos entre o início do incidente e a volta ao normal. Fonte oficial: Summary of the Amazon S3 Service Disruption in the Northern Virginia (US-EAST-1) Region.
GitHub, 14 de agosto de 2024: quando a própria supervisão dispara a falha. Às 22h59 UTC, o GitHub implanta uma mudança de configuração em seus bancos de dados. Essa mudança quebra a capacidade desses bancos de responder corretamente aos testes de saúde (health checks) enviados pela camada de roteamento. Não recebendo mais uma resposta válida, a camada de roteamento declara esses bancos "com problemas de saúde" e remove o acesso de leitura: o GitHub.com fica inacessível para todos os usuários das 23h02 às 23h38 UTC, ou seja, 36 minutos. A equipe corrige revertendo a mudança de configuração, depois confirma por meio de monitoramento contínuo que a conectividade foi restabelecida antes de encerrar o incidente à 00h30 do dia seguinte. O ponto a reter: não foi a ausência de supervisão que causou a falha, foi um dos próprios mecanismos de supervisão, o teste de saúde, que, mal configurado, a disparou. Fonte oficial: GitHub Availability Report: August 2024.
Os três incidentes convergem em um ponto: nos três casos, a empresa sabia muito rápido que algo não estava certo (as métricas de erro se movem em poucos segundos). O que leva tempo é saber por quê. É exatamente isso que o labo deste curso faz você construir, em pequena escala, na sua máquina.
O monitoramento monitora indicadores escolhidos com antecedência, com limites já conhecidos: "a taxa de erros passa de 5%". É eficaz para uma falha que já se viu acontecer antes. A observabilidade é a capacidade de entender o estado interno de um sistema a partir dos sinais que ele já produz (suas métricas, seus logs, seus traços), incluindo para uma pergunta que não havia sido prevista, sem precisar reimplantar código para ir buscá-la. O monitoramento diz "algo não está indo bem"; a observabilidade ajuda a responder "por quê, onde e desde quando".
| Termo | Definição em uma frase | Onde aparece no labo |
|---|---|---|
| Monitoramento | Monitorar indicadores conhecidos com antecedência e alertar quando um limite é ultrapassado. | As dez regras de prometheus/regles/alertes.yml (módulo 6) |
| Observabilidade | Entender o estado interno de um sistema a partir de suas métricas, logs e traços, mesmo para uma pergunta imprevista. | O conjunto Prometheus, Loki e Grafana do labo |
| Métrica | Um valor numérico medido em intervalos regulares, que forma uma série no tempo. | http_requetes_total, exposta pela API em /metrics |
| Log | Uma mensagem com data e hora que um programa escreve em um momento preciso para descrever um evento. | Uma linha JSON escrita pela API na sua saída padrão, lida por journal api |
| Traço | O trajeto completo de uma requisição por vários serviços, com a duração de cada etapa. | Mencionado neste curso, sem ferramenta neste labo (módulo 7) |
| Alerta | Uma notificação automática enviada quando uma condição medida permanece verdadeira por um período determinado. | APIInjoignable, roteado pelo Alertmanager para o webhook |
| SLI (Service Level Indicator) | Uma medida quantitativa do nível de serviço realmente observado. | A taxa de respostas 5xx da API em 5 minutos (api:taux_erreurs_5m) |
| SLO (Service Level Objective) | O objetivo interno fixado sobre um SLI, em um determinado período. | "Menos de 5% de erros": o limite do alerta TauxErreursEleve |
| SLA (Service Level Agreement) | O compromisso contratual com um cliente, com penalidade em caso de descumprimento. | Fora do labo: uma cláusula em um contrato de cliente |
Referência para as definições de SLI, SLO e SLA: Google SRE Book — Service Level Objectives. Para a observabilidade vista pelas ferramentas do curso: Prometheus — Overview e Grafana — Observability.
A diferença essencial entre monitoramento e observabilidade: o monitoramento responde a perguntas escritas com antecedência ("a taxa de erros passa de 5%?"). A observabilidade permite fazer uma pergunta que não havia sido prevista ("quais requisições demoraram mais de 500 ms entre 19h33 e 19h34?") e obter a resposta a partir do que o sistema já registrou.
Antes do Prometheus e do Grafana, a equipe de plataforma se conectava via SSH ao servidor e digitava grep ERROR /var/log/api.log. Isso funciona, para uma única máquina, um único arquivo, um único momento. Mas:
grep só vê o que é escrito naquele servidor, naquele arquivo. Com vários contêineres da API rodando em paralelo, é preciso se conectar a cada um e cruzar manualmente.grep não mantém histórico além do arquivo atual: quando o arquivo é rotacionado (log rotation) ou o contêiner reinicia, o que não foi lido se perde.grep não calcula tendência: ele mostra linhas, não uma curva de "porcentagem de erros nos últimos cinco minutos".SELECT count(*) FROM inscriptions) diz quantas inscrições existem agora. Ela não diz nada sobre a latência das requisições HTTP, sobre a taxa de erro, nem sobre o estado dos contêineres: essas informações não estão nesse banco.grep, nem a query SQL, avisam alguém automaticamente. É preciso lembrar de executá-los, de novo e de novo, ou esperar que um usuário reclame.A observabilidade responde a essas lacunas: ela centraliza as métricas e os logs de todas as instâncias, mantém um histórico consultável, calcula tendências, e avisa automaticamente, sem esperar que alguém faça a pergunta.
Você entra na equipe que mantém a plataforma de cursos online usada nos outros cursos do catálogo. O núcleo do sistema é uma API, a API de catálogo, escrita em Python com FastAPI, que expõe 64 cursos (C0001 a C0064) nas rotas /cours, /cours/{id}, /inscriptions, /lent, /sante e /metrics. Um segundo programa, o gerador de carga (o serviço charge), chama essa API continuamente, como fariam centenas de estudantes navegando pelo catálogo, se inscrevendo em um curso, ou caindo em uma página que não existe mais.
Sua chefe de equipe faz uma pergunta simples, mas que nenhum grep nem nenhuma query SQL respondem de uma vez: "Está funcionando? Para quem? Desde quando? E por que quebra?" Ela não quer se conectar ao servidor. Ela quer um painel de controle que ela mesma possa abrir, e um alerta que a avise antes que um estudante escreva reclamando.
Esse é o fio condutor do curso. Cada módulo adiciona uma peça: as métricas e o PromQL (módulo 2), a instrumentação da própria API (módulo 3), os painéis de controle Grafana (módulo 4), os logs com Loki (módulo 5), os alertas que avisam antes da reclamação (módulo 6). O módulo 7 reúne tudo. E a cada etapa, o labo permite que você quebre propositalmente uma parte da plataforma (.\labo.ps1 casser api, casser erreurs, casser lenteur, casser disque) para que você aprenda a ler a falha nas ferramentas antes de repará-la.
| Serviço (nome do contêiner) | Papel | Porta na sua máquina |
|---|---|---|
api (labo-api) | O serviço observado: /cours, /inscriptions, /sante, e suas próprias métricas em /metrics | 8000 |
charge (labo-charge) | Simula estudantes usando a plataforma, para que haja algo a observar | nenhuma |
prometheus (labo-prometheus) | Busca (scrape) as métricas de cada serviço a cada 15 s, as armazena como séries no tempo, avalia as regras de alerta | 9090 |
alertmanager (labo-alertmanager) | Recebe os alertas disparados pelo Prometheus, os agrupa, os roteia para um receptor | 9093 |
webhook (labo-webhook) | Recebe os alertas do Alertmanager e os exibe: o que um sistema de sobreaviso receberia | 8090 |
alloy (labo-alloy) | Descobre os contêineres Docker e transporta seus logs para o Loki | 12345 |
loki (labo-loki) | Armazena os logs e os indexa por rótulos (labels), não pelo seu texto completo | 3100 |
node-exporter (labo-node-exporter) | Expõe as métricas da máquina hospedeira (CPU, memória, disco) no formato Prometheus | 9100 |
cadvisor (labo-cadvisor) | Expõe as métricas de cada contêiner (CPU, memória, rede) no formato Prometheus | 8080 |
grafana (labo-grafana) | Interface única para explorar e visualizar Prometheus, Loki e Alertmanager | 3000 (GRAFANA_PORT) |
Você ainda não instalou o labo: isso é trabalho das lições 03 e 04. Este passo a passo faz você ler quatro saídas reais, capturadas na máquina do curso, para que você reconheça uma métrica, um log e um alerta quando você mesmo os produzir. Mantenha esta página aberta durante a lição 04: você vai reencontrar cada uma dessas quatro saídas na tela.
Uma métrica, como o Prometheus a lê. A cada 15 segundos, o Prometheus chama http://api:8000/metrics. Aqui estão quatro linhas dessa página, na máquina do curso:
# HELP http_requetes_total Nombre de requêtes HTTP reçues, par méthode, route normalisée et code de réponse.
# TYPE http_requetes_total counter
http_requetes_total{code="200",methode="GET",route="/cours"} 3247.0
http_requetes_total{code="500",methode="GET",route="/cours"} 32.0O que é preciso ver: uma métrica tem um nome (http_requetes_total), labels entre chaves (code, methode, route) e um valor (3247.0). As duas linhas têm o mesmo nome, mas labels diferentes: são duas séries distintas. A linha # TYPE … counter diz que esse número só aumenta. A lição 02 detalha os quatro tipos.
Um log, como a API o escreve. A API escreve uma linha JSON por requisição na sua saída padrão. .\labo.ps1 journal api as exibe; aqui estão duas, na máquina do curso:
labo-api | {"horodatage": "2026-09-15T19:33:25.839+00:00", "niveau": "INFO", "id_requete": "46bb533b33e9", "methode": "GET", "route": "/cours/{id}", "code": 200, "duree_ms": 13.9, "message": "GET /cours/C0038 -> 200"}
labo-api | {"horodatage": "2026-09-15T19:33:14.781+00:00", "niveau": "ERROR", "id_requete": "dc1c2ff189a6", "methode": "GET", "route": "/cours/{id}", "code": 500, "duree_ms": 0.1, "message": "GET /cours/C0019 -> 500"}O que é preciso ver: um log é um evento preciso (essa requisição específica, nesse instante específico, para o curso C0038), enquanto a métrica da etapa 1 é um acumulado (3247 requisições /cours bem-sucedidas desde a inicialização). O campo id_requete identifica uma requisição única; o mesmo valor é devolvido ao cliente no cabeçalho HTTP x-id-requete. A segunda linha é um erro 500: o labo produz propositalmente 1% desses em funcionamento normal.
Um alerta, como a equipe de sobreaviso o recebe. Quando a API é parada (casser api), o Prometheus não consegue mais ler /metrics, a regra APIInjoignable passa para firing depois de 30 segundos, o Alertmanager a transmite para o webhook. Aqui está o que http://localhost:8090/alertes.json contém nesse momento, na máquina do curso:
{"recu_a":"2026-09-15T19:41:26+00:00","etat":"firing","nom":"APIInjoignable","severite":"critique","service":"api","resume":"L'API catalogue ne répond plus","description":"Prometheus n'arrive plus à lire http://api:8000/metrics depuis 30 secondes (cible api:8000).","debut":"2026-09-15T19:41:11.496Z","fin":"0001-01-01T00:00:00Z"}O que é preciso ver: o alerta tem um nome, uma severidade, um resumo legível por um humano, e um estado firing (está soando). O campo fin vale uma data nula enquanto o alerta está em curso; depois de reparer, uma segunda notificação chega com "etat":"resolved" e uma data de fim real. Ninguém precisou atualizar uma página: o aviso luminoso se acendeu por conta própria.
A visão geral, em um único comando. .\labo.ps1 etat resume o estado dos dez serviços e da supervisão. Na máquina do curso, em funcionamento normal:
== Supervision ==
✔ Prometheus répond — cibles up : 8/8
séries en mémoire : 12350
alertes : 0 active(s), 0 en attente (pending)
✔ Alertmanager répond (http://localhost:9093)
✔ Grafana répond (http://localhost:3000)
✔ Loki répond (http://localhost:3100)
✔ API catalogue répond — version 1.0.0, 64 cours
✔ Webhook répond — 0 alerte(s) reçue(s) (http://localhost:8090)
Labo : 10/10 services, 8/8 cibles up, 0 alertes actives.O que é preciso ver: 8/8 cibles up (o Prometheus lê oito páginas /metrics: os dez serviços menos charge e webhook, que não expõem nenhuma), 12350 séries em memória (esse número varia de uma máquina para outra), 0 alertes actives. É a linha que você deve reencontrar ao final de cada prática do curso.
A regra que liga a métrica ao alerta. O alerta da etapa 3 não veio do nada: está escrito em um arquivo do kit, prometheus/regles/alertes.yml, cujas regras o Prometheus avalia a cada 15 segundos (evaluation_interval: 15s em prometheus/prometheus.yml). Aqui está a primeira das dez regras, como está no kit:
groups:
- name: api-catalogue
rules:
- alert: APIInjoignable
expr: up{job="api"} == 0
for: 30s
labels:
severite: critique
service: api
annotations:
resume: "L'API catalogue ne répond plus"
description: "Prometheus n'arrive plus à lire http://api:8000/metrics depuis 30 secondes (cible {{ $labels.instance }})."O que é preciso ver: expr é uma métrica (up, a que o Prometheus mesmo fabrica em cada leitura: 1 se o target respondeu, 0 caso contrário) comparada a um valor; for: 30s é a duração durante a qual a condição precisa permanecer verdadeira antes de o alerta soar; resume e description são exatamente o texto que o webhook exibiu na etapa 3, com {{ $labels.instance }} substituído por api:8000. Um alerta é uma métrica, um limite e uma duração: nada mais. O módulo 6 vai fazer você escrever os seus próprios.
Esta lição não faz você instalar nada, mas três confusões surgem já na lição 04. As mensagens abaixo foram provocadas de verdade na máquina do curso.
"A API está fora do ar, ela responde 404": não. Um 404 é uma resposta saudável de um serviço que está rodando e que diz "esse recurso não existe". No labo, http://localhost:8000/cours/C9999 responde:
HTTP 404 {"detail":"cours C9999 introuvable"}Uma API realmente parada não responde nada. Durante casser api, curl http://localhost:8000/sante retorna:
curl: (7) Failed to connect to localhost:8000 after 2237 ms: Could not connect to serverE Invoke-RestMethod http://localhost:8000/sante no PowerShell: Le délai de l'opération a expiré. Um 404 é um log de nível WARNING e uma métrica code="404"; uma API parada é up{job="api"} valendo 0.
"Não há nenhum alerta, a supervisão não está funcionando": no Prometheus, a métrica ALERTS retorna um resultado vazio quando tudo está bem. Na máquina do curso, em funcionamento normal, a API de consulta responde:
{"status":"success","data":{"resultType":"vector","result":[]}}"status":"success" com "result":[]: a query está correta, simplesmente não há nada para mostrar. É a situação normal, não uma falha. ALERTS só contém uma série para um alerta pending ou firing.
"Uma métrica e um log são a mesma informação": não. A métrica http_requetes_total{code="500",methode="GET",route="/cours/{id}"} 27.0 diz que houve 27 erros nessa rota desde a inicialização, sem dizer quais. O log "GET /cours/C0019 -> 500" com "id_requete": "dc1c2ff189a6" diz precisamente qual. A métrica é barata e se conta; o log é detalhado e se lê. O módulo 5 os liga pelo campo id_requete.
O monitoramento monitora limites conhecidos com antecedência; a observabilidade permite entender uma falha que não havia sido prevista, a partir das métricas, dos logs e dos traços que um sistema já produz. Uma métrica é um número medido no tempo, com um nome, labels e um valor (http_requetes_total{code="200",methode="GET",route="/cours"} 3247.0). Um log é um evento com data e hora, uma linha JSON por requisição no labo, com um id_requete único. Um alerta avisa automaticamente quando uma condição permanece verdadeira por tempo suficiente (APIInjoignable após 30 segundos de API inacessível) e chega ao webhook com um estado firing e depois resolved. O painel de controle de um carro resume tudo: contadores = métricas, caixa-preta = logs, avisos luminosos = alertas, GPS = traços, para-brisa = Grafana. Nem um grep em um único servidor nem uma query SQL no banco de negócio centralizam o histórico, calculam uma tendência, ou avisam automaticamente. Um 404 é a resposta saudável de um serviço em funcionamento; uma API parada não responde nada e up vale 0. O fio condutor do curso é a plataforma de cursos online, sua API de catálogo com 64 cursos, seu gerador de carga e seus dez serviços.
casser e reparer./metrics do labo: os quatro tipos de métricas, os labels, a cardinalidade, o pull, e a estrutura exata de uma linha de log JSON.