Quando o tail -f para de funcionar
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
- Quando o
tail -fpara de funcionar (você está aqui). - Logs estruturados: de prosa para dado.
- Correlação: seguindo uma requisição entre processos.
- Envio: tirando os logs da máquina.
- Guardando e buscando sem uma conta alta.
- O que registrar, e o que nunca registrar.
- 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.
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.