Making Every Field and Audit Field (Implications?)

I’m having an issue where a client wants a report on every change to every field. I know that’s not possible out of the box. I was thinking about the audit log. However that means making every single field in every module an “audit” field. (Their projects module has like 100 custom fields! alone). I’m thinking this would be disasterous for speed on record save and also quite quickly grow the datbase to an unamanageable size.

Anyone ever done anything like this? Issues? Problems? Ideas?

Probably would be a smart idea to implement a logic hook which checks the fields that are changed and creates a bulk insert query in the audit log table

Skip the fields that have audited checked to avoid duplicate inserts ( or uncheck audited for every field

1 Like

Maybe you can set workflow on your 100 fields and it will send an email to users. :thinking:

Any change option

Sounds doable but Id have to do that for every module. A hook for each.

You can do a global hook that will run on all modules and then maybe the thing you need to think about is filtering out certain modules that you don’t want to run on. Like background admin modules for example or you could just check for modules that have audit enabled

What would be an example of global hooks? I’m familiar with module hooks, like before save or after save etc, but I don’t see any application level hooks that do this. What were you thinking?

In custom/modules/logic_hooks.php you can also create before and after save hooks. I would say those will be called on the save for all modules. Don’t have the time to test it rn but i think I’ve done something similar in the past

There’s already some after_save hooks on this file (For ElasticSearch indexation for example). So it should work fine

$hook_array['after_save'] = Array(); 
$hook_array['after_save'][] = Array(1, 'AOD Index Changes', 'modules/AOD_Index/AOD_LogicHooks.php','AOD_LogicHooks', 'saveModuleChanges'); 
$hook_array['after_save'][] = Array(1, 'ElasticSearch Index Changes', 'lib/Search/ElasticSearch/ElasticSearchHooks.php','SuiteCRM\Search\ElasticSearch\ElasticSearchHooks', 'beanSaved'); 
$hook_array['after_save'][] = Array(30, 'popup_select', 'modules/SecurityGroups/AssignGroups.php','AssignGroups', 'popup_select'); 

I just tried at my local development system. It is working to have audits for every field of every module. The code is not thoroughly tested but creates entries in the audit tables and shows on audit screens.

  1. Made a logic entry in the custom/modules/logic_hooks.php with this
    $hook_array['after_save'][] = Array(1, 'Log_Change', 'custom/modules/AllModulesLog.php','AllModulesLog', 'updateAudit');
  2. Added a class file at custom/modules/AllModulesLog.php with the following
    code
<?php

if(!defined('sugarEntry') || !sugarEntry){
	die('Not a valid entry');
}

class AllModulesLog{
	
	public function updateAudit(SugarBean $bean, $event,$args){
		global $db;
		if(!empty($bean->fetched_row)){		
			
			$changed_fields = array();
			foreach ($bean->field_defs as $field => $properties){
				if (isset($bean->$field) && $bean->fetched_row[$field] != $bean->$field) {
					$changed_fields[$field] = $properties;
				}
			}

			$bean->audit_enabled_fields = array();
			$auditDataChanges = $db->getDataChanges($bean, array_keys($changed_fields));
			if (!empty($auditDataChanges)){
			
				foreach ($auditDataChanges as $change) {
					$db->save_audit_records($bean, $change);
					$bean->fetched_row[$change['field_name']] = $change['after'];
				}
				$bean->createdAuditRecords = true;
			}
		}
	}
}

Tested for few fields on accounts, contacts , opportunities modules. I am not sure about the performance. May be we can have a config value in config_override.php to enable/disable the entire module fields audit.

3 Likes

Hello Paul,

what’s the business requirement behind it, if I may ask?
I had something similar before in a project - the target was time series reporting + trend reporting.

What I’ve done was simply to trigger on all updates and take the whole bean and store it inside a MongoDB.
That has the huge advantage, that the schema is flexible (even if there are field changes in the CRM later on) and the whole reporting was run on the Mongo / DWH.

Alternatively, I’ve had another project where we just use Suite with plenty (not all, but plenty) of audited fields and there we have issues with huge DB table sizes, backups are incredibly slow, Restore over the network practically impossible with several hours downtime etc.

Nice thank you, lots of good ideas here.

I did not know you could put a module level hook in main module directory and it applies to all modules! I always learn something new.