Loggeando las actividades de Odoo con SQL

17 de diciembre de 2023 por
Gustavo Orrillo
| Sin comentarios aún
 

Este es el post que debería titularse "Porque es bueno saber Postgresql" ya que el conocimiento de las capacidades de esta formidable base de datos, nos permite resolver problemas que de otra manera serían muy dificiles de hacer, por ejemplo loggear los INSERT y UPDATEs a Odoo.

Muchas veces es necesario auditar las modificaciones que se van haciendo a los diferentes objetos de Odoo. Para ello podemos utilizar el módulo auditlog de OCA, el cual hace el trabajo para ser honesto. Tiene un gran drama, utiliza el ORM por ende termina siendo un ancla en términos de performance. El otro problema es, uno tiene que declarar todos los objetos que va a auditar, lo cual a veces no puede ser del todo práctico.

Otra opción es loggear los cambios a la base de datos utilizando triggers. Que es un trigger? es un procedimiento que se ejecuta cuando se inserta, actualiza o borra un registro de la base de datos (un buen ejemplo es actualizar un campo many2one cuando se actualiza un registro, de esta manera no tendriamos que hacer que el campo sea computado y seria mucho mas rápida la actualización debido a que salteamos el ORM).

Lo que vamos a hacer es, en cada tabla que querramos auditar vamos a crear un trigger que va a invocar una función de Python (no es maravilloso PostgreSQL?) que va a actualizar una tabla, la cual vamos a poder ver mediante Odoo. Dicha tabla la creamos con el módulo data-logger (el cual no tiene grandes secretos, solo crea el modelo y el menu con vista correspondiente).


No es del todo user friendly pero hace el trabajo que uno necesita hacer.

Bien, ahora vamos a capturar los cambios en la base de datos y crear los triggers correspondientes. Primero debemos asegurarnos que tenemos Python instalado en la base de datos, para ello creamos la extension plpython3u

create extension plpython3u;

Y luego creamos la función que va a loggear cada uno de los cambios. Los contenidos de la funcion son los siguientes:

create or replace function py_logger()
returns trigger as $$
# if int(TD['new']['id'])%2 == 0:
tx_id = plpy.execute('SELECT txid_current() AS tx_id')[0]['tx_id']
table_name = TD.get('table_name')
event = TD.get('event')
old_content = TD.get('old') and str(TD.get('old')) or ''
if old_content != '':
create_date = TD.get('old').get('create_date')
res_id = TD.get('old').get('id')
create_uid = TD.get('old').get('create_uid')
else:
create_date = TD.get('new').get('create_date')
res_id = TD.get('new').get('id')
create_uid = TD.get('new').get('create_uid')
new_content = TD.get('new') and str(TD.get('new')) or ''
model_name = table_name.replace('_','.')
model_id = plpy.execute("SELECT id AS model_id from ir_model where model = '%s'"%(model_name))[0]['model_id']
qty = plpy.execute("SELECT COUNT(*) AS qty FROM DATA_LOGGER WHERE EVENT = '%s' and TX_ID = %s"%(TD.get('event'),tx_id))[0]['qty']
if qty == 0:
#sql_statement = 'INSERT INTO data_logger(table_name,event,old_content,new_content) VALUES ("%s","%s","%s","%s")'%(table_name,event,old_content,new_content)
sql = plpy.prepare(""" INSERT INTO data_logger(table_name, event, old_content, new_content, model_id, create_date, res_id, tx_id, create_uid) values ($1, $2, $3, $4, $5, $6, $7, $8
, $9); """,\
("TEXT", "TEXT", "TEXT", "TEXT", "INTEGER", "TIMESTAMP","INTEGER","INTEGER","INTEGER"))
#sql = plpy.prepare(sql_statement)
ss = plpy.execute(sql, (TD['table_name'], TD['event'],TD['old'], TD['new'], model_id, create_date, res_id, tx_id, create_uid))
#ss = plpy.execute(sql)
$$ language plpython3u;

En dicha función capturamos la operación (evento), e insertamos la informacion necesaria en el modelo data.logger. Por último, para cada tabla que necesitemos auditar creamos el trigger correspondiente; por ejemplo si queremos auditar product_template

create trigger logger_product_template after insert or update on product_template for each row execute procedure py_logger();

Como decía, no es del todo user-friendly pero la verdad hace el trabajo que tiene que hacer. Por lo pronto queria mostrar como hacer un logger con SQL y de paso introducir funcionalidades como trigger y funciones de Python dentro de PostgreSQL

Gustavo Orrillo 17 de diciembre de 2023
Compartir
Archivar
Identificarse dejar un comentario