Configuração de Logs do RUB

O RUB possui um sistema de logs que armazena em disco mensagens de diagnósticos, todas as consultas ao banco de dados e todas as alterações de dados, bem como as ações dos usuários no sistema.

1. Categorias e Armazenamento

Os logs são divididos em 6 categorias principais:

CategoriaSufixo do ArquivoDescrição
MAIN_main.logLogs gerais do sistema.
SYNC_sync.logSincronização entre loja e central (arquitetura remota).
INTF_intf.logProcessamento de integrações entre sistemas.
DATA_data.logOperações de banco de dados (Insert/Update/Delete).
ANA_ana.logLogs referentes ao ETL para análises.
ERRO_erro.logLogs específicos para mensagens de nível erro.

1.1 Diretório de Logs

Os logs são armazenados no subdiretório log dentro do diretório de instalação do RUB.

Em servidores Linux, recomenda-se utilizar links simbólicos (symlinks) para armazenar os logs em partições dedicadas ( ex: /var/log/rub):

cd /opt/rub
ln -s /var/log/rub log

2. Formato dos Logs

Os arquivos de logs seguem o padrão definido na classe RuBLogWriter. O formato básico de cada linha é:

DATAHORA NÍVEL [MDC] ORIGEM: MENSAGEM

*DATAHORA: Carimbo de data e hora em que a mensagem foi gerada (AAAA-MM-DD HH:mm:ss). *NÍVEL: Nome do nível de log com 5 caracteres (ex: INFO, DEBUG, WARN, ERROR). Note o espaço à esquerda para alinhar níveis com 4 letras. *MDC (Mapped Diagnostic Context): Conjunto de informações contextuais entre colchetes, essencial para rastreabilidade: * [main]: Nome da categoria do log (LogKind). * [TID: 490]: ID da Thread que gerou o log. * [EXEC_ID]: Um UUID único para cada execução/requisição (ex: 66623dcc-be76-4cfd-8716-37f039f1c2c7). Permite filtrar todas as linhas de uma mesma operação. * [CONTEXT_ID]: ID do contexto atual, como o código da loja ou empresa (ex: [loja999]). Fundamental para troubleshooting em ambientes multiloja. *ORIGEM: Local onde o log foi gerado. Pode ser simplificado (Arquivo.java:Linha) ou expandido ( pacote.Classe.metodo(Arquivo.java:Linha)), dependendo da chave log.src.full. *MENSAGEM: O conteúdo descritivo do log.

Exemplo de linha de log (Real):

2026-06-19 03:34:07 INFO [main] [TID: 490] [66623dcc-be76-4cfd-8716-37f039f1c2c7] [loja999] AbstractSubDBAuditoria.java:122: SQL Time: 2ms queryEx select ...

2.1 Identificação de Categorias (log.mdc.logKind)

Quando a chave log.mdc.logKind está ativa (padrão true), o primeiro campo do MDC identifica a categoria do log. Isso permite saber a qual categoria a mensagem pertence mesmo quando os logs são visualizados de forma unificada (como no journalctl ou stdout de containers).

Exemplos de MDC por categoria:

*Logs Gerais: [main] *Sincronização: [sync] *Banco de Dados: [data] *Interfaces: [intf] *Analytics: [ana] *Erros: [erro]

Exemplo de log de Sincronização: 2026-06-19 03:35:10 INFO [sync] [TID: 512] [88d3e2...] [loja3] SyncPlan.java:88: Sincronização concluída com sucesso.

2.2 Utilidade do MDC em Ambientes Multiloja

Em instâncias que atendem diversas lojas simultaneamente, o MDC permite filtrar logs de uma loja específica utilizando comandos como grep:

# Filtrar todos os logs da loja 999
tail -f log/20260619_main.log | grep "[loja999]"

# Rastrear uma execução específica pelo seu UUID
grep "66623dcc-be76-4cfd-8716-37f039f1c2c7" log/20260619_main.log

3. Manutenção e Rotação

3.1 Retenção (Dias)

Os arquivos de log são mantidos pelo sistema pela quantidade de dias definida em configuração avançada.O valor padrão para todas as categorias é de 15 dias.

Chave de ConfiguraçãoPadrãoDescrição
tempoDeRegistroDeLogMain15Dias de retenção para logs gerais (MAIN).
tempoDeRegistroDeLogSync15Dias de retenção para logs de sincronização (SYNC).
tempoDeRegistroDeLogIntf15Dias de retenção para logs de interface (INTF).
tempoDeRegistroDeLogData15Dias de retenção para logs de banco de dados (DATA).
tempoDeRegistroDeLogAna15Dias de retenção para logs de analytics (ANA).
tempoDeRegistroDeLogErro15Dias de retenção para logs de erro (ERRO).

Os logs gerados há mais dias do que o configurado serão apagados automaticamente.

3.2 Rotação por Tamanho e Data

Os logs são rotacionados por dia ou tamanho para economia de disco.

*tamanhoMaximoLog: Determina o tamanho máximo (em MB) do log descompactado antes de rotacionar (Padrão: 2048 MB). *maximoArquivosRotacionadosDia: Indica a quantidade máxima por dia de arquivos rotacionados que o sistema irá manter (0 para ilimitado).

Ao mudar o dia ou atingir o tamanho máximo, o RUB compacta os logs anteriores em formatogzip. Arquivos compactados por tamanho possuem o seguinte formato de nome: AAAAMMDD_TIPO.N.log.gz

Onde N é o sequencial de arquivos compactados no mesmo dia, iniciado em 0 (zero).

4. Ligar e Desligar Logs (Arquivo e Saída Padrão)

O RUB permite controlar individualmente se cada categoria de log deve ser gravada em arquivo (archive) ou enviada para a saída padrão (sysout).

Estas configurações são feitas diretamente no arquivo config.ini.

4.1 Chaves de Configuração

Substitua {suffix} pelo sufixo da categoria desejada (main, sync, intf, data, ana, erro).

ChaveValoresDescrição
log.archive.{suffix}true / falseSe false, o RUB para de gravar logs desta categoria em arquivos no disco.
log.sysout.{suffix}true / falseSe false, o RUB para de enviar logs desta categoria para a saída padrão (console).

4.2 Exemplos Práticos

Desligar logs de Banco de Dados (_data.log) no arquivo:

log.archive.data=false

Desligar todos os logs de saída padrão para economizar recursos:

log.sysout.main=false
log.sysout.sync=false
log.sysout.intf=false
log.sysout.data=false
log.sysout.ana=false

Ligar log de erro na saída padrão (por padrão é desativado):

log.sysout.erro=true

5. Configurações Avançadas de Formatação

Estas chaves no config.ini permitem personalizar o conteúdo do MDC e da Origem no log:

ChavePadrãoDescrição
log.mdc.logKindtrueInclui o nome da categoria no início do MDC (ex: [main]).
log.mdc.tidtrueInclui o ID da thread (ex: [TID: 42]).
log.mdc.execIdtrueInclui o ID de execução único (UUID).
log.mdc.contextIdtrueInclui o ID do contexto atual (ex: loja ou empresa). Se indefinido, mostra [undefined].
log.src.fullfalseSe true, expande a origem para incluir pacote, classe e método. Se false, mostra apenas Arquivo:Linha.

6. Regras de Filtragem (.logrules)

O RUB permite criar regras de filtragem finas para permitir ou negar mensagens específicas. Cada categoria de log possui seu próprio arquivo de regras no diretório configuration/.

6.1 Nomes dos Arquivos de Regras

*MAIN: configuration/default.logrules *ANA: configuration/ana_default.logrules *DATA: configuration/data_default.logrules *ERRO: configuration/erro_default.logrules *INTF: configuration/intf_default.logrules *SYNC: configuration/sync_default.logrules

6.2 Formato das Regras

As regras são lidas sequencialmente, e as linhas inferiores têm prioridade sobre as superiores. O formato é:

ACAO NIVEL ORIGEM TEXTO

*ACAO: allow (permite) ou deny (nega). *NIVEL: Combinação de níveis (D, I, W, E) ou * para todos os níveis. *ORIGEM: Classe ou pacote que emitiu o log. Use * para todas as origens. A regra se aplica se o texto informado estiver contido no nome do método/classe. *TEXTO(Opcional): Se informado, a regra só será aplicada se a mensagem contiver este texto.

6.3 Exemplos de Regras

Desabilitar todos os logs de uma categoria:

deny IDWE *

Desabilitar apenas logs de DEBUG:

deny D *

Desabilitar logs específicos de operações de banco de dados:

deny IDWE *.logInsert
deny IDWE *.logUpdate
deny IDWE *.logDelete

Desabilitar logs de um pacote específico:

deny IDWE com.gicbrasil.rub.ressup.analiseconsumo

Desabilitar logs que contenham um texto específico (ex: tempo de SQL):

deny IDWE * "SQL Time:"

Permitir logs de erro mesmo em classes silenciadas:

deny IDW com.gicbrasil.rub.SuaClasse *
allow E com.gicbrasil.rub.SuaClasse *

Filtragem condicional (Deny geral, exceto para um usuário):

deny IDWE *.logInsert
allow IDWE * ID_USUARIO_ESPECIFICO

7. Integração com systemd (Observabilidade)

Quando o RUB roda como um serviço no Linux via systemd, o objetivo principal de utilizar a saída padrão (sysout) é a Observabilidade. Ao centralizar os logs no journald, facilitamos a coleta por agentes comoPromtail(Grafana Loki) ouFluent-bit, permitindo a criação de dashboards e alertas no Grafana.

7.1 Por que separar os logs?

Utilizar um SyslogIdentifier único (ex: rub) é fundamental para que as ferramentas de coleta consigam:

1.Filtragem Eficiente: Isolar as mensagens do RUB de outras mensagens do sistema (como SSH ou kernel). 2.Rotulagem (Labeling): Atribuir rótulos automáticos como {job="rub"} no Loki, facilitando buscas complexas. 3.Performance: Evitar o processamento de logs irrelevantes pelo agente de coleta.

7.2 Preparação no RUB

Certifique-se de que o envio para a saída padrão está ligado para as categorias operacionais no config.ini:

log.sysout.main=true
log.sysout.sync=true
log.sysout.intf=true
log.sysout.data=false  # Opcional: Desligado pelo alto volume (erros de SQL já saem no MAIN/SYNC)
log.sysout.erro=false  # Desligado pois erros já estão no main/sync

7.3 Exemplo de Arquivo de Serviço (rub.service)

Utilize o SyslogIdentifier para dar um nome único aos logs do RUB, facilitando a separação.

[Unit]
Description=Serviço RUB
After=network.target postgresql.service

[Service]
Type=simple
User=rub
WorkingDirectory=/home/rub/app
ExecStart=/home/rub/app/gradlew run
Restart=always

# Identificador para o log
SyslogIdentifier=rub

# Redireciona a saída para o journal
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

7.4 Visualizando Logs Separados

Com o SyslogIdentifier configurado, você pode filtrar os logs do RUB sem ver as mensagens normais do sistema:

# Ver apenas logs do RUB em tempo real
journalctl -u rub.service -f

# Ver logs do RUB filtrando pelo identificador
journalctl -t rub -f

7.5 Rotação e Retenção Curta no systemd

Ao utilizar ferramentas de observabilidade externa (Loki/Grafana), os logs no journald tornam-se efêmeros (apenas um buffer).Recomenda-se manter tempos e tamanhos de retenção pequenospara economizar recursos do servidor:

Crie uma configuração em /etc/systemd/journald.conf.d/rub.conf:

[Journal]
# Limite de tamanho total dos logs (buffer para o coletor)
SystemMaxUse=200M
# Mantém logs locais por pouco tempo (já estarão no Grafana)
MaxRetentionSec=2day

Para descartar logs (não salvar no disco) e manter apenas na memória:

[Journal]
Storage=volatile
RuntimeMaxUse=100M

7.6 Separando em um Arquivo Físico com rsyslog (Opcional)

Para evitar que os logs do RUB poluam o /var/log/syslog ou /var/log/messages, crie um arquivo de configuração no rsyslog (ex: /etc/rsyslog.d/rub.conf):

# Redireciona logs com identificador "rub" para um arquivo separado
if $programname == 'rub' then /var/log/rub-sysout.log

# Opcional: Para de processar esses logs para que não caiam no syslog geral
& stop

Após criar o arquivo, reinicie o rsyslog: sudo systemctl restart rsyslog.

7.7 Exemplo de Coleta para Grafana (Promtail)

Exemplo de configuração do Promtail para ler logs do RUB via journal:

scrape_configs:
  - job_name: rub_service
    journal:
      max_age: 12h
      path: /var/log/journal
      labels:
        job: rub
    relabel_configs:
      - source_labels: [ '__journal__syslog_identifier' ]
        target_label: 'syslog_identifier'
      # Filtra para pegar apenas o que identificamos como 'rub'
      - source_labels: [ 'syslog_identifier' ]
        regex: 'rub'
        action: keep

8. Coleta de Logs em Containers (Docker/Kubernetes)

Em ambientes de container, a saída padrão é o meio oficial de coleta para ferramentas de Observabilidade.

8.1 Configuração Recomendada (Eficiência)

Para dashboards no Grafana, o ideal é ter logs limpos e sem duplicidade: Em containers, a prática recomendada é ativar a saída padrão (sysout) para as categorias operacionais edesativar a categoria ERRO.

Por que desativar o sysout de ERRO? No RUB, a categoria ERRO contém apenas mensagens de nível ERROR. No entanto, essas mesmas mensagensjá são enviadaspara suas respectivas categorias de origem (como MAIN, SYNC ou DATA). Habilitar o sysout para ERRO resultaria em logs duplicados no coletor (Docker/Kubernetes), dificultando a análise e aumentando o volume de dados desnecessariamente.

Exemplo de configuração no config.ini para coleta completa e eficiente:

# Habilita categorias principais (erros já inclusos nestas)
log.sysout.main=true
log.sysout.sync=true
log.sysout.intf=true
log.sysout.ana=true

# Desabilita categoria de erro redundante
log.sysout.erro=false

# Opcional: Logs de banco de dados costumam ser volumosos, 
# avalie se realmente são necessários no sysout
log.sysout.data=false

# Desabilitar arquivamento em disco para evitar consumo de armazenamento efêmero
log.archive.main=false
log.archive.sync=false
log.archive.intf=false
log.archive.data=false
log.archive.ana=false
log.archive.erro=false

8.2 Outros Serviços

A mesma lógica de evitar logs redundantes de erro deve ser aplicada a outros serviços e módulos que compõem o ecossistema do RUB. Sempre priorize a coleta da categoria funcional (que dá contexto ao erro) em vez de uma categoria genérica de erros que apenas duplica a informação.

8.3 Visualizando Logs

Os logs capturados podem ser visualizados diretamente via comando do orquestrador:

# Docker
docker logs -f nome_do_container

# Kubernetes
kubectl logs -f nome_do_pod -c nome_do_container

8.4 Rotação e Retenção no Container

Em containers, os logs de stdout também devem ter retenção curta se estiverem sendo exportados para o Grafana:

docker-compose.yml:

services:
  rub:
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "2"

8.5 Exemplo de Coleta (Loki via Docker Driver)

Você pode configurar o Docker para enviar logs diretamente ao Loki:

logging:
  driver: loki
  options:
    loki-url: "http://loki:3100/loki/api/v1/push"
    loki-external-labels: "container_name={{.Name}},job=rub"

9. Estratégia Recomendada: Observabilidade vs. Logs Locais

A escolha da estratégia de log depende da infraestrutura disponível:

9.1 Com Infraestrutura de Observabilidade (Recomendado)

Se você utiliza Grafana, Loki, ELK ou Datadog:

*Use sysout: Ligue log.sysout.* (exceto erro). *Desligue archive: Defina log.archive.*=false para não gastar IOPS e disco local. *Retenção Local Curta: Mantenha apenas 1 ou 2 dias de log no journald ou Docker como fallback.

9.2 Sem Infraestrutura de Observabilidade

Se você faz troubleshooting acessando o servidor via SSH:

*Use Logs em Disco (Seção 1): Mantenha log.archive.*=true. *Aproveite a Organização: Os logs do RUB já são separados por categoria (_data.log, _sync.log), o que facilita muito a análise manual com grep, tail e less. *Gestão de Retenção: Ajuste as configurações avançadas (tempoDeRegistroDeLog...) para definir o tempo de retenção ideal no disco, garantindo histórico suficiente para auditoria manual sem esgotar o armazenamento. *Desligue sysout: Pode desligar log.sysout.*=false para reduzir o ruído no console do sistema.