Skip to content

Commit

Permalink
Fixed #529 by adding a try-catch block in Logger.callStatusApi() and …
Browse files Browse the repository at this point in the history
…returning null when exceptions occur
  • Loading branch information
jongpie committed Aug 7, 2023
1 parent 3843c34 commit d972e19
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 24 deletions.
2 changes: 1 addition & 1 deletion docs/apex/Logger-Engine/Logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ StatusApiResponse

**Description**

Instance of `Logger.StatusApiResponse`, a data transfer object (DTO) that maps to the JSON returned
An instance of `Logger.StatusApiResponse` (a DTO that maps to the JSON returned by the status API endpoint),

#### `createSettings()``LoggerSettings__c`

Expand Down
4 changes: 4 additions & 0 deletions docs/apex/Test-Utilities/LoggerMockDataCreator.md
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,8 @@ A new copy of the original `SObject` record that has the specified read-only fie

###### `statusCode``Integer`

###### `statusMessage``String`

---

##### Methods
Expand All @@ -612,6 +614,8 @@ A new copy of the original `SObject` record that has the specified read-only fie

###### `setResponseBody(String responseBody)``MockHttpCallout`

###### `setStatus(String statusMessage)``MockHttpCallout`

###### `setStatusCode(Integer statusCode)``MockHttpCallout`

---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,17 @@ public without sharing class LoggerHomeHeaderController {

private static void setStatusApiResponseDetails(Environment environment) {
Logger.StatusApiResponse statusApiResponse = Logger.callStatusApi();
if (statusApiResponse != null) {
environment.organizationInstanceLocation = statusApiResponse.location;
environment.organizationMaintenanceWindow = statusApiResponse.maintenanceWindow;
environment.organizationReleaseNumber = statusApiResponse.releaseNumber;
environment.organizationReleaseVersion = statusApiResponse.releaseVersion;
if (statusApiResponse == null) {
return;
}

environment.organizationInstanceLocation = statusApiResponse.location;
environment.organizationMaintenanceWindow = statusApiResponse.maintenanceWindow;
environment.organizationReleaseNumber = statusApiResponse.releaseNumber;
environment.organizationReleaseVersion = statusApiResponse.releaseVersion;

if (statusApiResponse.Products != null && statusApiResponse.Products.isEmpty() == false) {
environment.organizationInstanceProducts = getInstanceProductNames(statusApiResponse);
}
if (statusApiResponse.Products != null && statusApiResponse.Products.isEmpty() == false) {
environment.organizationInstanceProducts = getInstanceProductNames(statusApiResponse);
}
}

Expand Down
37 changes: 22 additions & 15 deletions nebula-logger/core/main/logger-engine/classes/Logger.cls
Original file line number Diff line number Diff line change
Expand Up @@ -3228,8 +3228,8 @@ global with sharing class Logger {
* Calls Salesforce's API endpoint https://api.status.salesforce.com/v1/instances/
* to get more details about the current org, including the org's release number and release version.
* Trust API docs available at https://api.status.salesforce.com/v1/docs/
* @return Instance of `Logger.StatusApiResponse`, a data transfer object (DTO) that maps to the JSON returned
* by the status API endpoint.
* @return An instance of `Logger.StatusApiResponse` (a DTO that maps to the JSON returned by the status API endpoint),
* or `null` when the callout fails (due to the remote site setting being disabled, the endpoint being unable, etc.).
*/
public static StatusApiResponse callStatusApi() {
if (LoggerParameter.CALL_STATUS_API == false) {
Expand All @@ -3243,20 +3243,27 @@ global with sharing class Logger {
request.setEndpoint(statusApiEndpoint);
request.setMethod('GET');

System.HttpResponse response = new System.Http().send(request);
if (response.getStatusCode() >= 400) {
String errorMessage =
'Callout failed for ' +
statusApiEndpoint +
'\nReceived request status code ' +
response.getStatusCode() +
', status message: ' +
response.getStatus();
throw new System.CalloutException(errorMessage);
}
try {
System.HttpResponse response = new System.Http().send(request);
if (response.getStatusCode() >= 400) {
String errorMessage =
'Callout failed for ' +
statusApiEndpoint +
'\nReceived request status code ' +
response.getStatusCode() +
', status message: ' +
response.getStatus();
throw new System.CalloutException(errorMessage);
}

StatusApiResponse statusApiResponse = (StatusApiResponse) JSON.deserialize(response.getBody(), StatusApiResponse.class);
return statusApiResponse;
StatusApiResponse statusApiResponse = (StatusApiResponse) JSON.deserialize(response.getBody(), StatusApiResponse.class);
return statusApiResponse;
} catch (Exception ex) {
if (LoggerParameter.ENABLE_SYSTEM_MESSAGES == true) {
finest('Callout to api.status.salesforce.com failed').setExceptionDetails(ex);
}
return null;
}
}

// Private logging level methods to keep global methods simpler/cleaner
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ public class LoggerMockDataCreator {
public System.HttpResponse response { get; private set; }
public String responseBody { get; private set; }
public Integer statusCode { get; private set; }
public String statusMessage { get; private set; }

public MockHttpCallout() {
}
Expand All @@ -472,6 +473,11 @@ public class LoggerMockDataCreator {
return this;
}

public MockHttpCallout setStatus(String statusMessage) {
this.statusMessage = statusMessage;
return this;
}

public System.HttpResponse respond(System.HttpRequest request) {
this.request = request;

Expand All @@ -480,6 +486,7 @@ public class LoggerMockDataCreator {
response.setBody(this.responseBody);
}
response.setStatusCode(this.statusCode);
response.setStatus(this.statusMessage);
return response;
}
}
Expand Down
35 changes: 35 additions & 0 deletions nebula-logger/core/tests/logger-engine/classes/Logger_Tests.cls
Original file line number Diff line number Diff line change
Expand Up @@ -7814,6 +7814,41 @@ private class Logger_Tests {
System.Assert.areEqual(JSON.serialize(mockApiResponse), JSON.serialize(returnedApiResponse));
}

@IsTest
static void it_should_gracefully_return_null_when_callout_fails_to_status_api() {
LoggerDataStore.setMock(LoggerMockDataStore.getEventBus());
LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'CallStatusApi', Value__c = System.JSON.serialize(true)));
LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'EnableLoggerSystemMessages', Value__c = System.JSON.serialize(true)));
System.Assert.isTrue(LoggerParameter.CALL_STATUS_API);
String mockErrorMessage = 'It broke! 😥';
Integer errorStatusCode = 404;
String errorStatusMessage = 'Oops, did not understand request, or something... IDK.... it\'s broken ¯\\_(ツ)_/¯';
System.Test.setMock(
System.HttpCalloutMock.class,
LoggerMockDataCreator.createHttpCallout().setStatusCode(errorStatusCode).setResponseBody(mockErrorMessage)
);
System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size());

Logger.StatusApiResponse returnedApiResponse = Logger.callStatusApi();

System.Assert.isNull(returnedApiResponse);
Logger.saveLog();
System.Assert.areEqual(2, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size());
LogEntryEvent__e logEntryEvent = (LogEntryEvent__e) LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().get(0);
System.Assert.areEqual('Callout to api.status.salesforce.com failed', logEntryEvent.Message__c);
System.Assert.areEqual('System.CalloutException', logEntryEvent.ExceptionType__c);
Organization organization = LoggerEngineDataSelector.getInstance().getCachedOrganization();
String expectedExceptionMessage =
'Callout failed for https://api.status.salesforce.com/v1/instances/' +
organization.InstanceName +
'/status' +
'\nReceived request status code ' +
errorStatusCode +
', status message: ' +
errorStatusMessage;
System.Assert.isTrue(logEntryEvent.ExceptionMessage__c.startsWith('Callout failed for https://api.status.salesforce.com/v1/instances/'));
}

@IsTest
static void it_should_return_null_when_status_api_callout_is_disabled() {
LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'CallStatusApi', Value__c = System.JSON.serialize(false)));
Expand Down

0 comments on commit d972e19

Please sign in to comment.