diff --git a/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls b/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls index b7b5efb42..7ebd4be36 100644 --- a/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls @@ -236,7 +236,7 @@ public without sharing class LogEntryEventHandler { List logs = [ SELECT Id, ApiReleaseNumber__c, ApiReleaseVersion__c FROM Log__c - WHERE CreatedDate >= :fourHoursAgo AND DAY_ONLY(CreatedDate) = TODAY AND ApiReleaseNumber__c != NULL + WHERE CreatedDate >= :fourHoursAgo AND CreatedDate = TODAY AND ApiReleaseNumber__c != NULL ORDER BY CreatedDate DESC LIMIT 1 ]; @@ -287,7 +287,13 @@ public without sharing class LogEntryEventHandler { System.debug('statusApiResponse==' + statusApiResponse); List logsToUpdate = new List(); - for (Log__c log : [SELECT Id FROM Log__c WHERE DAY_ONLY(CreatedDate) = TODAY AND ApiReleaseNumber__c = NULL ORDER BY CreatedDate LIMIT :Limits.getLimitDmlRows()]) { + for (Log__c log : [ + SELECT Id + FROM Log__c + WHERE CreatedDate = TODAY AND ApiReleaseNumber__c = NULL + ORDER BY CreatedDate + LIMIT :Limits.getLimitDmlRows() + ]) { log.ApiReleaseNumber__c = statusApiResponse.releaseNumber; log.ApiReleaseVersion__c = statusApiResponse.releaseVersion; diff --git a/nebula-logger/main/log-management/objects/LogEntry__c/fields/ExceptionType__c.field-meta.xml b/nebula-logger/main/log-management/objects/LogEntry__c/fields/ExceptionType__c.field-meta.xml index 8dd6bafcd..df93d8460 100644 --- a/nebula-logger/main/log-management/objects/LogEntry__c/fields/ExceptionType__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LogEntry__c/fields/ExceptionType__c.field-meta.xml @@ -10,6 +10,11 @@ true + + Flow.FaultError + false + + System.AsyncException false diff --git a/nebula-logger/main/logger-engine/classes/FlowLogEntry.cls b/nebula-logger/main/logger-engine/classes/FlowLogEntry.cls index f3ed146a3..65d93ca0c 100644 --- a/nebula-logger/main/logger-engine/classes/FlowLogEntry.cls +++ b/nebula-logger/main/logger-engine/classes/FlowLogEntry.cls @@ -24,6 +24,12 @@ global inherited sharing class FlowLogEntry { @InvocableVariable(required=true label='Log Entry Message') global String message; + /** + * @description Optionally log a Flow fault error message + */ + @InvocableVariable(required=false label='(Optional) Flow Fault Error Message') + global String faultMessage; + /** * @description Optionally choose to save any pending log entries. */ @@ -40,7 +46,7 @@ global inherited sharing class FlowLogEntry { * @description Optionally specify a logging level - the default is 'DEBUG' */ @InvocableVariable(required=false label='(Optional) Logging Level') - global String loggingLevelName = 'DEBUG'; + global String loggingLevelName; /** * @description Optionally provide a list of topics to dynamically assign to the log entry @@ -59,6 +65,15 @@ global inherited sharing class FlowLogEntry { global static List addFlowEntries(List flowLogEntries) { Boolean saveLog = false; for (FlowLogEntry flowLogEntry : flowLogEntries) { + // Set the logging level if it's blank + if (String.isBlank(flowLogEntry.loggingLevelName)) { + if (String.isNotBlank(flowLogEntry.faultMessage)) { + flowLogEntry.loggingLevelName = 'ERROR'; + } else { + flowLogEntry.loggingLevelName = 'DEBUG'; + } + } + LoggingLevel loggingLevel = Logger.getLoggingLevel(flowLogEntry.loggingLevelName); LogEntryEventBuilder logEntryEventBuilder = Logger.newEntry(loggingLevel, flowLogEntry.message) @@ -67,7 +82,7 @@ global inherited sharing class FlowLogEntry { LogEntryEvent__e logEntryEvent = logEntryEventBuilder.getLogEntryEvent(); - if (logEntryEvent == null) { + if (logEntryEventBuilder.shouldSave() == false) { continue; } @@ -75,12 +90,17 @@ global inherited sharing class FlowLogEntry { logEntryEvent.OriginType__c = 'Flow'; logEntryEvent.Timestamp__c = flowLogEntry.timestamp; - if (flowLogEntry.saveLog) { + if (String.isNotBlank(flowLogEntry.faultMessage)) { + logEntryEvent.ExceptionMessage__c = flowLogEntry.faultMessage; + logEntryEvent.ExceptionType__c = 'Flow.FaultError'; + } + + if (flowLogEntry.saveLog == true) { saveLog = flowLogEntry.saveLog; } } - if (saveLog) { + if (saveLog == true) { Logger.saveLog(); } diff --git a/nebula-logger/main/logger-engine/classes/FlowRecordLogEntry.cls b/nebula-logger/main/logger-engine/classes/FlowRecordLogEntry.cls index 45ae9c183..eef00a1c8 100644 --- a/nebula-logger/main/logger-engine/classes/FlowRecordLogEntry.cls +++ b/nebula-logger/main/logger-engine/classes/FlowRecordLogEntry.cls @@ -30,6 +30,11 @@ global inherited sharing class FlowRecordLogEntry { @InvocableVariable(required=true label='Record') global SObject record; + /** + * @description Optionally log a Flow fault error message + */ + @InvocableVariable(required=false label='(Optional) Flow Fault Error Message') + global String faultMessage; /** * @description Optionally choose to save any pending log entries */ @@ -40,7 +45,7 @@ global inherited sharing class FlowRecordLogEntry { * @description Optionally specify a logging level - the default is 'DEBUG' */ @InvocableVariable(required=false label='(Optional) Logging Level') - global String loggingLevelName = 'DEBUG'; + global String loggingLevelName; /** * @description Optionally provide a list of topics to dynamically assign to the log entry @@ -63,6 +68,15 @@ global inherited sharing class FlowRecordLogEntry { global static List addFlowRecordEntries(List flowRecordLogEntries) { Boolean saveLog = false; for (FlowRecordLogEntry flowRecordLogEntry : flowRecordLogEntries) { + // Set the logging level if it's blank + if (String.isBlank(flowRecordLogEntry.loggingLevelName)) { + if (String.isNotBlank(flowRecordLogEntry.faultMessage)) { + flowRecordLogEntry.loggingLevelName = 'ERROR'; + } else { + flowRecordLogEntry.loggingLevelName = 'DEBUG'; + } + } + LoggingLevel loggingLevel = Logger.getLoggingLevel(flowRecordLogEntry.loggingLevelName); LogEntryEventBuilder logEntryEventBuilder = Logger.newEntry(loggingLevel, flowRecordLogEntry.message) @@ -71,7 +85,7 @@ global inherited sharing class FlowRecordLogEntry { LogEntryEvent__e logEntryEvent = logEntryEventBuilder.getLogEntryEvent(); - if (logEntryEvent == null) { + if (logEntryEventBuilder.shouldSave() == false) { continue; } @@ -79,11 +93,17 @@ global inherited sharing class FlowRecordLogEntry { logEntryEvent.OriginType__c = 'Flow'; logEntryEvent.Timestamp__c = flowRecordLogEntry.timestamp; - if (flowRecordLogEntry.saveLog) { + if (String.isNotBlank(flowRecordLogEntry.faultMessage)) { + logEntryEvent.ExceptionMessage__c = flowRecordLogEntry.faultMessage; + logEntryEvent.ExceptionType__c = 'Flow.FaultError'; + } + + if (flowRecordLogEntry.saveLog == true) { saveLog = flowRecordLogEntry.saveLog; } } - if (saveLog) { + + if (saveLog == true) { Logger.saveLog(); } diff --git a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls index 4050b4a8b..63d9f76e3 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls @@ -408,7 +408,6 @@ private class LogEntryEventHandler_Tests { String transactionId = '123-456-789-0'; LogEntryEvent__e logEntryEvent = new LogEntryEvent__e(Message__c = 'my message', Timestamp__c = System.now(), TransactionId__c = transactionId); - Database.SaveResult saveResult; Test.startTest(); diff --git a/nebula-logger/tests/logger-engine/classes/FlowLogEntry_Tests.cls b/nebula-logger/tests/logger-engine/classes/FlowLogEntry_Tests.cls index 003937deb..e5cf2637d 100644 --- a/nebula-logger/tests/logger-engine/classes/FlowLogEntry_Tests.cls +++ b/nebula-logger/tests/logger-engine/classes/FlowLogEntry_Tests.cls @@ -9,7 +9,6 @@ private class FlowLogEntry_Tests { flowEntry.flowName = 'my test message'; flowEntry.message = 'MyFlowOrProcessBuilder'; flowEntry.saveLog = true; - flowEntry.loggingLevelName = 'DEBUG'; return flowEntry; } @@ -68,6 +67,59 @@ private class FlowLogEntry_Tests { System.assertEquals(0, logEntries.size()); } + @isTest + static void it_should_use_debug_as_default_level_when_faultMessage_is_null() { + String userLoggingLevel = 'FINEST'; + + LoggerSettings__c loggerSettings = LoggerSettings__c.getInstance(); + loggerSettings.LoggingLevel__c = userLoggingLevel; + update loggerSettings; + + Test.startTest(); + + FlowLogEntry flowEntry = createFlowLogEntry(); + System.assertEquals(null, flowEntry.loggingLevelName); + + FlowLogEntry.addFlowEntries(new List{ flowEntry }); + Logger.saveLog(); + + Test.stopTest(); + + LogEntry__c logEntry = [SELECT Id, LoggingLevel__c, Message__c, OriginType__c, OriginLocation__c FROM LogEntry__c ORDER BY CreatedDate LIMIT 1]; + System.assertEquals('DEBUG', logEntry.LoggingLevel__c); + System.assertEquals(flowEntry.message, logEntry.Message__c); + System.assertEquals('Flow', logEntry.OriginType__c); + System.assertEquals(flowEntry.flowName, logEntry.OriginLocation__c); + } + + @isTest + static void it_should_use_error_as_default_level_when_faultMessage_is_not_null() { + String userLoggingLevel = 'FINEST'; + + LoggerSettings__c loggerSettings = LoggerSettings__c.getInstance(); + loggerSettings.LoggingLevel__c = userLoggingLevel; + update loggerSettings; + + Test.startTest(); + + FlowLogEntry flowEntry = createFlowLogEntry(); + flowEntry.faultMessage = 'Whoops, a Flow error has occurred.'; + System.assertEquals(null, flowEntry.loggingLevelName); + + FlowLogEntry.addFlowEntries(new List{ flowEntry }); + Logger.saveLog(); + + Test.stopTest(); + + LogEntry__c logEntry = [SELECT Id, ExceptionMessage__c, ExceptionType__c, LoggingLevel__c, Message__c, OriginType__c, OriginLocation__c FROM LogEntry__c ORDER BY CreatedDate LIMIT 1]; + System.assertEquals('ERROR', logEntry.LoggingLevel__c); + System.assertEquals(flowEntry.faultMessage, logEntry.ExceptionMessage__c); + System.assertEquals('Flow.FaultError', logEntry.ExceptionType__c); + System.assertEquals(flowEntry.message, logEntry.Message__c); + System.assertEquals('Flow', logEntry.OriginType__c); + System.assertEquals(flowEntry.flowName, logEntry.OriginLocation__c); + } + @isTest static void it_should_set_related_record_id_when_id_parameter_is_used() { String userLoggingLevel = 'FINEST'; diff --git a/nebula-logger/tests/logger-engine/classes/FlowRecordLogEntry_Tests.cls b/nebula-logger/tests/logger-engine/classes/FlowRecordLogEntry_Tests.cls index 38ce2c377..3ab064604 100644 --- a/nebula-logger/tests/logger-engine/classes/FlowRecordLogEntry_Tests.cls +++ b/nebula-logger/tests/logger-engine/classes/FlowRecordLogEntry_Tests.cls @@ -9,7 +9,6 @@ private class FlowRecordLogEntry_Tests { flowRecordEntry.flowName = 'my test message'; flowRecordEntry.message = 'MyFlowOrProcessBuilder'; flowRecordEntry.saveLog = true; - flowRecordEntry.loggingLevelName = 'DEBUG'; return flowRecordEntry; } @@ -72,4 +71,58 @@ private class FlowRecordLogEntry_Tests { List logEntries = [SELECT Id FROM LogEntry__c]; System.assertEquals(0, logEntries.size()); } + + @isTest + static void it_should_use_debug_as_default_level_when_faultMessage_is_null() { + String userLoggingLevel = 'FINEST'; + + LoggerSettings__c loggerSettings = LoggerSettings__c.getInstance(); + loggerSettings.LoggingLevel__c = userLoggingLevel; + update loggerSettings; + + Test.startTest(); + + FlowRecordLogEntry flowEntry = createFlowRecordLogEntry(); + System.assertEquals(null, flowEntry.loggingLevelName); + + FlowRecordLogEntry.addFlowRecordEntries(new List{ flowEntry }); + Logger.saveLog(); + + Test.stopTest(); + + LogEntry__c logEntry = [SELECT Id, LoggingLevel__c, Message__c, OriginType__c, OriginLocation__c FROM LogEntry__c ORDER BY CreatedDate LIMIT 1]; + System.assertEquals('DEBUG', logEntry.LoggingLevel__c); + System.assertEquals(flowEntry.message, logEntry.Message__c); + System.assertEquals('Flow', logEntry.OriginType__c); + System.assertEquals(flowEntry.flowName, logEntry.OriginLocation__c); + } + + @isTest + static void it_should_use_error_as_default_level_when_faultMessage_is_not_null() { + String userLoggingLevel = 'FINEST'; + + LoggerSettings__c loggerSettings = LoggerSettings__c.getInstance(); + loggerSettings.LoggingLevel__c = userLoggingLevel; + update loggerSettings; + + Test.startTest(); + + FlowRecordLogEntry flowEntry = createFlowRecordLogEntry(); + flowEntry.faultMessage = 'Whoops, a Flow error has occurred.'; + System.assertEquals(null, flowEntry.loggingLevelName); + + FlowRecordLogEntry.addFlowRecordEntries(new List{ flowEntry }); + Logger.saveLog(); + + Test.stopTest(); + + LogEntry__c logEntry = [SELECT Id, ExceptionMessage__c, ExceptionType__c, LoggingLevel__c, Message__c, OriginType__c, OriginLocation__c FROM LogEntry__c ORDER BY CreatedDate LIMIT 1]; + System.assertEquals('ERROR', logEntry.LoggingLevel__c); + System.assertEquals(flowEntry.faultMessage, logEntry.ExceptionMessage__c); + System.assertEquals('Flow.FaultError', logEntry.ExceptionType__c); + System.assertEquals(flowEntry.message, logEntry.Message__c); + System.assertEquals('Flow', logEntry.OriginType__c); + System.assertEquals(flowEntry.flowName, logEntry.OriginLocation__c); + } + }