Quando o tail -f para de funcionar

Prévia grátis 4 min de leitura

Num servidor, depurar é kamal app logs -f e ler. Funciona, é rápido, e para de funcionar num momento específico e reconhecível: quando responder o que aconteceu com aquela requisição exige saber qual de seis máquinas a atendeu.

Esse momento chega com as estratégias de deploy dos últimos cursos. Com três réplicas, um worker, um canário e uma versão estável, a sessão de uma pessoa agora está espalhada por processos que guardam, cada um, um fragmento dela.

flowchart TB
  U["A requisição de uma pessoa"] --> P["kamal-proxy / ingress"]
  P --> W1["pod web 1 — parte da história"]
  W1 --> J["job enfileirado"]
  J --> WK["pod worker — outra parte"]
  WK --> M["e-mail enviado — uma terceira"]
  W1 -.-> Q["Qual log tem o erro?"]
  WK -.-> Q
  M -.-> Q

Agregação de logs é a resposta a essa pergunta: todo processo envia os logs para um lugar só, onde você busca em todos ao mesmo tempo.

Três problemas que ela resolve

Logs somem. O sistema de arquivos de um container morre com o container. Um pod que caiu às 2 da manhã e foi substituído levou os logs junto, e o kubectl logs no pod que o substituiu mostra uma inicialização saudável. Enviar os logs para fora da máquina conforme são escritos é o único jeito de tê-los depois.

Você não consegue buscar entre máquinas. Ninguém faz grep em seis hosts à mão direito sob pressão. Um índice sobre todos eles é outra atividade.

Você não consegue correlacionar. A requisição web, o job que ela enfileirou e o e-mail que ela mandou são três fluxos de log. Amarrá-los exige um identificador compartilhado, que é a aula 3.

O que esta aplicação já faz

Leia o config/environments/production.rb deste repositório:

# Log to STDOUT with the current request id as a default log tag.
config.log_tags = [ :request_id ]
config.logger   = ActiveSupport::TaggedLogging.logger(STDOUT)

# Change to "debug" to log everything (including potentially personally-identifiable information!)
config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info")

# Prevent health checks from clogging up the logs.
config.silence_healthcheck_path = "/up"

São quatro decisões, todas certas, e o resto do curso se apoia em cada uma.

STDOUT em vez de arquivo. Um processo em container deve escrever na saída padrão e deixar a plataforma capturar. Escrever num arquivo dentro do container gera um arquivo que ninguém coleta, num disco que desaparece, que nenhuma política de rotação gerencia. Esta é a linha mais importante do bloco.

log_tags = [ :request_id ] prefixa toda linha de uma requisição com um identificador compartilhado por todas elas. Esse fio permite remontar uma história espalhada por várias linhas, e a aula 3 o estende.

log_level vindo do ambiente. Aumentar a verbosidade em produção vira mudança de configuração em vez de deploy. Isso importa às 3 da manhã, e de novo na conta, porque debug em produção é caro em volume e perigoso em conteúdo.

silence_healthcheck_path descarta as requisições a /up. Uma probe a cada cinco segundos em três pods são cinquenta mil linhas por dia que não dizem nada. Ruído custa armazenamento, dinheiro e atenção.

O que ela não faz

Os logs não são estruturados: são linhas legíveis por pessoas, feitas para um terminal.

[a1b2c3d4] Started GET "/catalog/courses/rails-basics" for 203.0.113.5 at 2026-09-06 10:14:22
[a1b2c3d4] Processing by Catalog::CoursesController#show as HTML
[a1b2c3d4] Completed 200 OK in 47ms (Views: 31.2ms | ActiveRecord: 8.1ms)

São três linhas para uma requisição, num formato que uma máquina precisa adivinhar com uma expressão regular. Pergunte quais requisições levaram mais de um segundo ontem e você teria que extrair essa duração de uma frase. A aula 2 conserta isso.

Nada os envia para lugar nenhum, também. Agora eles vão para a saída padrão e, no Kamal, para os arquivos de log do Docker no host, onde dependem da rotação e de o host continuar existindo. Isso é a aula 4.

O que este curso cobre

  1. Quando o tail -f para de funcionar (você está aqui).
  2. Logs estruturados: de prosa para dado.
  3. Correlação: seguindo uma requisição entre processos.
  4. Envio: tirando os logs da máquina.
  5. Guardando e buscando sem uma conta alta.
  6. O que registrar, e o que nunca registrar.
  7. Juntando tudo: uma configuração de logs para este app.

Pontos-chave

  • Agregação importa quando os logs sobrevivem às máquinas, se espalham por várias delas ou precisam ser correlacionados entre processos.
  • Este repositório já escreve em STDOUT com tag de request id, nível vindo do ambiente e health checks silenciados, e os quatro estão certos.
  • Escrever num arquivo dentro do container é o erro comum; a plataforma deve capturar a saída padrão.
  • As lacunas são que as linhas são prosa em vez de dado, e que nada as envia para algum lugar durável.
Aula 1 de 7 · grátis

Continue com a aula 2

Logs estruturados: de prosa para dado

Como trocar linhas em prosa por eventos JSON com lograge, nomes de evento estáveis, campos nomeados e níveis consistentes.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...