1

I'm enquiring about best practices for storing Apex trigger execution failures in Salesforce for post-mortem analysis. The basic requirements are:

  • provide link back to the object instance that failed the trigger
  • field to log failure stack trace information
  • track logged in Salesforce user
  • (bonus) ability to provide editable fields on the created records (e.g. checkbox to track error resolution status)
  • ability to apply permissions on who can view the error listing -- however, the trigger should be able to create the error log record regardless of whether the user can view the errors or not.

Background/Details

I have a Salesforce package that

  • adds Apex triggers to the Contact create/update operations
  • additional metadata (custom settings) which define an HTTP endpoint.

Whenever the trigger is fired, Contact information is POSTed to the URL. If the trigger execution fails, a Chatter message is sent to a prescribed Chatter group. Using this mechanism we are able to record:

  • the Chatter failure message
  • a link to the object that failed to integrated

A sample Chatter failure message is shown below

enter image description here

However, we've encountered a number of challenges from a setup / design perspective:

  • The Chatter group cannot be made public so it has been configured as private. However, this makes it necessary for the system admin to add every single Salesforce user who updates Contact objects to the Chatter group. Failure message do not get posted for any members who are not part of the group
  • Metadata configuration is required at the package-level which stores the name of the specific Chatter group to which messages should be posted.
  • Chatter messages are unstructured so all needed information must be included in the message body.

My questions are

  • Is there a better way of capturing this error information in Salesforce, i.e. an entity type better suited to capture this information?
  • If a custom object is the way to go, is there a way of linking back to, e.g., the Contact object that failed the trigger without creating an integrity constraint, i.e. the Contact object that failed the trigger should still be deletable from Salesforce, even though it's related error messages may be retained.
2

Is there a better way of capturing this error information in Salesforce, i.e. an entity type better suited to capture this information?

Yes: a Custom Object. Your application can then apply all of the standard security features on the object, while allowing your Apex to insert records in the object and choose to ignore FLS/CRUD for logging purposes.

If a custom object is the way to go, is there a way of linking back to, e.g., the Contact object that failed the trigger without creating an integrity constraint, i.e. the Contact object that failed the trigger should still be deletable from Salesforce, even though it's related error messages may be retained.

Yes, store the Contact Id in a text field. Use a HYPERLINK() formula to link to the Contact instead of an actual relationship field.

Consider, however, exploring established error-logging frameworks rather than reinventing the wheel. Robert Soesemann has one based on platform events, for example.

4
  • I'm considering something simpler: a custom text (text area?) field on a Contact to store the latest error message pertaining to a Contact ... that would still allow users to see contacts that have errored (the trigger could be set up to clear the field when the trigger succeeds). Basically, it's not as important to see a historical log of all errors (though that's what's currently implemented) but more important to be able to fetch the list of contacts that have failed triggers and see the latest failure message tied to each contact. Thoughts? – Omair Inam Sep 2 '20 at 19:24
  • If you update a Contact will you cause infinite recursion when you try to sync it again? – David Reed Sep 2 '20 at 19:26
  • Good point! This was a concern. However, the trigger implementation already has safeguards in place to prevent infinite recursion... the existing trigger logic invokes a callout which uses a SOQL query to refetch the contacts .. and it updates custom Contact fields tracking audit information (update status, last integration attempt time) ... we'd be updating one additional field. – Omair Inam Sep 2 '20 at 19:56
  • In that case I do not have a strong opinion – David Reed Sep 2 '20 at 20:12

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