[SalesForce] How to capture Heap Dumps for other users

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?

Best Answer

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'");