
Reduzindo volume de logs do Fastify com LogController
O problema e a solução rápida
O texto parte de um caso comum: um orquestrador chama /health a cada cinco segundos, totalizando 17.280 requisições por dia. Como o Fastify registra duas linhas para cada requisição, isso pode gerar mais de 1 milhão de linhas por mês, todas indicando que o serviço está funcionando. Esses registros são armazenados, indexados e cobrados, mas nem sempre acrescentam informação útil.
A solução mais simples usa o contexto encapsulado criado por cada chamada a register. Ao registrar as rotas de saúde em um plugin com { logLevel: 'silent' }, o logger-filho daquele contexto descarta os registros automáticos. As demais rotas continuam no nível padrão, como info. Essa abordagem requer apenas duas linhas, mas é total: também elimina os logs emitidos pelo próprio manipulador da rota e não permite manter, por exemplo, apenas os erros.
Controle centralizado com LogController
Para decisões mais granulares, o Fastify passou a oferecer a opção logController, disponível desde a versão 5.10.0. A classe LogController, exportada pelo próprio Fastify, funciona como uma camada entre os eventos que o framework registra e a forma como a aplicação quer registrá-los. Cada tipo de registro automático corresponde a um método, incluindo início e conclusão de requisições, erros tratados pelo manipulador padrão, rotas inexistentes, falhas de fluxo ou serialização e a resposta 503 durante o desligamento.
A aplicação pode criar uma subclasse, substituir apenas os métodos necessários e deixar os demais com o comportamento padrão. As opções de nível e rótulo de identificação da requisição, antes configuradas como opções de nível superior, devem ser passadas ao controlador e estão depreciadas nessa forma; elas serão removidas no Fastify 6.
Um exemplo usa request.routeOptions.config para definir um nível por rota. As rotas de saúde podem emitir seus logs automáticos em debug, sendo descartadas por um logger configurado em info, enquanto as demais continuam registrando em info. Diferentemente de silenciar o plugin, isso preserva os logs próprios do manipulador e mantém os erros no nível error. O texto ressalta que, ao substituir um método, a verificação de isLogDisabled(request) deixa de ser aplicada automaticamente e precisa ser chamada pela implementação.
Reformatar e amostrar registros
O controlador também pode eliminar a linha de entrada e transformar a conclusão em um único registro de acesso. Esse registro pode reunir método, URL, padrão da rota, status, tempo arredondado, identificador de locatário e eventual erro. Usar o padrão da rota, como /orders/:id, ajuda a agrupar requisições semelhantes e evitar cardinalidade excessiva nos painéis.
Outra possibilidade é manter estado na instância do controlador e registrar apenas uma requisição bem-sucedida a cada intervalo definido, sem descartar nenhuma falha. No exemplo, sete sucessos e um erro com taxa de amostragem cinco produzem uma linha de acesso para os sucessos e uma linha imediata para o erro. O registro adicional com pilha é gerado por defaultErrorLog, que não foi substituído; para padronizar também esse evento, esse método precisa ser sobrescrito.
Limitações e conclusão
logController é uma única instância por servidor, não um controlador encapsulado por plugin. Portanto, comportamentos por rota precisam ser derivados da requisição, embora o controlador e plugins silenciados possam ser usados juntos. Como seus métodos ficam no caminho crítico de todas as requisições, devem executar operações simples, sem await nem conversões desnecessárias. A recomendação central é verificar primeiro se uma subclasse curta do controlador resolve a necessidade antes de propor uma nova opção no núcleo do Fastify.