Spraxium logoSpraxium

Visão Geral do Logger

A classe Logger fornece logging estruturado, baseado em transports, com mascaramento automático de tokens. Aprenda os níveis embutidos, como criar loggers filhos e como o logger se integra ao framework.

O pacote @spraxium/logger

Atualmente, o logger foi extraído de @spraxium/core para um pacote próprio: @spraxium/logger. Instale-o ao lado do framework ou de qualquer outro pacote Spraxium que precise emitir logs.

snippet.sh
pnpm add @spraxium/logger

Todos os pacotes do framework, como @spraxium/core, @spraxium/components e @spraxium/http, agora importam de @spraxium/logger diretamente. O transport ANSI de console não depende mais de bibliotecas de cor; chalk foi removido do monorepo inteiro.

O que o logger resolve

Bots do Discord geram um fluxo constante de informação operacional: comandos executados, alertas de rate limit, erros de chamadas de API e traces de debug durante o desenvolvimento. A classe Logger oferece uma API unificada para emitir essas mensagens por transports plugáveis. Em vez de espalhar console.log pelo código, você cria instâncias com contexto nomeado, chama métodos tipados como info, warn ou error e deixa a camada de transport decidir para onde cada mensagem vai.

O logger traz dois transports nativos. O ConsoleTransport formata mensagens com timestamp, rótulos coloridos por nível e, quando necessário, indicador de shard no terminal. Já o DiscordTransport envia logs como embeds para um canal ou webhook do Discord, dando visibilidade em tempo real para a operação sem depender de SSH. Os dois podem rodar em paralelo, então uma única chamada a logger.error pode aparecer no terminal e no Discord ao mesmo tempo.

Toda mensagem passa pelo TokenMasker antes de chegar a qualquer transport. Ele procura padrões que lembram tokens de bot do Discord e os substitui por [REDACTED]. Isso evita vazamento acidental de credencial mesmo quando uma stack trace ou mensagem de erro inclui o token cru.

Níveis de log embutidos

O logger reconhece seis níveis de log por padrão. Cada nível tem uma cor própria no console e uma cor de embed padrão no Discord. Você também pode adicionar níveis customizados via configuração, e eles se comportam exatamente como os nativos.

NívelMétodoCor no consoleCor no DiscordUso comum
infoinfoCyan#3498dbMensagens operacionais gerais
successsuccessGreen#2ecc71Operações concluídas e conexões bem-sucedidas
warnwarnYellow#f39c12Estados degradados e limites se aproximando
errorerrorRed#e74c3cFalhas que exigem atenção
debugdebugGray#95a5a6Rastros verbosos de desenvolvimento
commandlog('command', ...)Magenta#9b59b6Execuções de slash commands

O nível debug fica protegido por uma flag. Mensagens enviadas via debug são descartadas silenciosamente a menos que você chame Logger.setDebug(true) ou defina a variável de ambiente SPRAXIUM_DEBUG como "true". Isso permite manter chamadas de debug no código de produção sem custo prático quando o debug estiver desligado.

Criando e usando loggers

Você cria um logger instanciando a classe Logger com um contexto opcional. Esse contexto aparece em toda linha de log entre o nível e a mensagem, o que facilita filtrar saída por origem. O padrão mais comum é manter uma instância por service ou por módulo.

src/services/music.service.ts
import { Injectable } from '@spraxium/common';
import { Logger } from '@spraxium/logger';

@Injectable()
export class MusicService {
  private readonly logger = new Logger('MusicService');

  async play(guildId: string, trackUrl: string) {
    this.logger.info(`Playing track in guild ${guildId}`);
    try {
      await this.connectAndStream(trackUrl);
      this.logger.success(`Track started in guild ${guildId}`);
    } catch (err) {
      this.logger.error(`Failed to play track: ${(err as Error).message}`);
    }
  }
}

O método child cria um novo logger que herda a configuração de transports do logger pai, mas usa outro nome de contexto. Isso é útil dentro de métodos ou rotinas específicas que precisam aparecer com outra identidade no log sem exigir mais um logger declarado no nível da classe.

src/services/queue.service.ts
import { Logger } from '@spraxium/logger';

const parentLogger = new Logger('QueueService');
const importLogger = parentLogger.child('QueueImport');

importLogger.info('Starting playlist import');

Níveis de log customizados

O método extend cria uma função de log nomeada, vinculada a um nível customizado. Você informa o nome do nível e, opcionalmente, a cor. Depois disso, a função funciona como qualquer método embutido e passa por todos os transports. Isso é útil para níveis específicos do domínio, como audit, payment ou moderation, quando você quer separar esse tipo de evento no output.

src/services/audit.service.ts
import { Injectable } from '@spraxium/common';
import { Logger } from '@spraxium/logger';

@Injectable()
export class AuditService {
  private readonly logger = new Logger('AuditService');
  private readonly audit = this.logger.extend('audit', 'blueBright');

  logAction(userId: string, action: string) {
    this.audit(`User ${userId} performed ${action}`);
  }
}

O parâmetro de cor aceita nomes como 'red', 'greenBright' ou 'cyan'. Se ele for omitido, o nível cai para cinza. As cores registradas via extend também são reconhecidas pelo ConsoleTransport, o que mantém a saída consistente em todas as instâncias que usam esse mesmo nível.

O método log

O método log é a saída de baixo nível para emitir mensagens em qualquer nível informado por string. Ele recebe o nível, a mensagem e um objeto metadata opcional. Diferente dos métodos nomeados, log permite anexar dados estruturados diretamente à entrada de log sem precisar criar uma função tipada via extend. É justamente esse método que o CommandLogger usa internamente para anexar dados da execução dos comandos.

src/services/payment.service.ts
import { Logger } from '@spraxium/logger';

const logger = new Logger('PaymentService');

logger.log('payment', 'Charge processed', {
  userId: '123456789',
  amount: 4999,
  currency: 'USD',
});

As chaves de metadata ficam disponíveis como placeholders {{key}} em templates de embed no Discord. Se você configurar um transport de Discord para o nível payment, poderá usar {{userId}}, {{amount}} e {{currency}} diretamente no título, descrição ou campos do embed. Qualquer chave que não for referenciada no template é ignorada silenciosamente.

O método raw

Quando você precisa imprimir uma mensagem sem formatação, timestamp nem prefixo de nível, use raw. Ele chama console.log diretamente, pulando todos os transports e também o token masker. Isso é útil para banners ASCII, linhas separadoras ou qualquer saída estruturada que não deva ser embrulhada no formato padrão de log.

src/main.ts
import { Logger } from '@spraxium/logger';

const logger = new Logger();
logger.raw('');
logger.raw('  Spraxium Bot v2.0.0');
logger.raw('');

Formato da saída no console

Cada linha de log no console segue uma estrutura fixa: data, hora, nível colorido, contexto opcional entre colchetes, número do shard quando aplicável e a mensagem. O formato usa o padrão DD/MM/YYYY - HH:MM:SS em relógio de 24 horas. Quando o bot roda em processo sharded, o ID do shard aparece automaticamente para facilitar a correlação de mensagens entre shards.

terminal
12/04/2026 - 14:32:05 - INFO - [MusicService] - Playing track in guild 123456
12/04/2026 - 14:32:05 - SUCCESS - [MusicService] - Track started in guild 123456
12/04/2026 - 14:32:07 - ERROR - [MusicService] - [Shard 0] - Failed to play track: timeout