Week of 3/15/21
Yes, this is about a week overdue, but it's still something that I learned about on the week of the 15th, so it still counts! I ended up spending a lot of time with some debugging methods and needing to access Apex debug logs. Salesforce Apex debug logs are an extremely valuable resource for getting information about Apex code execution, API operations, and automated processes. The only issue is that the interface for the debug logs (at least of March 2021) is still shown in a classic UI with no filtering mechanisms.
This is fine for Sandbox developer orgs and small orgs, but what if you're running a Production org with hundreds of users and dozens of integrations? You could have several logs generated every second, and no real way to narrow down the list. Thankfully, there's an API we can take advantage of to get some better filtering solutions.
Postman & the Tooling API: The ApexLog endpoint
I use Postman for a lot of API testing within Salesforce. From creating and updating objects to accessing the LiveAgent REST resources, Postman can provide an easy-to-use interface to any Salesforce API. It's so popular that Salesforce has documentation on using this tool. Using Postman, we can create a quick and simple set of API calls to retrieve the results of an Apex debug log :
- Retrieve an OAuth token through a connected app
- Retrieve the Apex debug logs
- Retrieve the contents of a specified debug log
To start, we'll need a connected app with API access. We just need a connected app with OAuth enabled:
In order to do a password-based OAuth flow, we'll need the org URL, the client Id and secret, and the username + password of the user that will access the Apex logs through the API. In Postman, to provide easily re-usable requests, we'll put these values in an environment file. This will keep the values consistent between requests and will provide a place to write values (such as the access token and the Apex log Id) for use in another request.
- If you want to completely reset the process, you can click "Reset All" which will clear values generated during the process. The values you fill in the "initial value" column will not be cleared between requests.
Starting in the request tree, the "Get token" request will get an access token using our connected app configuration.
The "Get Token" request also contains some custom Postman Javascript code to write the org token value to an environment variable, as well as check the response for testing purposes.
pm.test("200 Response Code", function () {
pm.response.to.have.status(200);
});
pm.test("Token Check", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.token_type).to.eql("Bearer");
});
var jsonData = JSON.parse(responseBody);
pm.environment.set("ORG_TOKEN", jsonData.access_token);
On a successful request, the token will be stored in the ORG_TOKEN environment variable, which we reference as the bearer token in subsequent requests
Our next request will query the debug logs and sort them by date, just like what we see in the Salesforce UI for debug logs. We can even use Postman to properly format the data for the request:
The response contains an array of JSON objects that describe Apex debug logs. All we need to do is find the right time (times are in GMT) and save the target Id in the ORG_LOG_ID environment variable. You can access this menu in Postman by highlighting the desired Id and right-clicking:
This will save the Id as another environment variable for use in the "Retrieve Debug Log" request. This will get the full body of the Apex debug log:
I added the Postman collection and environment file to my Github repository so you can incorporate these requests into your own Postman deployment and have an easier time working with Apex debug logs in busy environments.
Thanks, and have fun!