O Winston é uma biblioteca de logging para Node.js, amplamente utilizada por sua flexibilidade e facilidade de uso. Ele permite registrar logs em diferentes níveis de severidade e enviá-los para múltiplos destinos, como arquivos, console, bancos de dados, entre outros.
Recursos
- Transports: Winston utiliza o conceito de "transports" para determinar onde os logs devem ser enviados. Por exemplo, você pode configurar um transporte para registrar logs em um arquivo, outro para exibir logs no console e até mesmo para enviar logs para uma API de terceiros.
- Formato personalizável: O Winston permite customizar o formato dos logs, seja adicionando timestamps, colorindo a saída no console ou formatando os logs como JSON.
- Níveis de log: Você pode definir diferentes níveis de severidade para os logs. Por padrão, o Winston segue os níveis
error,warn,info,http,verbose,debug, esilly. - Suporte a múltiplos transportes: Você pode definir vários transportes ao mesmo tempo. Por exemplo, enquanto um transporte escreve logs de erro em um arquivo, outro pode estar enviando logs de informação para um serviço de monitoramento.
- Middleware para Express: Winston pode ser facilmente integrado a uma aplicação Express.js para registrar todas as requisições HTTP.
- Customização e Extensibilidade: É possível estender o Winston para criar transportes personalizados ou alterar o comportamento padrão de como os logs são formatados e enviados.
Rotacionamento de Logs
npm install winston-daily-rotate-filePara grande volume de logs, rotação de logs.
import DailyRotateFile from 'winston-daily-rotate-file';
const logger = createLogger({
transports: [
new DailyRotateFile({
filename: '/app/logs/application-%DATE%.log',
datePattern: 'YYYY-MM-DD',
maxSize: '20m',
maxFiles: '14d'
}),
],
});
Arquivo de configuração do wiston
// logger.ts
import { createLogger, format, transports } from 'winston'
import DailyRotateFile from 'winston-daily-rotate-file'
export const logger = createLogger({
format: format.combine(
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), // time log
format.errors({ stack: true }),
format.printf(({ timestamp, level, message, ...meta }) => {
const metaString = meta ? JSON.stringify(meta) : ''
return `${timestamp} [${level.toUpperCase()}]: ${message} ${metaString}`
}),
format.splat()
),
transports: [
new transports.Console(),
new DailyRotateFile({
filename: './logs/info/portal-%DATE%.log',
datePattern: 'YYYY-MM-DD HH:mm:ss',
level: 'info',
zippedArchive: true,
maxSize: '20m',
maxFiles: '14d',
}),
new DailyRotateFile({
filename: './logs/error/portal-%DATE%.log',
datePattern: 'YYYY-MM-DD HH:mm:ss',
level: 'error',
zippedArchive: true,
maxSize: '20m',
maxFiles: '14d',
}),
],
})
Formatação (format)
format.combine(...): Combina vários formatos para criar um único formato final.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }): Adiciona um timestamp (data e hora) a cada log. O formatoYYYY-MM-DD HH:mm:ssdefine a forma como a data e hora serão exibidas.format.errors({ stack: true }): Adiciona a stack trace (rastreamento de pilha) ao log se omessagefor um erro.format.printf(({ timestamp, level, message, ...meta }) => {...}): Cria um formato customizado para a saída de log. No exemplo, ele organiza a mensagem no formato:timestamp [LEVEL]: message meta.timestamp: A data e hora do log.level: O nível de log (info, error, etc.), em letras maiúsculas.message: A mensagem de log.meta: Metadados adicionais passados na mensagem de log, convertidos em string JSON.
format.splat(): Habilita a substituição de tokens (%s,%d, etc.)
Transportes (transports)
transports.Console(): Envia as mensagens de log para o console.DailyRotateFile: Escreve logs em arquivos que são rotacionados diariamente.filename: Define o caminho e o nome do arquivo de log, onde%DATE%será substituído pela data de criação do arquivo.datePattern: Define o padrão de data a ser usado para rotacionar os arquivos de log. Aqui, éYYYY-MM-DD HH:mm:ss, mas geralmente éYYYY-MM-DD. (Esse formato que você configurou parece estar aplicando a rotação a cada segundo. Se deseja rotação diária, um padrão comoYYYY-MM-DDseria mais comum.)level: Especifica o nível de log que esse arquivo deve armazenar (info,error, etc.).zippedArchive: Setrue, arquiva (compressão em formato zip) os arquivos de log antigos.maxSize: Limita o tamanho máximo de cada arquivo de log (ex:20mpara 20 megabytes).maxFiles: Limita o número máximo de arquivos de log antigos que são mantidos. Aqui, define que logs mais antigos que 14 dias serão excluídos.
Configurações para o
DailyRotateFile:
Arquivo de função log
// log.ts
import { logger } from './logger'
export type LogOptions = {
level: 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly'
message: string
meta?: object
}
export const log = ({ level, message, meta }: LogOptions) => {
logger.log({
level,
message,
...meta,
})
}
Integração co ElasticSearch
npm install --save winston winston-elasticsearchArquivo de configuração de integração elasticsearch
import { ElasticsearchTransport } from 'winston-elasticsearch';
import { Client } from '@elastic/elasticsearch';
const esClient = new Client({ node: 'http://localhost:9200' }); // Substitua pela URL do seu Elasticsearch
export const esTransport = new ElasticsearchTransport({
level: 'info', // Define o nível mínimo de log para enviar para o Elasticsearch
client: esClient,
indexPrefix: 'application-logs', // Prefixo para os índices no Elasticsearch
transformer: (logData) => {
return {
'@timestamp': logData.timestamp,
message: logData.message,
severity: logData.level,
fields: logData.meta, // Metadados adicionais
};
},
// Configurações opcionais
bufferLimit: 1000, // Número máximo de logs para armazenar em buffer antes de enviar
flushInterval: 5000, // Intervalo em milissegundos para envio de logs em buffer
pipeline: 'logs_pipeline' // Se você tiver um pipeline de ingestão configurado no Elasticsearch
});