8

Some of my users are experiencing a strange behavior that I can't yet reproduce in a Sandbox, so I'm trying to monitor the bug more closely in our production database.

Since I'm in a production database, I can't edit the code to add new System.debug() calls. Instead, I'd like to use Heap Dumps to inspect the heap and state at various points, but I can't figure out how to collect them.

I'm monitoring a user's debug logs with the APEX_CODE filters set to 'Finest'. Logged in as myself, I have the Developer Console open with 2 heap dump locations set. But no heap dumps are captured, even though I can see from the debug logs that the code is being run.

How can I capture these dumps, or do you have other recommended debugging techniques?

4
  • Does unchecking 'Show My Current Heap Dumps Only' show Heap Dumps for other users? If not I reckon it may not be possible (reckon this question did come up in the recent Advanced Debugging Webinar, cant remember if it was possible) Apr 5, 2013 at 17:23
  • No, doesn't help.
    – Benj
    Apr 5, 2013 at 17:50
  • Hi Benj, Since debug logs are too unpredictable, why dont you store your exceptions in a custom object . In our application we log all exceptions in a custom object. If it is a run time exception and you want to simulate, a quick refresh of the production sandbox might help to recreate the issue. You can also set a flag to debug true on your custom setting and put the logs in a custom object and test it in production as well. Let me know if this helps.. Apr 6, 2013 at 4:50
  • @buyankumar It's a cool idea, but I don't know how applicable it is here. We're not having any trouble accessing the debug logs. The problem is that we haven't planned in advance WHAT to monitor or debug, and it doesn't make sense to debug every var at every moment or to deploy new code every time we want to add a debug statement.
    – Benj
    Apr 7, 2013 at 15:55

1 Answer 1

6

The new Tooling API has the ApexExecutionOverlayAction object.

Specifies an Apex code snippet or SOQL query to execute at a specific line of code in an Apex class or trigger and optionally generate a heap dump.

You could use this to capture the heap dump for the required user.

Specifically, try setting:

  • ActionScriptType to 'None'
  • ExecutableEntityId to the Apex class Id
  • ExpirationDate to some time in the future. Maybe an hour out
  • IsDumpingHeap to true
  • Iteration to 1
  • The Line to "The line number of the heap dump marker"
  • the ScopeId to the required UserId

I hacked something together in a .NET to try it out.

SforceService toolingService = // Get an instance of the ToolingService

string apexClassId = "01p70000CLASSID";

// This is the session owners UserId
//string heapUserId = "005700000000FOO";
// This is an Id of another user in the Org
string heapUserId = "005700000000BAR";

int heapDumpLine = 27;

ApexExecutionOverlayAction apexExecutionOverlayAction = new SalesforceTooling.ApexExecutionOverlayAction();
apexExecutionOverlayAction.ActionScriptType = "None";
apexExecutionOverlayAction.ExecutableEntityId = apexClassId;

apexExecutionOverlayAction.IsDumpingHeap = true;
apexExecutionOverlayAction.IsDumpingHeapSpecified = true;

apexExecutionOverlayAction.Iteration = 1;
apexExecutionOverlayAction.IterationSpecified = true;

apexExecutionOverlayAction.Line = heapDumpLine;
apexExecutionOverlayAction.LineSpecified = true;

apexExecutionOverlayAction.ScopeId = heapUserId;

SaveResult[] results = toolingService.create(new sObject[] { apexExecutionOverlayAction });
SaveResult triggerSaveResult = results[0];
if (!triggerSaveResult.success)
{
    Assert.Fail(triggerSaveResult.errors[0].message);
}
Assert.IsTrue(triggerSaveResult.success);

Note that this didn't make the Heap Dump Location appear in the developer console for the session owner. I logged in as the target user, but it appears I've broken the developer console for that user:

Broken Salesforce Developer Console - Error loading configuration: Server Error

However, after hitting the dump point you can pull the resulting dump out from the ToolingService using the ApexLog. E.g.

QueryResult apexdumpLogResult = toolingService.query("Select Id, Application, DurationMilliseconds, Location, LogUserId, Operation from ApexLog where Location = 'HeapDump'");
1
  • I used the Tooling Rest API via Workbench but followed your process. Good stuff!
    – Benj
    Apr 8, 2013 at 17:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .