Introdução ao registro em aplicações TypeScript
\n\nRegistro (logging) é o processo de gravar eventos que ocorrem durante a execução de um programa. Para aplicações TypeScript, especialmente aquelas que rodam no ambiente Node.js, um registro bem configurado não é apenas uma boa prática, mas uma ferramenta criticamente importante para depuração, monitoramento e análise de erros.
\n\nMuitos desenvolvedores iniciantes se limitam a usar console.log(). No entanto, em um ambiente de produção, essa abordagem é ineficaz: ela não permite gerenciar flexivelmente os níveis de importância, filtrar mensagens ou salvá-las em arquivos. Neste artigo, vamos explorar como criar um sistema de registro profissional em TypeScript do zero.
Por que não usar console.log em produção?
\n\nVejamos um exemplo típico:
\n\n// Abordagem ruim — usando console.log diretamente\nfunction processOrder(orderId: string): void {\n console.log(`Processing order ${orderId}`);\n try {\n // lógica de negócio\n } catch (error) {\n console.error(`Error processing order: ${error}`);\n }\n}\n\n\nProblemas dessa abordagem:
\n- \n
- Falta de níveis de registro: não é possível separar mensagens de debug de erros críticos. \n
- Sem formatação: difícil ler grandes volumes de dados. \n
- Não é redirecionável: todas as mensagens vão apenas para stdout/stderr. \n
- Problemas de desempenho: a gravação síncrona no console pode desacelerar a aplicação. \n
Melhores práticas de registro em TypeScript
\n\n1. Escolha da biblioteca de registro
\n\nPara TypeScript, recomenda-se usar uma das duas bibliotecas populares:
\n- \n
- Winston — um logger poderoso e flexível com suporte a transportes (arquivo, console, bancos de dados). \n
- Pino — um logger ultrarrápido, ideal para aplicações de alta carga. \n
Vamos instalar o Winston:
\nnpm install winston\nnpm install @types/winston --save-dev\n\n\n2. Criando um logger configurável
\n\nCrie o módulo logger.ts:
import winston from 'winston';\n\nconst logger = winston.createLogger({\n level: process.env.LOG_LEVEL || 'info',\n format: winston.format.combine(\n winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),\n winston.format.errors({ stack: true }),\n winston.format.json()\n ),\n transports: [\n new winston.transports.Console({\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.simple()\n )\n }),\n new winston.transports.File({ \n filename: 'logs/error.log', \n level: 'error' \n }),\n new winston.transports.File({ \n filename: 'logs/combined.log' \n })\n ]\n});\n\nexport default logger;\n\n\nAgora você pode usar o logger em qualquer módulo:
\nimport logger from './logger';\n\nfunction getUser(id: string) {\n logger.info(`Fetching user with ID: ${id}`);\n try {\n // lógica para obter o usuário\n logger.debug('User data retrieved successfully');\n } catch (error) {\n logger.error('Failed to fetch user', { userId: id, error });\n }\n}\n\n\n3. Usando níveis de registro
\n\nNíveis padrão (do menos importante ao mais importante):
\n- \n
- debug — informações detalhadas de depuração (apenas para desenvolvimento). \n
- info — mensagens informativas padrão. \n
- warn — avisos sobre problemas potenciais. \n
- error — erros que exigem atenção. \n
Configure o nível de registro através de variáveis de ambiente:
\n// No arquivo .env\nLOG_LEVEL=debug # para desenvolvimento\nLOG_LEVEL=warn # para produção\n\n\n4. Registro estruturado
\n\nPasse informaçõ