AUDITORIA DO SISTEMA..

 Tópico anterior Próximo tópico Novo tópico

AUDITORIA DO SISTEMA..

VB.NET

 Compartilhe  Compartilhe  Compartilhe
#497516 - 14/07/2021 14:28:33

FERDEAD
LIMEIRA
Cadast. em:Outubro/2004


Olá pessoal..

gostaria de fazer uma função no meu sistema, onde eu gravasse quem alterou o que..

por exemplo, no meu cadastro de produtos,  o usuario 'nome' alterou o valor de venda do produto 'produto teste' de '2,00' para '3,00'..

qual seria a melhor forma de fazer isso?
lembrando que o cadastro de produtos possui uma infinidade de campos, não gostaria de ficar fazendo comparações lógicas de campo por campo.. existe alguma coisa que faça isso de forma mais automatizada?



#497517 - 14/07/2021 15:06:32

MARCOSFSAN
SAO PAULO
Cadast. em:Setembro/2009


Crie uma trigger que grava os dados que estavam a antes em uma tabela de LOG e com as informações que vc precisa (data, usuario etc)

Marcos


#497518 - 14/07/2021 15:22:48

KERPLUNK
RIO GRANDE DO SUL
Cadast. em:Junho/2009


Membro da equipe
Aqui entra mais uma vez OOP. Quando faço o CRUD(seja um artesanal, usando ORM ou qualquer outro método), o método de gravação é sempre genérico. Isso faz com que toda e qualquer gravação de dados(seja inserção ou alteração), vai cair no mesmo método, contendo os dados. Para criar uma auditoria de dados, geralmente implemento uma interface 'Original Object', que contêm os dados do objeto ao ser aberto. Ele simplesmente contêm uma serialização do objeto ao ser instanciado. Aí faço as alterações que quero no objeto(o que não altera a propriedade contendo os dados originais) e ao salvar, gravo numa tabela de log o objeto original(se contiver, pois em caso de inserção ele é nulo) e os dados após alterações. Como o método de gravação é sempre o mesmo, o procedimento para saber quem é o usuário eu busco do contexto da chamada(sempre faço uma WebAPI). Assim, tenho o objeto original, vindo do banco sem alterações, o objeto alterado e o usuário, além da data e hora.
Tenho sempre um 'liga/desliga' dessa operação toda, que é simplesmente uma variável setada nas configurações do serviço, já que isso consome bastante recursos e pode causar lentidão. Além disso, ele pode ficar MUITO grande. Ao ponto de criar uma segunda API onde simplesmente envio os dados, ela grava em um banco separado da aplicação principal e em alguns casos(quando é MUITO dado), eu uso compressão de string ao gravar no banco de log.

Em resumo, não é tarefa simples e depende muito do seu sistema estar bem estruturado.

Existem também algumas técnicas no próprio banco de dados que permitem criar isso, mas na real eu não recomendo, já tive problemas sérios com isso, que chegaram até a resultar na perda de dados.

_______________________________________________________________________
Virei Orculo!
The end is nigh, be ready for the nukes!


#497521 - 14/07/2021 16:14:21

FERDEAD
LIMEIRA
Cadast. em:Outubro/2004


Kerplunk,

Eu tenho um objeto serializado do meu cadastro de produtos.. e um método de inserir/alterar que faz por SQL..

agora só não sei comparar esses objetos.. o que veio do banco com o que o usuário alterou..

vc conseguiria me mostrar um código de exemplo que faça isso?




#497522 - 14/07/2021 16:59:29

MESTRE
GUARULHOS
Cadast. em:Novembro/2013


Última edição em 14/07/2021 17:06:58 por MESTRE

Faço por trigger no banco de dados conforme o @MARCOSFSAN falou, tinha problema com isso.. os usuários falavam que não faziam as coisas maior BO aqui depois que implantei os logs
em algumas tabelas principais parou a ladainha de falar que não fez e etc.. fulano nem vem mais na minha mesa falar, tem gente que vem até na mesa perguntar o que aconteceu com o pedido..

Dupliquei a estrutura da tabela de : pedidos,pedidos-itens para pedidos_log,pedidos-itens_log..

Depois criei uma Trigger para as principais After insert e After update no After insert 'Inseriu item de pedido' no After update 'Alterou item do pedido'.

Lembrando que voce pode usar e brincar com NEW ou OLD nos campos

EX:
  CREATE
    /*!50017 DEFINER = 'sistema'@'%' */
    TRIGGER `triggerlogpedido` AFTER UPDATE ON `pedidos`
    FOR EACH ROW BEGIN
    INSERT INTO exemplo_log(codigo,acao,nome,evento_log VALUES(NEW.codigo,NEW.acao,NEW.nome,'ATUALIZOU');
    END;
$$


Fora que é banco né?? ele sozinho faz isso sem dor de cabeça voce pode fazer um EVENT que roda toda semana, 1x ao ano 00h01 que aciona um Stored Procedure no qual trata de fazer um calculo basico exemplo: dataAtual - 6 months eai depois da um Delete nos log's antigos que voce não precisa aí o céu é o limite da criatividade das Gambiarra KKKKKK  

Obs: Uso MySQL aqui. e isso me poupou bastante tempo com miseras 2 linhas rs.

_______________________________________________
[]A alegria est na luta, na tentativa, no sofrimento envolvido e no na vitria propriamente dita.[]
Gandhi.


#497523 - 14/07/2021 17:35:49

CLEVERTON
SERRINHA
Cadast. em:Dezembro/2003


Membro da equipe
KERPLUNK
Aproveitando o ganho do tópico AUDITORIA DO SISTEMA..

Eu já pensei em criar a seguinte Estrutura nas tabelas para fazer esse esquema de auditoria proposto no tópico.  (exemplo/analogia abaixo)

ClienteId
ClienteIdRoot
(campos)
UsuarioId
DataHora
StatusRegistroId (Ativo, Alterado, Incluido, Deletado)

Usando um método genérico pra gravação, eu pensei em sempre Manter o ClienteIdRoot sendo igual ao ClienteId do primeiro registro criado.
Sendo assim eu conseguiria saber que o Cliente João  já foi João da Silva ou João da Silva Oliveira

Mesmo que o eu lance o ClienteId na tabela de Vendas, eu sempre vou me basear no momento da relação por ClienteIdRoot para saber que se trata da mesma pessoa.

O que vc acha sobre esse formato para auditoria?  




#497524 - 14/07/2021 17:49:50

KERPLUNK
RIO GRANDE DO SUL
Cadast. em:Junho/2009


Membro da equipe
Citação:
:
Kerplunk,

Eu tenho um objeto serializado do meu cadastro de produtos.. e um método de inserir/alterar que faz por SQL..

agora só não sei comparar esses objetos.. o que veio do banco com o que o usuário alterou..

vc conseguiria me mostrar um código de exemplo que faça isso?

Assim como você serializa, você também desserializa. Você pode comparar objetos com algum ObjectComparer
Posso fazer um exemplo pra mostrar, mas pode demorar um tempinho. Mas você pode usar como base os exemplos que tenho nos vídeos de OOP no meu canal.


_______________________________________________________________________
Virei Orculo!
The end is nigh, be ready for the nukes!


#497525 - 14/07/2021 17:58:39

KERPLUNK
RIO GRANDE DO SUL
Cadast. em:Junho/2009


Membro da equipe
Citação:
:
KERPLUNK
Aproveitando o ganho do tópico AUDITORIA DO SISTEMA..

Eu já pensei em criar a seguinte Estrutura nas tabelas para fazer esse esquema de auditoria proposto no tópico.  (exemplo/analogia abaixo)

ClienteId
ClienteIdRoot
(campos)
UsuarioId
DataHora
StatusRegistroId (Ativo, Alterado, Incluido, Deletado)

Usando um método genérico pra gravação, eu pensei em sempre Manter o ClienteIdRoot sendo igual ao ClienteId do primeiro registro criado.
Sendo assim eu conseguiria saber que o Cliente João  já foi João da Silva ou João da Silva Oliveira

Mesmo que o eu lance o ClienteId na tabela de Vendas, eu sempre vou me basear no momento da relação por ClienteIdRoot para saber que se trata da mesma pessoa.

O que vc acha sobre esse formato para auditoria?  

Isso resultaria em uma auditoria específica de um objeto, que você teria que replicar para outros, como produtos, fornecedores...
Como uso GUID como tipo de dados de identificadores e não inteiros, a tabela de log pode conter um campo ID, que gravaria o ID específico do registro, além de tipo de objeto para poder desserializar.
A tabela completa fica:
ID - GUID - PK: Id do registro de Log
Object - VARCHAR: Tipo de objeto para desserializar(que uso reflection em uma classe genérica para tipar)
RecordId - GUID: Id do registro inserido/alterado/excluído
Original - VARCHAR - Nullable: JSON dos dados do objeto original
Updated - VARCHAR - Nullable: JSON dos dados alterados
TimeStamp - DateTime/Timestamp: A hora em que foi feita a alteração
User - GUID: Id do usuário fazendo a gravação
ContextData - VARCHAR - Nullable: Aqui, posso gravar os dados de contexto, é opcional

A vantagem principal de ID's sendo GUID é que eles são únicos no sistema todo. Jamais vai haver dois GUID's iguais(tecnicamente é possível, mas as chances de isso acontecer são maiores de 1 em um trilhão). Então se procurar no log por um Id específico, vai constar tudo que foi feito com esse registro, não importando o tipo de dados(entidade).

_______________________________________________________________________
Virei Orculo!
The end is nigh, be ready for the nukes!


#497527 - 15/07/2021 08:47:53

CLEVERTON
SERRINHA
Cadast. em:Dezembro/2003


Membro da equipe
Citação:
Isso resultaria em uma auditoria específica de um objeto, que você teria que replicar para outros, como produtos, fornecedores...
Como uso GUID como tipo de dados de identificadores e não inteiros, a tabela de log pode conter um campo ID, que gravaria o ID específico do registro, além de tipo de objeto para poder desserializar.
A tabela completa fica: ......     não importando o tipo de dados(entidade).


KERPLUNK

é uma estratégia bem interessante viu. gostei muito, vou adotar, sem falar que é bem menos trabalhosa de implementar.
Muito obrigado, mais uma vez.



#497528 - 15/07/2021 10:36:33

KERPLUNK
RIO GRANDE DO SUL
Cadast. em:Junho/2009


Membro da equipe
Nesse caso, sugiro também uma WebAPI e um banco separado pra isso.

_______________________________________________________________________
Virei Orculo!
The end is nigh, be ready for the nukes!


#497533 - 16/07/2021 07:56:56

MRSILVA
MARINGA
Cadast. em:Julho/2015


Última edição em 16/07/2021 07:58:08 por MRSILVA

Olá.
Muito bom esse tópico.

Queria expor a forma que estou fazendo meus log para avaliação dos mais experientes e talvez seja uma idéia para quem precisa implementar.

Tenho um projeto Blazor WebAssembly e uma WEBAPI, na aplicação Blazor tenho componentes que são input de dados cada input trata de um tipo de dados, só pelos nomes vocês irão entender (InputString, InputInt, InputDecimal, SelectString .....)  meus modelos de dados que serão gravados no banco de dados herdam de uma classe base uma propriedade chamada ListLog, essa propriedade é uma lista de uma classe que tem as propriedades (Id, IdLog, IdUsuario PropriedadeAlterada, Tabela, ValorAntigo, DataAlteracao) (claro que não utilizo esses nomes kkk) meus componentes que citei acima consegue informar para modelo de dados que houve uma alteração e adiciona um log de alteração do campo especifico, isso ocorre somente quando estou fazendo uma alteração.  Quando envio os dados para WebApi  no caso de uma alteração percorro minha lista de log e faço as alterações somente nos campos que houveram alteração de fato, utilizo reflection para isso, verifico se os campos realmente foram alterados e gravo o valor antigo na propriedade ValorAntigo, tabela, Id do registro  e o Id do Usuário que pego essa informação do próprio contexto da chamada. Depois que fiz todas as alterações faço um SaveChanges para salvar os dados do meu modelo e outro SaveChanges para salvar meu log utilizo um contexto diferente para o log,  no momento tenho uma tabela no mesmo banco de dados para o log mas se quiser colocar em um banco de dados diferente é muito fácil fazer a alteração porque utilizo contextos diferentes.

Dessa forma é possível fazer auditoria de todas as alterações ocorridas e consigo buscar essas informações através dos campos IdLog e nome da tabela.

Tudo isso criei apenas uma única vez tenho apenas um único método que vale para minha aplicação inteira inclusive o método que faz a alteração.

Kerplunk se tenho contexto diferente para a tabela log você acha necessário criar uma API somente para gravar o log?.

Desde já agradeço.




 Tópico anterior Próximo tópico Novo tópico


Para responder este tópico o login é requerido
Se você já possui uma conta de usuário por favor faça seu login
Se você não possui uma conta de usuário use a opção Criar usuário