0

Context: A specific kind of sObject which is the detail in a master-detail relationship is getting mysteriously deleted across a number of different Master records.

I have been trying to narrow the variables down, but it would be great if I could assign a continuous log (beyond just a 24 hour allotment) that could show me all DML statements run against all records, and the users that triggered it.

Is something like this possible?

  • 1
    can you inspect the recycle bin? that would identify user – cropredy Apr 23 '16 at 5:59
  • 1
    It would be fairly simple to write an after delete trigger if you don't find anything out of the box. – Adrian Larson Apr 23 '16 at 6:00
  • 1
    Delete of master records would cascade delete the details and there would be no trace of their deletion. Adrian's suggestion would work if somewhere there is an explicit DML delete of the detail or you extended the trigger to include deletes of the master. – cropredy Apr 24 '16 at 4:17
  • 1
    GPP -- you're going to need to have each sobject-of-interest's after delete trigger do DML to some custom Log__c object using the values in Trigger.old – cropredy Apr 26 '16 at 0:53
  • 1
    Yes, that is correct; there is no way to 'subscribe' to DML events so each sobject you care about tracking will need to do the logging explicitly - of course, do the logging through a utility class/method that is simply passed trigger.old – cropredy Apr 26 '16 at 0:56
2

Custom object for logging

DML_Log__c with fields:

  • SObjectType__c (type = Text)
  • Name__c (type = Text)
  • ID__c (type = text)
  • RecordTypeId__c (type = Text)

Utility method

public static void logDmlDelete(Sobject[] sObjList) {
    DML_Log__c[] logInsList = new List<DML_Log__c>();
    for (Sobject sobj : sobjList)
       logInsList.add(new DML_Log__c(
                       sobjectType__c = sobj.getSobjectType().getDescribe().getName(),               
                       name__c = (String) sobj.get('name'),
                       id__c = (String) sobj.get('ID'),
                       recordtypeId__c = sobj.getSobjectType().getDescribe().getRecordTypeInfos().size() <= 1  // master recordtype will exist in describe even if no others 
                                        ? null
                                        : (String) sobj.get('recordtypeId') 
                                 ));

    insert logInsList; 
}

Trigger on Foo__c

trigger fooDelete on foo__c on (after delete) {
  ... other stuff
  Util.logDmlDelete(Trigger.old);
}

Notes:

  1. Assumes that the sobject has a Name field
  2. Logs only the name field and sobject type; implicitly created by user = user doing the deletes
  • wow, this is super baller, thanks! What does Foo__c represent in this case? The custom object being logged? – GPP Apr 26 '16 at 2:39
  • 1
    @GPP -- sorry, typo in the trigger definition; yes - Foo__c is the object being logged; you'd need similar ones for each sobject you are trying to log – cropredy Apr 26 '16 at 14:25
  • 1
    @GPP Yes - the name of the sobject - so the log can record dml events on many sobjects using a single field – cropredy Apr 26 '16 at 18:08
  • 1
    @GPP put the method inside a class called Util - that was my intent; I assumed you already had a Util-type class in your system – cropredy Apr 26 '16 at 21:26
  • 1
    Let us continue this discussion in chat. – cropredy Apr 27 '16 at 5:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.