Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

I currently have a trigger which sometimes fails when new information is inserted from a 3rd party system. I can't simply check the logs as it usually happens during the night and it's not easy to spot the reason (pretty complicated code). Therefore I tried to add some enhanced debugging which stores valuable information into a custom object and then inserts this into the database.

This unfortunately only works if I catch the exception. As I would prefer the system to still throw an exception if such a weird situation happens I search for a way to store my debug for later research.

I already tried with @future but even these methods do not get called if I have an exception in the trigger.

Any ideas how I can log data from a trigger for later inspection although the trigger throws an exception?

share|improve this question
    
did you try maybe to send an email from within the catch? with the data you need? –  Saariko Sep 18 '12 at 12:12

5 Answers 5

up vote 11 down vote accepted

As you've noticed if an apex script throws an unhandled exception everything it did is rolled back: @future, emails, DML, etc.

The good news is that there is a way to prevent a DML operation from succeeding without causing the whole apex transaction to be rolled back (except in the specific case mentioned below): the sObject.addError method. If you call this method on every sObject in your trigger it will prevent them all from being committed to the database, however any other DML operations you perform (that of course, do not cause errors in their own triggers) will be committed successfully.

If you're looking to log to a custom object this is your best bet; catch the exception, mark everything in Trigger.new with addError, then commit your log sObject.

EXCEPTION - To summarize the edits from subsequent contact with salesforce: this will not work if every record in the trigger has errors. In this case all work done in the trigger, including @future method calls, sending email, queueing batch jobs, or performing any DML, is rolled back.

I opened a Salesforce case with partner premier support (who actually troubleshoot apex issues!) #08522717. Salesforce claims this is working as designed, and pointed me to the wiki. Which seems to suggest that setting the all or nothing flag will impact this behavior but in my testing it didn't matter - if no DML rows commit without errors all operations are rolled back.

share|improve this answer
1  
I tried that and it also results in a full rollback. no data is stored. simple example: trigger TestException on Account (before insert, before update) { try { Account a; a.name = 'xxx'; } catch (Exception e) { for(Account a : trigger.new) { a.addError(e.getStackTraceString()); } DebugLog__c dl = new DebugLog__c(); dl.Log__c = e.getStackTraceString(); insert dl; } } –  iwerstler Sep 29 '12 at 19:51
    
Wow, you're right. That's unexpected and undocumented. I'll open a case with salesforce Monday (I have partner premier support so I actually get the skilled support team who can answer about this). I'm not sure if that's an apex bug, or an undocumented "feature" that if no records success to rollback the whole trigger context. –  ca_peterson Sep 29 '12 at 20:27
    
did you ever receive some feedback? –  iwerstler Dec 17 '12 at 15:35
    
Forgot about this, just opened case 08522717 on this. –  ca_peterson Dec 18 '12 at 17:28
1  
Regarding the exceptional case, I believe this is basically the same issue I describe in salesforce.stackexchange.com/questions/23462/…. What happens is that when you use the Database methods, if any of the records fail, that whole operation will roll back and the system will try again ONLY with those records that succeeded. For example, if you try inserting 5 records with Database.insert and 2 of them fail, the initial insert will be rolled back and a second one will occur with only 3 records. –  ceiroa Jan 8 at 19:59

There is a very good wiki page on Developerforce.com on Exception handling. There you can see how to use email notifications on errors or even write an error record to a custom object.

http://wiki.developerforce.com/page/An_Introduction_to_Exception_Handling

share|improve this answer
    
that only works if I catch the exception in the trigger and allow the (probably invalid data) to be stored. –  iwerstler Sep 19 '12 at 10:36
    
you can re throw any caught exception, eg: ..}catch(Exception e) { throw e; } –  Daniel Blackhall Sep 24 '12 at 1:34
    
when I rethrow the exception, the data will not be stored and the email will not be sent. –  iwerstler Sep 29 '12 at 18:33

I would've thought handling the exception should let you insert into a log object in the finally block

Boolean exceptionOccured= false;
try{
//do something
}
catch(Exception ex){
exceptionOccured=true;
throw ex;
}
finally{
If(exceptionOccured)
//log exception XML}      }
share|improve this answer
    
Per my answer it does... but if every sObject in the triger context has an error your logging is also rolled back. Bug? Feature? Not sure. –  ca_peterson Sep 30 '12 at 2:21

If an exception is thrown in your code and you do not attempt to catch it, then SF will roll back the transaction and throw away any data inserted up until the exception is thrown.

On the surface, the behaviour you want is the somewhat unintentional side effect of not handling the transaction failure in the best manner.

I agree with the earlier comment, which is that if the exception is infrequent then catching the exception and sending an email with debug info would be the best thing to do.

share|improve this answer

And so you've found the reason why external "cloud" logging sites exist. Loggly.com and others like it live to serve us. Some exceptions can't be caught and all changes are rolled back in SFDC. The only log possibilities are email and cloud logging like loggly.com. Loggly.com is free for low volume accounts.

share|improve this answer
1  
Can you demonstrate how you would use loggly.com to log an error from within a trigger when the transaction is rolled back? –  Mark Pond Jan 8 '13 at 21:41
    
@MarkPond you can't as future calls and sendEmail calls are also rolled back when the trigger fails to commit any rows. While loggly looks awesome it doesn't really help in this case. –  ca_peterson Jan 9 '13 at 3:18
    
@ca_peterson, I concur... just wanted to document that conclusion within this context. I agree loggly looks like a very cool log management SaaS app. –  Mark Pond Jan 9 '13 at 5:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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