Wednesday, September 30, 2015

The Trace Flag and Debug Level in Salesforce Force.com

This feature wasn't in  before until I noticed it in Sep 2015, round about the Dreamforce. And I somewhat figured it out myself navigating here and there in the Debug Log screen.

So when you go to Setup - Monitoring - Debug Log, we only used to see the "DEBUG LOG" section.

Now we see two sections, the "USER TRACE FLAGS" section and we have the legacy "DEBUG LOG" section right below it.

To debug your Apex code, click on the 'NEW' button in the USER TRACE FLAGS section.

Now this new feature is powerful. The Trace Entity dropdown will allow you to select User, Apex Class, Apex Trigger, which means you can debug your code in a more granular fashion by targeting what you want user/component to debug.

Now say you are debugging a functionality in your Salesforce org for a specific user, select "USER" in the dropdown and specify that user's name.

The start date & end date cannot be more than 24 hours apart. Salesforce still wants to track on how much we can debug at a time. In short, there is still a limit on how much we can debug.

The Debug Level is something new you will see here. In the beginning, you wont have any Debug Level of your own. You will have to create your own customized Debug Levels here. So for that, click the Search button on the Debug Level field and this will open a popup for you.

Because you do not have any debug level to start with, you really cant search and go. So click on 'New'.

Here you can define your own name for your choice of Debug Level.

Next, you can select your debug choice from each of the following dropdowns available: Database, Workflow, Validation, Callout, Apex Code, Apex Profiling, Visualforce, System.

Thats it, Save your Debug Level. Go back to the Trace Flags screen and save your settings.

Once done, you can start debugging the code for the user you specified.

Go get better at freaking debugging.


Friday, August 14, 2015

Tuesday, March 31, 2015

How to drink a beer and sleep well while your Apex Jobs are running?

Catching Job Errors and Re-firing them using Apex Scheduler


Pain, pain, pain, oh sometimes it pains in the ass when no matter what you do, no matter how much you brain it out and architect the delicate pillars to build a huge Apex batchable job that processes tons and tons of records, there are many times your batch job might fail. And that failure could throw you out of your job if your batch job fails to execute an ultra-important business calculation that the business folks were relying on. The damn bloody error could be because of a CPU timeout, a concurrency lock error, or a Salesforce Internal Server Error due to a SOQL query that is taking more time to execute than allowed by the god damn governor limits. And you cant be bloody monitoring the job waking up in the middle of the night, to re-fire it manually when you realize it didn't fire the automated way. Sometimes it might even happen that the error handler in your code's Exception block might not fire because of an Internal Server Error. And you were expecting like an idiot an email to your inbox that would tell you what's the status of the job - Completed or Aborted? 

So what can you do to handle such crazy scenarios?

Well the following approach is a bit of a work-around, until you manage to build a Cadillac out of your code, simply check for errors and re-fire your batch job if it didn't run successfully in the last fire.

Now here comes to rescue the super duper AsyncApexJob sObject. Simply query it, ask it if your darling job fired. To start with, I must say I love this object for many reasons that I can keep on going on.

Enough of shit stories, here is the approach:
* Query the AsyncApexJob object to find out the status of the last fired instance of your batch class
* If the job didn't run happily, just refire your job.

Now say the name of your batchable job is MyDearBatchable. And you or some external source like an ETL fired MyDearBatchable to run. But then due to some stupid bloody reason, MyDearBatchable didn't run successfully.

So what you do is create a Schedulable job like the one below:

global class MyDearSchedulable implements Schedulable{
    global void execute(SchedulableContext ctx) {
        // Fetch status of the MyDearBatchable job that ran last
        List<AsyncApexJob> listStatusOfBatch = [SELECT Id, MethodName, JobItemsProcessed, ApexClassId, ApexClass.Name, CompletedDate, NumberOfErrors, Status, ExtendedStatus, TotalJobItems FROM AsyncApexJob where ApexClass.Name='MyDearBatchable' order by CompletedDate Desc Limit 1 ];
        
       Boolean refire1 = false; // status flag for refiring IntradayEmailBatchable
        for(AsyncApexJob j1:listStatusOfBatch){
            if(j1.Status=='Aborted'){
              refire1 = true; 
            }
         }
        
        // Refire MyDearBatchable 
        if((refire1==true){
            Database.executeBatch(new MyDearBatchable(null), 200);
        }
    }

}

Now you can schedule this class to run by navigating to Setup -> Apex Classes and then click on "Schedule Apex Jobs", or alternatively, schedule it to run using the Developer Console using the following command:

MyDearSchedulable m = new MyDearSchedulable(); 
string sch = '0 20 10,14,16 * 1,2,3,4,5,6,7,8,9,10,11,12 ? 2015'; // You can set your own CronExpression here to set the time you want it to fire in Queue 
system.schedule('MyDearSchedulable', sch, m);

And thats it. You can sleep happily ever after. You just need to know & guess when to schedule this job.

Have a beer & sleep well.

Cheers!
Vishal Khanna