Apex Rest Logging

In the previous article we've taken a look at an outbound scenario where a callout is made from Salesforce to another external system. Now, imagine a reverse use case where Salesforce is receiving a request from an external system via a custom REST endpoint.

A custom REST endpoint is facilitated via an annotated Apex class similar to the one in the snippet below.

For this example, let's assume we're handing a POST request. Regardless of the method the solution below still applies. Our goal is to log the initial request and pass on the generated transaction Id to any other processing that may happen. In addition, if there is an exception during a DML operation or anything else, we'd like to associate this error to the parent REST log.

@RestResource(urlMapping='/Account/*')
global with sharing class MyRestResource {

  @HttpPost
    global static String doPost(String name, String phone, String website) {
        String transactionId = Triton.instance.startTransaction();
        RestRequest req = RestContext.request;
        RestResponse res = Restcontext.response;
        Log.instance.integrationLog(TritonTypes.Type.AccountIntegration, /* type */
                                      TritonTypes.Area.Accounts, /* functional area */
                                      'Initiating new account creation', /* summary */
                                      String.format('POST received with name = {0}, phone = {1}, website = {2}',
                                           new String[]{name, phone, website}), /* formatted details */
                                      req, /* request */
                                      res); /* response */
        try {
            Account account = new Account();
            account.Name = name;
            account.phone = phone;
            account.website = website;

            //(optional) perform some other processing asynchronously, 
            //passing an existing transaction Id 
            AccountProcessing.doAsyncProcessing(account, transactionId);
            
            insert account;
            return account.Id;
        } catch(Exception e) {
            //uh oh, something went wrong, let's log this!
            Triton.instance.error(e);
        }
        return null;
    }
}

The Result

Let's assume that we do run into a DML Exception on line 26 and we will also have some logging performed inside doAsyncProcessing() on line 24. Given all of the above, the snipped may generate the following log structure:

  • Parent Apex Integration Log from line 9

    • Child Apex Error Log from our try/catch block on line 28

    • Any child logs inside the AccountProcessing.doAsyncProcessing() routine on line 24.

The order of child logs created may vary, depending on how quickly Salesforce schedules AccountProcessing for execution. This depends on what type of processing takes place, Batch or Queueable, and whether or not this execution starts immediately.

Last updated