Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Pino no Node.js

Atualizado em: 4 de outubro de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

Pino é uma biblioteca de logs estruturados para Node.js. Em vez de montar linhas de texto manualmente, a aplicação grava objetos JSON com nível, horário, mensagem e contexto. Esse formato facilita busca, alertas, correlação e processamento por plataformas de observabilidade.

Logs não substituem métricas e traces. Eles registram eventos discretos que ajudam a explicar falhas, decisões e mudanças de estado. Uma estratégia boa produz contexto suficiente sem expor segredos ou gerar volume impossível de armazenar.

Instalação

npm install pino

Primeiro logger

import pino from 'pino';

const logger = pino({
  level: process.env.LOG_LEVEL || 'info',
});

logger.info({ port: 3000 }, 'Servidor iniciado');

A saída contém campos estruturados. Em produção, envie JSON para stdout e deixe o coletor transportar e indexar.

Níveis

  • trace: detalhe muito fino;
  • debug: diagnóstico de desenvolvimento;
  • info: eventos operacionais normais;
  • warn: condição inesperada recuperável;
  • error: operação falhou;
  • fatal: processo não consegue continuar.

Não registre toda requisição como error. Isso gera alertas e custos desnecessários.

Child logger

Um child adiciona contexto comum:

const requestLogger = logger.child({
  requestId,
  method: req.method,
  route: req.route?.path,
});

requestLogger.info('Requisição recebida');

Use rota normalizada, não URL completa com IDs e query sensível.

AsyncLocalStorage

Contexto assíncrono evita passar logger manualmente por todas as funções:

import { AsyncLocalStorage } from 'node:async_hooks';

const context = new AsyncLocalStorage();

app.use((req, res, next) => {
  const requestId = req.get('x-request-id') || crypto.randomUUID();
  const child = logger.child({ requestId });
  context.run({ logger: child }, next);
});

function currentLogger() {
  return context.getStore()?.logger || logger;
}

Erros

try {
  await processOrder(order);
} catch (error) {
  logger.error({ err: error, orderId: order.id }, 'Falha ao processar pedido');
  throw error;
}

Pino possui serialização apropriada para Error quando o campo segue a convenção esperada. Não use apenas JSON.stringify(error), pois propriedades importantes não são enumeráveis.

Causes

Erros modernos podem possuir cause. Garanta que o serializador e a plataforma preservem a cadeia sem repetir dados sensíveis.

Redaction

Remova campos sensíveis antes da saída:

const logger = pino({
  redact: {
    paths: [
      'req.headers.authorization',
      'req.headers.cookie',
      'password',
      '*.token',
    ],
    censor: '[REDACTED]',
  },
});

Redaction é uma defesa adicional. O ideal é não passar secrets ao logger.

Não registre corpos completos

Request e response body podem conter senha, cartão, documento, saúde ou conteúdo grande. Registre somente campos permitidos e agregados.

Serializers

const logger = pino({
  serializers: {
    req(req) {
      return {
        method: req.method,
        url: req.url?.split('?')[0],
        remoteAddress: req.socket?.remoteAddress,
      };
    },
  },
});

Revise IPs conforme a política de privacidade e proxy confiável.

Pretty print

Em desenvolvimento, uma ferramenta como pino-pretty torna a saída legível. Não use formatação pesada no caminho principal de produção.

node server.js | pino-pretty

Transport

Transports processam a saída fora do fluxo principal conforme a arquitetura da biblioteca. Mesmo assim, stdout com agente externo costuma ser simples e robusto em containers.

stdout

Escreva logs na saída padrão. Kubernetes, Docker e systemd coletam o stream. Evite gerenciar arquivos e rotação dentro de cada processo, salvo necessidade específica.

Backpressure

Logs podem se tornar gargalo quando o destino está lento. Não gere megabytes por requisição. Meça throughput, use níveis e amostragem.

Extreme mode

Modos de buffering podem melhorar desempenho, mas aumentam risco de perda em crash. Avalie a durabilidade necessária e o contrato da versão utilizada.

Flush

Antes de encerramento normal, permita flush do destino. Em crash, operações assíncronas podem não concluir. Para eventos fatais, mantenha o handler mínimo e encerre.

Logs de requisição

Campos úteis:

  • requestId;
  • traceId;
  • método;
  • rota normalizada;
  • status;
  • duração;
  • bytes;
  • tenant técnico;
  • resultado.

Não use query inteira, Authorization ou payload.

Middleware de duração

app.use((req, res, next) => {
  const start = performance.now();

  res.once('finish', () => {
    currentLogger().info({
      statusCode: res.statusCode,
      durationMs: performance.now() - start,
    }, 'Requisição concluída');
  });

  next();
});

Trate também close para conexões interrompidas sem duplicar o evento.

Trace ID

Quando OpenTelemetry está ativo, inclua trace ID e span ID:

const span = trace.getActiveSpan();
const spanContext = span?.spanContext();

logger.info({
  traceId: spanContext?.traceId,
  spanId: spanContext?.spanId,
}, 'Operação');

Request ID externo

Valide tamanho e caracteres de X-Request-ID. Ou gere um ID interno e registre o externo separadamente.

Mensagens estáveis

Use mensagem humana curta e campos para detalhes:

logger.info({ userId, plan }, 'Plano alterado');

Evite interpolar tudo na mensagem, pois dificulta agregação.

Eventos de auditoria

Auditoria possui requisitos diferentes de logs operacionais. Pode exigir imutabilidade, retenção, acesso restrito e campos obrigatórios. Não misture sem política.

PII

Classifique dados pessoais. Use IDs internos, mascaramento e retenção curta. Email e IP podem ser dados pessoais conforme contexto.

Cardinalidade

Plataformas de logs aceitam mais cardinalidade que métricas, mas valores únicos ainda aumentam custo. Indexe apenas campos usados em busca.

Amostragem

Para eventos muito frequentes:

if (Math.random() < 0.01) {
  logger.debug({ operation }, 'Amostra de operação');
}

Erros raros e auditoria podem exigir retenção completa. Use amostragem determinística por trace para manter coerência.

Rate limit de logs

Uma dependência falhando pode gerar milhões de mensagens iguais. Agregue contagens ou limite por chave e janela.

Erro e retry

Não registre cada tentativa como error e depois o erro final novamente. Use debug ou warn nas tentativas e error na falha final, conforme impacto.

Health checks

Probes frequentes podem poluir logs. Exclua ou amostre acessos bem-sucedidos, mantendo falhas.

Workers e cluster

Inclua PID, threadId ou worker ID. A ordem entre processos não é garantida; use timestamp e requestId.

Timestamp

Use horário UTC e relógio sincronizado. A plataforma pode adicionar timestamp de ingestão, mas preserve o de emissão.

Configuração dinâmica

Alterar LOG_LEVEL pode ajudar em incidentes. Implemente de forma autenticada, auditada e temporária. Debug permanente aumenta custo e exposição.

Testes

Capture a saída e confirme campos, redaction, nível e serialização de erro. Não faça testes dependentes da ordem de propriedades JSON.

Desempenho

Benchmark com volume real. O custo não está só na biblioteca: serializar objetos grandes e enviar à rede domina. Compare logs ativados e desativados.

Observabilidade do logging

Meça:

  • bytes por segundo;
  • eventos por nível;
  • falhas de transporte;
  • fila ou buffer;
  • logs descartados;
  • latência de ingestão;
  • custo de armazenamento.

Graceful shutdown

Pare de aceitar tráfego, finalize tarefas e permita flush. Não aguarde indefinidamente por um coletor indisponível.

Erros comuns

  • registrar senha ou token;
  • logar body completo;
  • usar pretty em produção;
  • interpolar todos os campos;
  • não correlacionar request e trace;
  • registrar retry repetido como error;
  • indexar tudo;
  • não limitar volume;
  • não testar redaction;
  • confiar no log como auditoria completa.

Fluxo recomendado

Produza JSON em stdout, use child loggers, AsyncLocalStorage, redaction e mensagens estáveis. Correlacione com traces e controle volume. Combine com AsyncLocalStorage, OpenTelemetry, Graceful Shutdown e Diagnostics Channel.

Consulte a documentação oficial do Pino e o repositório oficial.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita