Pular para conteúdo

Logs

Sistema de logging da aplicação Nayax → Saipos.

Níveis de Log

Configure via variável LOG_LEVEL:

# Development - mais verboso
LOG_LEVEL=debug

# Staging - moderado
LOG_LEVEL=info

# Production - apenas importante
LOG_LEVEL=warn

Hierarquia

  • debug - Tudo (debug, info, warn, error)
  • info - Info + warn + error
  • warn - Warn + error
  • error - Apenas erros

Localização dos Logs

Logs da Aplicação

# Arquivo principal
logs/app.log

# Erro
logs/error.log

# Combinado
logs/combined.log

Logs do PM2

# Logs do PM2
~/.pm2/logs/nayax-saipos-out.log
~/.pm2/logs/nayax-saipos-error.log

# Ou com PM2
pm2 logs nayax-saipos

Ver Logs em Tempo Real

Logs Gerais

# Seguir todos os logs
tail -f logs/app.log

# Últimas 100 linhas
tail -100 logs/app.log

# Com cores (se disponível)
tail -f logs/app.log | ccze -A

Logs Filtrados

# Apenas erros
tail -f logs/app.log | grep ERROR

# Webhooks Nayax
tail -f logs/app.log | grep NAYAX

# Processamento Saipos
tail -f logs/app.log | grep SAIPOS

# Jobs
tail -f logs/app.log | grep "JOB\|JobsProcessor"

# Múltiplos filtros
tail -f logs/app.log | grep -E "ERROR|WARN|CRITICAL"

Logs com Contexto

# Ver 5 linhas após match
tail -f logs/app.log | grep -A 5 "ERROR"

# Ver 5 linhas antes
tail -f logs/app.log | grep -B 5 "ERROR"

# Ver 5 antes e 5 depois
tail -f logs/app.log | grep -C 5 "ERROR"

Tipos de Logs

1. Recepção de Webhook

[NayaxController] NAYAX EVENT: {
  "transactionKey": "550e8400-e29b-41d4-a716-446655440000",
  "storeCode": "LOJA001",
  "totalAmount": 50.00
}

2. Autenticação

[NayaxAuthGuard] JWT token válido para "user@example.com". Acesso autorizado.
[NayaxAuthGuard] Bearer token Nayax válido. Acesso autorizado.
[NayaxAuthGuard] ❌ Bearer token inválido

3. Enfileiramento

[NayaxService] Event queued: transactionKey=550e8400... jobId=job_abc123

4. Processamento de Jobs

🚀 INICIANDO PROCESSAMENTO DO JOB
ID: job_abc123
Action: CREATE
EventKey: 550e8400-e29b-41d4-a716-446655440000
═══════════════════════════════════════
✅ Evento encontrado: true
[SAIPOS][CREATE] Processing key: 550e8400... store: LOJA_SAIPOS_001
[SAIPOS][CREATE] Response: {"success":true,"orderId":"..."}
[JobsProcessor] Job job_abc123 SENT (CREATE)

5. Erros

═══════════════════════════════════════
❌ ERRO NO PROCESSAMENTO DO JOB
Job ID: job_abc123
Status HTTP: 400
Response Data: {"errorCode":400,"message":"order_id já existe"}
Error Message: Request failed with status code 400
Error Stack: [stack trace]
═══════════════════════════════════════

6. Reaper

[JobsProcessor] Reaper: resetting 3 stuck PROCESSING jobs
[JobsProcessor] Reaper: no stuck jobs

Logs Detalhados (Debug)

Habilitar

LOG_LEVEL=debug
LOG_SAIPOS_BODY=true

Corpo das Requisições Saipos

[SAIPOS][CREATE] Request body:
{
  "order_id": "550e8400-e29b-41d4-a716-446655440000",
  "cod_store": "LOJA_SAIPOS_001",
  "total_amount": 50.00,
  "items": [...],
  "payment_types": [...]
}

Performance

LOG_SAIPOS_BODY=true gera logs muito grandes. Nunca use em produção.

Analisar Logs

Contar Erros

# Contar por tipo
grep "ERROR" logs/app.log | wc -l
grep "WARN" logs/app.log | wc -l

# Últimas 24h
find logs/ -name "*.log" -mtime -1 -exec grep "ERROR" {} \; | wc -l

Erros Mais Comuns

# Top 10 erros
grep "ERROR" logs/app.log | \
  sed 's/.*ERROR: //' | \
  sort | uniq -c | \
  sort -rn | head -10

Jobs por Status

# Contar jobs SENT
grep "Job.*SENT" logs/app.log | wc -l

# Contar jobs FAILED
grep "Job.*FAILED" logs/app.log | wc -l

# Contar jobs DLQ
grep "Job.*DLQ" logs/app.log | wc -l

Análise por Período

# Logs de hoje
grep "$(date +%Y-%m-%d)" logs/app.log

# Logs entre 10:00 e 11:00
grep "2025-01-15T10:" logs/app.log

# Logs de ontem
grep "$(date -d yesterday +%Y-%m-%d)" logs/app.log

Rotação de Logs

Manual

# Criar script de rotação
nano /home/usuario/rotate-logs.sh
#!/bin/bash
LOG_DIR="/home/usuario/nayax-saipos/logs"
DATE=$(date +%Y%m%d)

# Comprimir logs antigos
gzip -c "$LOG_DIR/app.log" > "$LOG_DIR/app-$DATE.log.gz"
gzip -c "$LOG_DIR/error.log" > "$LOG_DIR/error-$DATE.log.gz"

# Limpar logs atuais
> "$LOG_DIR/app.log"
> "$LOG_DIR/error.log"

# Deletar logs > 30 dias
find "$LOG_DIR" -name "*.log.gz" -mtime +30 -delete
# Permissão
chmod +x /home/usuario/rotate-logs.sh

# Cron diário às 00:00
crontab -e

# Adicionar:
0 0 * * * /home/usuario/rotate-logs.sh

Com Logrotate

# Criar configuração
sudo nano /etc/logrotate.d/nayax-saipos
/home/usuario/nayax-saipos/logs/*.log {
    daily
    rotate 30
    compress
    delaycompress
    notifempty
    create 0644 usuario usuario
    sharedscripts
    postrotate
        pm2 reloadLogs
    endscript
}

Com PM2

# Instalar módulo
pm2 install pm2-logrotate

# Configurar
pm2 set pm2-logrotate:max_size 10M        # Tamanho máximo
pm2 set pm2-logrotate:retain 7            # Dias para manter
pm2 set pm2-logrotate:compress true       # Comprimir
pm2 set pm2-logrotate:rotateInterval '0 0 * * *'  # Diário às 00:00

Logs Estruturados (JSON)

Para melhor parsing, use logs em JSON:

Configuração

// src/main.ts
import { WinstonModule } from 'nest-winston';
import * as winston from 'winston';

const app = await NestFactory.create(AppModule, {
  logger: WinstonModule.createLogger({
    transports: [
      new winston.transports.File({
        filename: 'logs/app.json',
        format: winston.format.json(),
      }),
    ],
  }),
});

Parsing

# Ver logs JSON
cat logs/app.json | jq '.'

# Filtrar por nível
cat logs/app.json | jq 'select(.level == "error")'

# Filtrar por campo
cat logs/app.json | jq 'select(.context == "JobsProcessor")'

Monitoramento com Ferramentas

Tail no Browser

# Instalar
npm install -g pm2-web

# Iniciar
pm2-web

Acesse: http://localhost:9615

Kibana + Elasticsearch

Para grandes volumes:

  1. Enviar logs para Elasticsearch
  2. Visualizar no Kibana
  3. Criar dashboards
  4. Configurar alertas

Datadog

# Instalar agent
DD_API_KEY=xxx bash -c "$(curl -L https://s3.amazonaws.com/dd-agent/scripts/install_script.sh)"

# Configurar logs
sudo nano /etc/datadog-agent/conf.d/nodejs.d/conf.yaml

Sentry

// src/main.ts
import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.NODE_ENV,
});

Queries Úteis nos Logs

Encontrar Job Específico

grep "job_abc123" logs/app.log

Rastrear Evento Completo

# Buscar por transactionKey
grep "550e8400-e29b-41d4-a716-446655440000" logs/app.log

Ver Todas Tentativas de um Job

# Buscar eventKey e ver histórico
grep "eventKey_xyz" logs/app.log | grep -E "PROCESSING|SENT|FAILED|DLQ"

Performance

# Tempos de processamento
grep "tick: end in" logs/app.log | \
  sed 's/.*end in \([0-9]*\)ms.*/\1/' | \
  awk '{sum+=$1; count++} END {print "Avg:", sum/count, "ms"}'

Alertas Baseados em Logs

Script de Alerta

#!/bin/bash
# alert-errors.sh

ERROR_COUNT=$(grep "ERROR" logs/app.log | wc -l)
THRESHOLD=10

if [ $ERROR_COUNT -gt $THRESHOLD ]; then
  echo "⚠️ Muitos erros: $ERROR_COUNT (threshold: $THRESHOLD)" | \
    mail -s "Alert: Nayax-Saipos Errors" admin@example.com
fi

Cron

# A cada hora
0 * * * * /home/usuario/alert-errors.sh

Dicas de Performance

Evitar Logs Excessivos

// ❌ Ruim - loga tudo
this.logger.debug('Processing', data);

// ✅ Bom - só em debug
if (process.env.LOG_LEVEL === 'debug') {
  this.logger.debug('Processing', data);
}

Sampling

// Logar apenas 10%
if (Math.random() < 0.1) {
  this.logger.info('Sampled log', data);
}

Async Logging

Use transports assíncronos para não bloquear:

new winston.transports.File({
  filename: 'logs/app.log',
  stream: fs.createWriteStream('logs/app.log', { flags: 'a' })
});