Find your content:

Search form

You are here

custom error logging, batch apex, failure/success counts

 
Share

This may be simple, but I want to implement custom error logging for a batch class, where handled exceptions get written to a logging object in the database.

So I could use the technique in Andrew's answer here: Can I prevent an insert to be rolled back even if my class (later) runs into an exception?

The wrinkle is that if a handled exception occurs and is logged, I'd still like that batch to count as a "Failure" so that when the user monitors the job in Apex Jobs, it'll still show in the failed batches count.

enter image description here

Make sense? I'm handling the exceptions in this case in order to log them, not because I want them hidden from the user.

Is it possible to do this, and still have the log survive? If I use Andrew's technique, and catch the original err, do a rollback, write the logs, and then throw a new exception, it'll roll back the logs, right? And if I don't do the throw, the batch will count as a success, right?


Attribution to: mscholtz

Possible Suggestion/Solution #1

Yes, you can capture your logs and still have individual batches fail and rollback. For that you need to define an instance variable in your batch class - List of custom object used for logging - to store your logs while batch is running and insert them all at once in the finish() method. You will have to add Database.Stateful to your class definition (see 'Using State in Batch Apex' in this document) to ensure that your instance variable is preserved across transactions.

global class TestBatch implements Database.Batchable<sObject>, Database.Stateful {

    global List<Log__c> logs;

    global TestBatch() {
        logs = new List<Log__c>();
    }

    global Database.QueryLocator start(Database.BatchableContext BC) {
        query = 'Your query...';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<sObject> scope) {
        for (sobject s : scope) {
            try{
                Your logic goes here...
            } catch (Exception e) {
                logs.add(new Log__c(
                        Name__c = '...',
                        Stacktrace__c = e.getStackTraceString()
                    ));
                throw e;
            }
        }
        update scope;
    }

    global void finish(Database.BatchableContext BC) {
        insert logs;
    }
}

Attribution to: IvanR

Possible Suggestion/Solution #2

This is my understanding of how the platform works by default: if any unhandled exception (exception that is not caught by our code) occurs, or if any record in the context is flagged as containing an error through the use of the addError method, the whole transaction is rolled back. This makes it impossible to store custom errors or to send error notifications, as the storing of the error records or the Chatter post records would also be rolled back. The emails containing error notifications would never be sent, as the transaction rollback pulls them from the queue they were put in.

The only alternative is the workaround mentioned above, in which exceptions are caught and addError is not used. However in this case the platform has no way of knowing that an error occurred.


Attribution to: ceiroa
This content is remixed from stackoverflow or stackexchange. Please visit https://salesforce.stackexchange.com/questions/34207

My Block Status

My Block Content