Log de Auditoria Assíncrono

Pessoal, preciso desenvolver uma rotina genérica que toda funcionalidade acessada pelo usuário logado no site seja gravada numa base dados de uma maneira assíncrona, pois o tempo de gravar esse log não pode ser somado ao tempo da action !!!

O site é desenvolvido com Struts 1.

Alguém sabe me dizer quais as opções que tenho ?

Grato.

até onde conheço não tem como, o que pode fazer é uma Thread

[quote=marceloplis]Pessoal, preciso desenvolver uma rotina genérica que toda funcionalidade acessada pelo usuário logado no site seja gravada numa base dados de uma maneira assíncrona, pois o tempo de gravar esse log não pode ser somado ao tempo da action !!!

O site é desenvolvido com Struts 1.

Alguém sabe me dizer quais as opções que tenho ?

Grato.[/quote]

Vc não vai querer fazer isso. O registro da auditoria e o registro normal têm que acontecer na mesma transação. O que significa que não pode ser assincrono.

[quote=sergiotaborda][quote=marceloplis]Pessoal, preciso desenvolver uma rotina genérica que toda funcionalidade acessada pelo usuário logado no site seja gravada numa base dados de uma maneira assíncrona, pois o tempo de gravar esse log não pode ser somado ao tempo da action !!!

O site é desenvolvido com Struts 1.

Alguém sabe me dizer quais as opções que tenho ?

Grato.[/quote]

Vc não vai querer fazer isso. O registro da auditoria e o registro normal têm que acontecer na mesma transação. O que significa que não pode ser assincrono.[/quote]

Então, é que não seria bem uma auditoria, na verdade seria uma forma de saber qual é a trilha de navegação do usuário, pois queremos saber o que cada usuário mais acessa para fazer campanhas, por exemplo.

Teria que ser assíncrono, pois é algo que não pode impactar para o usuário, tanto por performance quanto por possíveis erros.

Valew.

Se você precisa usar esses dados para determinar a navegação do usuário, aconselho usar um arquivo-texto mesmo, não uma base de dados, até porque a quantidade de dados gerada será imensa.
Imprimir em um arquivo texto só é limitado pela velocidade do disco e não gasta nada de CPU; se precisar de uma base para fazer alguma análise, você pode carregar esse arquivo em um banco de dados separado (até na máquina de um desenvolvedor, por exemplo).
Não fique criando coisas assíncronas para log - em um sistema que temos rodando aqui, eu fiz o tal log assíncrono (em arquivo-texto, diga-se de passagem), mas isso pode gerar picos de utilização de memória.

[quote=bezier curve]Se você precisa usar esses dados para determinar a navegação do usuário, aconselho usar um arquivo-texto mesmo, não uma base de dados, até porque a quantidade de dados gerada será imensa.
Imprimir em um arquivo texto só é limitado pela velocidade do disco e não gasta nada de CPU; se precisar de uma base para fazer alguma análise, você pode carregar esse arquivo em um banco de dados separado (até na máquina de um desenvolvedor, por exemplo).
Não fique criando coisas assíncronas para log - em um sistema que temos rodando aqui, eu fiz o tal log assíncrono (em arquivo-texto, diga-se de passagem), mas isso pode gerar picos de utilização de memória.[/quote]

Você poderia descrever qual o fluxo dessa sua implementação ?

Uma dúvida… o tempo de IO de gravação em arquivo é MENOR do que em BD ?

Valew.

a) O tal “log assíncrono” que implementei é bem boboca: a ideia é que os métodos que precisam logar alguma coisa, em vez de escreverem diretamente no arquivo, ponham a string a ser logada em uma fila*. Essa fila, por sua vez, é consumida periodicamente por uma thread que grava os dados em arquivo. As complicações, é claro, aparecem quando você precisa ter logs rotacionados (ou seja, para o arquivo não ficar muito grande, a ideia é renomear o arquivo que ficou muito grande, fechá-lo, e abrir um outro arquivo. ). Há algumas sutilezas que podem aparecer quando, por exemplo, alguém usa algum utilitário para examinar o tal arquivo de log ENQUANTO a aplicação está funcionando.

b) Tem de ser, porque ao você ínserir alguma coisa em um banco de dados (e supondo que a tabela tenha uma chave primária, o que normalmente é verdade), os seguintes passos normalmente são efetuados pelo seu servidor de bancos de dados, e vários deles exigem acesso a disco (mesmo que “delayed”):

  1. O registro é gravado sequencialmente no log de transações (um arquivo basicamente sequencial, como o arquivo-texto que citei anteriormente);
  2. Quando o processo de “journaling” do seu banco de dados é efetuado, no final da transação, os dados são movidos do log de transações para a sua tabela, que normalmente é representada como uma b-tree**. Como você deve saber bem, uma b-tree é uma árvore balanceada em disco, e pode ser que, por algum motivo, seja necessário efetuar o “split” do nó que está sendo gravado, porque ele encheu. Isso quer dizer que uma simples gravação de um registro pode ocasionar vários acessos ao disco.
  3. Se a tabela tiver mais índices (o que é inevitável quando você quer usar a tabela para fazer análises e emitir relatórios), então os outros índices também têm de ser atualizados. Arquivos de índices normalmente também são representados como b-trees.
  • O pico de utilização de memória pode ocorrer, por exemplo, se a aplicação gera muitos dados durante muito tempo, de forma que você não consiga gravar tudo que está tentando ser logado em arquivo. Aí a fila vai crescer, crescer e crescer até que a aplicação fique mais ociosa.

** A menos que você especifique, no momento de criação de sua tabela, que você queira representá-la como uma tabela hash. Tabelas hash são de uso bem mais limitado, porque é necessário especificar o valor correto da chave para encontrar algo rapidamente e os registros não ficam “ordenados”.

Existe a possibilidade de se fazer esse log da trilha de navegação usando o Log4J ? e que ao invés de ele logar em arquivo, ele log na base de dados ?

O Log4J loga em base de dados se quiser (acho que é o JDBCAppender).

Entretanto, ele não é assíncrono.

A menos que seja absolutamente necessário, evite fazer tais logs em bancos de dados; use uma conexão separada se for o caso, e use “auto-commit” nessa conexão. Vou dar um exemplo bobo: digamos que você tenha iniciado uma transação em um determinado banco e além de inserir/atualizar dados em uma determinada tabela, você logue alguma coisa em outra tabela que esteja participando da mesma transação. Se ocorrer um rollback nessa transação, o log também será desfeito, ou seja, você não vai saber o que ocorreu de errado na transação.

[quote=bezier curve]O Log4J loga em base de dados se quiser (acho que é o JDBCAppender).

Entretanto, ele não é assíncrono.

A menos que seja absolutamente necessário, evite fazer tais logs em bancos de dados; use uma conexão separada se for o caso, e use “auto-commit” nessa conexão. Vou dar um exemplo bobo: digamos que você tenha iniciado uma transação em um determinado banco e além de inserir/atualizar dados em uma determinada tabela, você logue alguma coisa em outra tabela que esteja participando da mesma transação. Se ocorrer um rollback nessa transação, o log também será desfeito, ou seja, você não vai saber o que ocorreu de errado na transação. [/quote]

Pelo que andei pesquisando, acho que vou acabar optando pelo MDB mesmo… o meu custo seria só de montar e enviar a mensagem, já que isso tem que ser síncrono.

Que vc acha ?

Alguém tem mais a acrescentar ?

[quote=marceloplis][quote=bezier curve]O Log4J loga em base de dados se quiser (acho que é o JDBCAppender).

Entretanto, ele não é assíncrono.

A menos que seja absolutamente necessário, evite fazer tais logs em bancos de dados; use uma conexão separada se for o caso, e use “auto-commit” nessa conexão. Vou dar um exemplo bobo: digamos que você tenha iniciado uma transação em um determinado banco e além de inserir/atualizar dados em uma determinada tabela, você logue alguma coisa em outra tabela que esteja participando da mesma transação. Se ocorrer um rollback nessa transação, o log também será desfeito, ou seja, você não vai saber o que ocorreu de errado na transação. [/quote]

Pelo que andei pesquisando, acho que vou acabar optando pelo MDB mesmo… o meu custo seria só de montar e enviar a mensagem, já que isso tem que ser síncrono.

Que vc acha ?

Alguém tem mais a acrescentar ?[/quote]

Log4J sim é assincrono. Basta configurar direito.
Este framework é exatamente o que vc precisa. então estude-o e vai-lhe ser muito utill.

A mensagem do log4j não precisa ser uma string. vc pode mandar um objeto complexo. Ai vc precisa implementar um appender para escrever para o lugar certo.

O que vc precisa é chamado de estatistica de uso , não é auditoria.
Porque a estatistica é dependente de amostragem ela não precisa ser transacional e por isso o log4j caem que nem uma luva.
Só não se esqueça se colocar isso encapsulado num objeto de forma a não obrigar as camadas da aplicação a trabalharem diretamente com o log4j.

http://glueclue.blogspot.com/2007/01/log4j-asyncappender-is-not-always_31.html

[quote=sergiotaborda]

Log4J sim é assincrono. Basta configurar direito.
Este framework é exatamente o que vc precisa. então estude-o e vai-lhe ser muito utill.

A mensagem do log4j não precisa ser uma string. vc pode mandar um objeto complexo. Ai vc precisa implementar um appender para escrever para o lugar certo.

O que vc precisa é chamado de estatistica de uso , não é auditoria.
Porque a estatistica é dependente de amostragem ela não precisa ser transacional e por isso o log4j caem que nem uma luva.
Só não se esqueça se colocar isso encapsulado num objeto de forma a não obrigar as camadas da aplicação a trabalharem diretamente com o log4j.[/quote]

Você sabe onde encontro material de apoio com exemplos ? do tipo mandar objeto e escrevê-lo no BD da maneira que achar melhor?

Grato.