Integration Logs

If your Salesforce instance is talking to external services via REST or other types of APIs, Pharos Triton can perform a certain type of logging that helps troubleshoot those integrations.

In this article, we'll look at creating logs with supporting request/response payload information. A typical scenario involves performing an Apex callout. Oftentimes we expect an HTTP 200 response if all goes well. However, the most troublesome scenario is when things don't go well. You may receive a non 200 response from your external service and, at that point, the only way to get to the bottom of the problem is to examine the request/response payload.

Integration Log View

Triton offers a convenient interface for visualizing payloads directly from a log record. Below is an example of such a log record:

If you've used Postman before, this view may look familiar. From this interface you have the ability to view the request endpoint, parameters, headers, and body. In a similar fashion, you can examine the response that is returned. There is also a replay capability that allows you to re-send the request (with optional modifications) to your external endpoint. The request will be sent from your org and not just your browser. This is a very powerful way to troubleshoot integrations. Moreover, there is an easy way to create these types of logs view the Pharos Triton Apex interface. Let's take a look at an example.

Common Callout Example

Regardless of where your integration is kicked off, you'll likely have some Apex code that sets up an HttpRequest and performs a callout to your external service. In the example below, we're going to collect some data from a custom object and use that to create the JSON body of the request and send it off to our external service.

Basic HTTP Post
public static void pushLoanApplication(Id loanApplicationId) {
    //collect the data for our http request
    Loan_Application__c la = [select Id, 
                                    Account__r.Name, 
                                    Primary_Contact__r.FirstName, 
                                    Primary_Contact__r.LastName, 
                                    Primary_Contact__r.Email, 
                                    Primary_Contact__r.Social__c 
                                    from Loan_Application__c 
                                    where Id=:loanApplicationId limit 1]; 

    //put together a map so we can serialize it into JSON
    Map<String, String> requestMap = new Map<String, String>();
    requestMap.put('firstName', la.Primary_Contact__r.FirstName);
    requestMap.put('lastName', la.Primary_Contact__r.LastName);
    requestMap.put('email', la.Primary_Contact__r.Email);        
    requestMap.put('ssn', la.Primary_Contact__r.Social__c);                

    //setup an HttpRequest with all the necessary attributes
    Http http = new Http();
    HttpRequest request = new HttpRequest();
    request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals');
    request.setMethod('POST');
    request.setHeader('Content-Type', 'application/json;charset=UTF-8');
    request.setBody(JSON.serializePretty(requestMap));      
    
    //perform the POST operation
    HttpResponse response = http.send(request);
}

Your use case may not be this exact operation, but in all likelihood, the idea is similar: gather data, create a request payload and perform the callout.

One glaring issue with the code snippet above is that it doesn't account for the possibility of failure. If the HttpResponse response returns a 500 status or some other non-200 failure, we will never know. At that point it's next to impossible to connect the dots, especially if the failure is discovered well after the request was performed. To remedy this situation, let's add some logging to help us out.

Creating an Integration Log

public static void pushLoanApplication(Id loanApplicationId) {
    //collect the data for our http request
    Loan_Application__c la = [select Id, 
                                    Account__r.Name, 
                                    Primary_Contact__r.FirstName, 
                                    Primary_Contact__r.LastName, 
                                    Primary_Contact__r.Email, 
                                    Primary_Contact__r.Social__c 
                                    from Loan_Application__c 
                                    where Id=:loanApplicationId limit 1]; 

    //put together a map so we can serialize it to JSON
    Map<String, String> requestMap = new Map<String, String>();
    requestMap.put('firstName', la.Primary_Contact__r.FirstName);
    requestMap.put('lastName', la.Primary_Contact__r.LastName);
    requestMap.put('email', la.Primary_Contact__r.Email);        
    requestMap.put('ssn', la.Primary_Contact__r.Social__c);                

    //setup an HttpRequest with all the necessary attributes
    try {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals');
        request.setMethod('POST');
        request.setHeader('Content-Type', 'application/json;charset=UTF-8');
        request.setBody(JSON.serializePretty(requestMap));      
    
        //perform the POST operation
        HttpResponse response = http.send(request);
        if (response.getStatusCode() != 200) {
            //we didn't get a successful response, so let's log this
            Triton.instance.integrationError(TritonTpes.Type.PushIntegration, /* type */
                                    TritonTpes.Area.LoadApplications, /* area */
                                    'Unable to push an application to the loan service', /* summary */
                                    String.format('Received a {0} status code from the loan service when pushing an application id {1}',
                                        new String[] {String.valueOf(response.getStatusCode()), la.Id]    /* formatted details */ 
                                    request, /* HttpRequest */
                                    response /* HttpResponse */
            ); 
        }
       
    } catch (Exception e) {
        //something else went wrong, let's log this as well
        Triton.instance.error(e);
    }
}

Executing this code snippet should result in a log similar to the following:

Because we also specified a record Id in the details of the log we should also see a related object linked to the log record:

Last updated