Logging em aplicações TypeScript: melhores práticas na prática

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Logging em aplicações TypeScript: melhores práticas na prática



Logging é uma parte fundamental de qualquer aplicação em produção. Ele permite não apenas rastrear a execução do código e encontrar erros, mas também realizar auditoria de segurança, analisar desempenho e depurar cenários complexos. Em TypeScript, com seu poderoso sistema de tipos, a abordagem de logging se torna ainda mais flexível e confiável. Neste artigo, vamos abordar as melhores práticas de logging com exemplos concretos.



1. Escolha da biblioteca e configuração do logger



A primeira coisa a fazer é escolher uma biblioteca adequada. Entre as soluções populares, destacam-se winston e pino. Ambas oferecem suporte nativo a TypeScript, mas têm prioridades diferentes: winston — flexibilidade e funcionalidades ricas, pino — máxima performance.



Veja um exemplo de configuração do winston com tipagem:



import winston from 'winston';

const logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', format: winston.format.combine( winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.errors({ stack: true }), winston.format.json() ), defaultMeta: { service: 'user-service' }, transports: [ new winston.transports.Console({ format: winston.format.combine( winston.format.colorize(), winston.format.simple() ), }), new winston.transports.File({ filename: 'logs/error.log', level: 'error' }), new winston.transports.File({ filename: 'logs/combined.log' }), ],});

export default logger;


Para pino, a configuração será mais concisa, mas igualmente eficaz:



import pino from 'pino';

const logger = pino({ level: process.env.LOG_LEVEL || 'info', transport: { target: 'pino-pretty', options: { colorize: true, translateTime: 'SYS:standard', }, },});

export default logger;


Dica: Sempre externalize a configuração do nível de logging para variáveis de ambiente (LOG_LEVEL). Em produção, geralmente usa-se info ou warn, e em desenvolvimento, debug.



2. Logging estruturado e contexto



Um dos maiores erros é registrar strings simples. Em vez disso, use objetos estruturados. Eles permitem filtrar e agregar logs facilmente em sistemas como ELK, Grafana ou Datadog.



Exemplo de logging ruim:



logger.info('User logged in successfully');


Exemplo de logging bom com contexto:



logger.info({  message: 'User logged in',  userId: user.id,  email: user.email,  loginMethod: 'oauth',  ip: request.ip,  duration: Date.now() - startTime,});


Para facilitar, crie um wrapper tipado:



interface LogContext {  requestId?: string;  userId?: string;  action?: string;  [key: string]: unknown;}

function logWithContext(message: string, context: LogContext = {}): void { logger.info({ message, ...context });}

// UsologWithContext('Order processed', { orderId: '12345', userId: 'user_678', total: 99.99 });


Essa abordagem garante que cada log contenha informações essenciais para análise.



3. Logging de erros e exceções



O tratamento de erros é a parte mais importante do logging. Sempre registre o stack trace completo do erro e o contexto em que ocorreu. Não use console.error — ele não oferece flexibilidade para rotação e formatação.



Padrão correto com TypeScript:



import logger from './logger';

async function fetchUserData(userId: string): Promise<UserData> { try { const response = await api.get(`/users/${userId}`); ret

Blogs

Book Recommendations