Como criar log de ações do usuário numa aplicação?

4 respostas
T

Olá.

Recentemente surgiu uma demanda aqui para criar logs de rastreio de ações do usuário.

Exemplos hipotéticos:

O administrador [email removido] bloqueou o usuário [email removido] O moderador
[email removido] alterou o limite de [email removido] de 400 para 1200.

Nos exemplos hipotéticos, demonstrei casos muito simples, mas ao modificar uma entidade qualquer, pode ser necessário mostrar também todos os campos que foram alterados.

Como isto é comumente feito? É uma string literal salva no banco? Existe algum padrão para implementar tal coisa?

4 Respostas

E

Veja o Log4j
Como mostra o site do projeto, você pode salvar os logs onde quiser e da forma que desejar, caso queria customizar, eh claro.

T

Amigo, agradeço a intenção. Aqui já usamos o Serilog.

A questão não é emitir log em string simples, mas sim ter um rastreamento das ações e dos dados que o usuário alterou.

Praticamente um “antes” e “depois” da alteração, mas sem ter que montar uma string, checando propriedade a propriedade pra saber se foi alterada pra então montar o log.

De forma geral, acredito que não haja um padrão para isto, por hora vou me contentar em gravar logs em string + informações adicionais, talvez serializar a entidade em campos como “oldValue” and “newValue”.

J

Pela minha experiência em grandes empresas, os DBAs costumam usar triggers. Assim é mais seguro, temos o log garantido independente de qual aplicação ou ferramenta que tenham acessado o banco.

Abaixo exemplo em SQL Server, com a instrução FOR XML PATH podemos sem esforço gravar o antes e depois de toda a linha em XML. Outros bancos nao tenho exemplo.

CREATE TRIGGER TR_TABELA on TABELA
for INSERT, UPDATE, DELETE 
AS
BEGIN
	SET NOCOUNT ON;

	IF NOT EXISTS(SELECT 1 FROM deleted) AND NOT EXISTS(SELECT 1 FROM inserted) 
		RETURN;

	declare @tablename varchar(100)
	SELECT @tablename = OBJECT_NAME(parent_object_id) 
	FROM sys.objects 
	WHERE sys.objects.name = OBJECT_NAME(@@PROCID)

	DECLARE @ActionType char(1)
	IF EXISTS (SELECT * FROM inserted)
		   IF EXISTS (SELECT * FROM deleted)
				   SELECT @ActionType = 'U'
		   ELSE
				   SELECT @ActionType = 'I'
	ELSE
		   SELECT @ActionType = 'D'

	declare @inserted xml, @deleted xml 
	SET @inserted = (SELECT * FROM inserted FOR XML PATH)
	SET @deleted = (SELECT * FROM deleted FOR XML PATH)

	INSERT INTO LOG
		(NOME_TABELA, ACAO, USUARIO, HOST, XML_ANTES, XML_DEPOIS)
	VALUES 
		(@tablename, @ActionType, SUSER_SNAME(), HOST_NAME(),@deleted, @inserted)
END
E

Entendi. Isso é chamado “auditoria” em alguns lugares.

Se você usa JPA, o Hibernate tem esse recurso automático. Caso não usar, tens que implementar manualmente.

Isso é feito salvando Strings no banco mesmo, na mesma transação que alterou o registro. Um objeto pode ter sua versão 1,2,3 etc… com detalhes da alteração, e até com o objeto inteiro duplicado coma informação antiga.
Você pode normalizar as tabelas da forma que desejar, usando associações, caso queira economizar recursos. Porém tens que ter equilíbrio nessa decisão para manter a performance (se isso for um problema).
Basicamente você pode fazer o que quiser para atender os requisitos.

Criado 13 de abril de 2022
Ultima resposta 14 de abr. de 2022
Respostas 4
Participantes 3