DevPath · Aprenda a programar ESPTEN

Observabilidade e desempenho

Os três pilares da observabilidade

Monitoramento vs. observabilidade

Monitorar é vigiar sinais que você já sabe que importam (o servidor está vivo? quanta CPU ele usa?). Observabilidade é poder responder perguntas que não tinha antecipado a partir do que o sistema emite. A diferença prática: quando algo falha às 3 da madrugada, você tem dados suficientes para entender por quê, sem fazer deploy de código novo?

Esses dados se apoiam em três pilares: logs, métricas e traces. São complementares, não intercambiáveis.

1. Logs estruturados

Um log é um registro de um evento pontual. O erro clássico é escrever texto livre (console.log("usuário " + id + " fez login")): legível para uma pessoa, inservível para uma máquina. Um log estruturado é um objeto (que se serializa em JSON) com campos consistentes:

{ "nivel": "info", "mensagem": "login", "usuarioId": 42, "ts": "2026-06-22T10:00:00Z", "requestId": "abc-123" }

Assim você pode filtrar e agregar: "me dê todos os error do usuarioId 42 na última hora". Cada log carrega um nível que indica sua gravidade e permite silenciar o ruído em produção:

2. Métricas

Uma métrica é um número agregado no tempo, barato de armazenar (você não guarda cada evento, apenas sua contagem ou distribuição). Tipos comuns:

Sobre a latência, nunca olhe só a média: uma média de 100 ms pode esconder que 1 a cada 20 usuários espera 3 segundos. Por isso se usam percentis. O p95 é o valor abaixo do qual cai 95 % das requisições: "95 % responde em menos de 200 ms". O p99 captura a cauda, a pior experiência. Melhorar o p95/p99 costuma importar mais do que melhorar a média.

3. Traces (distributed tracing)

Num sistema com vários serviços, uma única requisição do usuário cruza muitos saltos: gateway → serviço de pedidos → banco de dados → serviço de pagamentos. Um trace segue essa requisição de ponta a ponta. Cada salto é um span com sua duração, e todos compartilham um mesmo request id (ou trace id) que se propaga nos cabeçalhos. Assim você vê onde o tempo se vai: se a requisição leva 800 ms, o trace te diz que 700 foram numa consulta lenta ao BD.

Esse mesmo requestId deve ir também nos logs: é o fio que costura os três pilares. Com ele você salta de "esta requisição foi lenta" (trace) para "e além disso registrou este erro" (log).

O que você constrói por cima

Regra prática: instrumente primeiro os golden signals — latência, tráfego, erros e saturação. Cobrem a maioria dos incidentes.

Exemplos

Um log estruturado em JSON, pronto para indexar

function log(nivel, mensagem, contexto = {}) {
  return JSON.stringify({
    nivel,
    mensagem,
    ts: new Date().toISOString(),
    ...contexto,
  });
}

console.log(log("error", "pagamento recusado", { usuarioId: 42, requestId: "abc-123" }));

p95: o percentil 95 de uma lista de latências (ms)

function percentil(valores, p) {
  const ordem = [...valores].sort((a, b) => a - b);
  const i = Math.ceil((p / 100) * ordem.length) - 1;
  return ordem[Math.max(0, i)];
}

const latencias = [80, 90, 95, 100, 110, 120, 130, 140, 150, 900];
console.log("p95:", percentil(latencias, 95), "ms"); // a cauda aparece
Coloque isto em prática

O DevPath é um curso prático: aqui você lê a teoria; no app você a coloca em prática com exercícios que rodam de verdade, offline.

Comece grátis no app →
Desempenho: cache, lazy loading e o BD →