Log4j estendido

12 respostas
U

Salve todos.
Trabalhei com Log4j algumas vezes, sempre com a idéia de depuração de erros mesmo.
Aconteceu algo fora do estado esperado da aplicação, registra um mensagem de log!

Bom, agora eu preciso de algo mais. Preciso de logs que gerem “informações de negocio” mesmo.
Como quem acessou tal recurso, quando, por quanto tempo, etc. Informações que vão servir de base para relatórios, ajudar na tomada de decisões.
De cara, vi que preciso salvar tudo isso numa persistência confiável. O Log4J tem o JDBCAppender que salva as msgs em BD, blz.

A questão é como faço para passar mais que uma simples mensagem String para log.
Sei que usando o código abaixo, por exemplo, o PatternLayout pode “imprimir” no appender a data, hora, qual classe lançou, método e a msg em si.

logger.debug("Minha msg");

Gostaria de passar, por exemplo, objetos de domínio ou negócio, bem como outros tipos quaisquer, SEM CONCATENÁ-LOS NA MENSAGEM.
É importante separar a mensagem desses parâmetros pois devo guarda-los em campos separados na tabela do banco.

Algo como:

logger.info("O recurso foi alterado.", usuarioLogado, recurso, recurso.getStatus() ); //só um exemplo..

Deu pra sacar a idéia?
Como eu faria isso?
O Log4J dá suporte pra isso ou na verdade eu nem preciso dele??

Abraços

12 Respostas

eduveks

Quanto a passar varios parametros é impossível!

O que vc pode fazer é, enviar:

logger.info("O recurso foi alterado.[[$]]"+ usuarioLogado +"[[$]]"+ recurso +"[[$]]"+ recurso.getStatus());

Ai na tabela em que vai ser guardada esta informação, vc faz um trigger que faz o split por “[[$]]” e guarda a informação como bem entender…

No H2DataBase podes fazer uma trigger com código Java.

Mas em qualquer DB vc pode fazer isto tanto usando SQL ou usando Java como no caso do H2DataBase.

Há… e aconselho ter uma classe mais ou menos assim para gravar os logs:

public class BusinessLog { private static Logger logger = Logger.getLogger(BusinessLog.class); public static void info(String msg, String usuario, String recurso, String recursoStatus) { logger.info(msg +"[[$]]"+ usuario +"[[$]]"+ recurso +"[[$]]"+ recursoStatus); } }

Assim se quiser mudar o separador é mais fácil, além de também ser mais fácil detectar o tipo dos logs, sendo eles sempre da mesma classe.

U

Hmm, tinha pensando nisso…
Mas aí vc tá concatenando os objetos à mensagem. Depois tem que quebrar as mensagem pra recuperar os valores.
Bom, é uma solução rápida, mas não parece meio POG não?!

(POG = Programação da Orientada a Gambiarra! rs )

[]s

sergiotaborda

O log4j aceita qualquer objeto como mensagem, mas no fim ele só guarda o toString.
Para alterar isso vc precisa costumizar o log4j com Fortmatters e Appenders apropriados

U

Footmatters?? :?
O que seria?

Pois é, imaginei que tivesse que estendê-lo mesmo.
Mas como eu faria isso?

sergiotaborda

uchoaaa:
Footmatters?? :?
O que seria?

Pois é, imaginei que tivesse que estendê-lo mesmo.
Mas como eu faria isso?

Desculpa não é formater é layout
( http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Layout.html)

Como faria isso ? Herdando a classe Layout do Log4j.

U

Opa, valeu.
Tava dando uma olhada no material do site justamente agora.

Mas aí eu teria que estender também o LogginEvent, não é?! Visto que agora meus eventos de logs também utilizam objetos de negócio… :?

Viugi, se assim for, vai ficar meio complicado…

sergiotaborda

uchoaaa:
Opa, valeu.
Tava dando uma olhada no material do site justamente agora.

Mas aí eu teria que estender também o LogginEvent, não é?! .

Não. O LogginEvent transporta o objeto passado em logXXX() com mais algumas informações como data , thread, etc…

quando vc loga vc passa o objeto de negocio logger.logInfo (ObjetoNegocio) e depois vc pega ele de volta com getMessage()
em LogginEvent dentro do layout. Ai vc faz um cast e trabalha normalmente com ObjetoNegocio

Estude bem a API do log4j que é muito bem arquitetada.

P

uchoaaa:
Salve todos.
Bom, agora eu preciso de algo mais. Preciso de logs que gerem “informações de negocio” mesmo.
Como quem acessou tal recurso, quando, por quanto tempo, etc. Informações que vão servir de base para relatórios, ajudar na tomada de decisões.

IMO, vc. não deve usar o log4j ou qualquer API de log para este fim. Pelo que entendi, vc. quer uma espécie de trilha de auditoria e fazer isto via log possui alguns inconvenientes:

  1. Depende da inserção de chamadas nos pontos corretos do código
  2. No caso do log4j e outros, o destino das mensagens pode ser manipulado em tempo de execução, o que representa um risco de segurança

A melhor abordagem é a utilizada por produtos como o Guardium, que interceptam e gravam em um banco de dados separado todo o tráfego SQL entre sua aplicação e o banco. Como não é todo mundo que tem “bala na agulha” para bancar uma solução destas, uma alternativa viável é vc. utilizar AOP ou criar um “proxy driver” que intercepte as chamadas JCBC e armazene a informação “bruta” dos comandos executados em uma base distinta da utilizada pela aplicação. A partir dos dados brutos, vc. criaria um pós-processador para obter as informações gerenciais necessárias.

U

Não, não, não é bem por aí.
Não são todas as requisições ao banco que precisam ser monitoradas. Não precisa dessa trilha, como vc chamou.
Na verdade, depende sim da inserção de chamadas nos pontos corretos do código. São operações bem pontuais que seriam registradas.

A aplicação precisa registrar quando um determinado recurso foi consumido. Na prática, toda vez que um Vídeo for requisitado para exibição, deve-se salvar no banco a data e hora dessa requisição, qual Vídeo foi requisitado e por quem, que é o usuário logado.

A aplicação é Web, MVC, sem muito espaço para AOP, na minha humilde opinião. (Até porque não trabalho com AOP :wink:
Penso em criar um logger específico com um JDBCAppender. Ou mesmo uma utilizar um POJO que amarre essas informações e salve via JDBC mesmo…

O que me dizem??

P

Bem, isto, para mim, caracteriza uma trilha de auditoria ;^) A questão básica é se o log será utilizado para fins de negócio ou não. Se for, mantenho minha opinião: log4j e assemelhados não são adequados - que não quer dizer que não possam ser utilizados, é claro.

AOP é mais simples de implementar do que parece, e evita ter que depender da boa vontade do programador em inserir as chamadas nos pontos corretos do código. Se há uma aplicação em que AOP vale a pena é justamente o seu cenário.

Note que um filtro (servlet filter) não deixa de ser uma implementação do conceito de AOP. Se sua aplicação possui urls específicas em que o download efetuado, vc. já tem o “pointcut” (no caso uma URI) para inserir o código que vai logar o acesso.

U

Hmmm… interessante, isso. Vou dar uma olhada em AOP, fiquei curioso.
Mas pra esse projeto não vai dar tempo.

Ah, outra coisa, também não tinha pensado nessa abordagem de um servlet fitler. O ‘pointcut’ seria mapeado via código, e não via URL.
O método que faz o download, chamaria um método que geraria esse registro.

Bom, uma coisa. Mapeando via URL me parece que a o registro não faz parte da lógica de negócio, ou seja, eu posso não usar mais esse Filter e o download continuar disponível. Mapeando esse ‘pointcut’ via código, eu teria o registro como parte da lógica de negócio, bem como todas as outras operações, etc. Ou seja, sem o registro, não há download!

Ou esse pensamento é errado??

[]s

P

Bom, uma coisa. Mapeando via URL me parece que a o registro não faz parte da lógica de negócio, ou seja, eu posso não usar mais esse Filter e o download continuar disponível. Mapeando esse ‘pointcut’ via código, eu teria o registro como parte da lógica de negócio, bem como todas as outras operações, etc. Ou seja, sem o registro, não há download!

Ou esse pensamento é errado??

[]s

Se eu entendi direito, no seu caso o registro do download faz parte da regra de negócio, e este é o motivo básico de minha restrição ao uso de um mecanismo mais voltado para aspectos operacionais, como é o log4j.

Uma forma de escrever este requisito é “qualquer ação de download deve ser registrada em uma tabela específica”. Note o “qualquer”: ele é uma dica de que este é um requisito que deve ser aplicado à aplicação como um todo ou, em outras palavras, um “crosscut aspect” - daí minha recomendação de se utilizar o AOP.

Dado que vc. não tem tempo para se aventurar nisto, o filtro provavelmente lhe atenderá, mesmo que, no fim das contas, vc. use o log4j no mesmo. O ponto fundamental é evitar que, se amanhã vc. mudar por algum motivo a lógica de download, o registro não “escape” ou, no mínimo, seja simples de agregar.

Criado 9 de junho de 2008
Ultima resposta 12 de jun. de 2008
Respostas 12
Participantes 4