From c4d3987c3a4eedc517dd7870fa7a1eac62ff09fe Mon Sep 17 00:00:00 2001 From: Joseph Mercie Date: Fri, 28 Jul 2023 11:18:56 -0300 Subject: [PATCH] Added the ability to throw fault message exception in Flow invocable actions * Updated Apex classes FlowLogEntry, FlowRecordLogEntry, and FlowCollectionLogEntry to have a new optional Boolean property, shouldThrowFaultMessageException * Updated FlowLogger to handle throwing the exception for all 3 Flow invocable logging actions when shouldThrowFaultMessageException == true * Rearranged a few properties in the Flow classes to group some related properties together for readability --- README.md | 12 +++--- .../Logger-Engine/FlowCollectionLogEntry.md | 4 ++ docs/apex/Logger-Engine/FlowLogEntry.md | 4 ++ docs/apex/Logger-Engine/FlowLogger.md | 4 ++ docs/apex/Logger-Engine/FlowRecordLogEntry.md | 4 ++ .../classes/FlowCollectionLogEntry.cls | 18 +++++--- .../logger-engine/classes/FlowLogEntry.cls | 18 +++++--- .../main/logger-engine/classes/FlowLogger.cls | 30 ++++++++++++-- .../classes/FlowRecordLogEntry.cls | 19 ++++++--- .../main/logger-engine/classes/Logger.cls | 2 +- .../main/logger-engine/lwc/logger/logger.js | 2 +- .../classes/FlowCollectionLogEntry_Tests.cls | 41 +++++++++++++++++++ .../classes/FlowLogEntry_Tests.cls | 41 +++++++++++++++++++ .../classes/FlowLogger_Tests.cls | 41 +++++++++++++++++++ .../classes/FlowRecordLogEntry_Tests.cls | 41 +++++++++++++++++++ .../managed-package/sfdx-project.json | 6 +-- package.json | 2 +- sfdx-project.json | 7 ++-- 18 files changed, 260 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 9b246e505..8be226035 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,15 @@ The most robust logger for Salesforce. Works with Apex, Lightning Components, Flow, Process Builder & Integrations. Designed for Salesforce admins, developers & architects. -## Unlocked Package - v4.11.0 +## Unlocked Package - v4.11.1 -[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000023SI6QAM) -[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000023SI6QAM) +[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001TsX4QAK) +[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001TsX4QAK) [![View Documentation](./images/btn-view-documentation.png)](https://jongpie.github.io/NebulaLogger/) -`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y0000023SI6QAM` +`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y000001TsX4QAK` -`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y0000023SI6QAM` +`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y000001TsX4QAK` --- @@ -25,7 +25,7 @@ The most robust logger for Salesforce. Works with Apex, Lightning Components, Fl `sf package install --wait 30 --security-type AdminsOnly --package 04t5Y0000023SI1QAM` -`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y0000023SI1QAM` +`sfdx force:package:install --wait 30 --securitytype AdminsOnly --package 04t5Y0000023SI1QAM` --- diff --git a/docs/apex/Logger-Engine/FlowCollectionLogEntry.md b/docs/apex/Logger-Engine/FlowCollectionLogEntry.md index cb5cb4a07..c6518da54 100644 --- a/docs/apex/Logger-Engine/FlowCollectionLogEntry.md +++ b/docs/apex/Logger-Engine/FlowCollectionLogEntry.md @@ -54,6 +54,10 @@ Optionally choose the save method to use when 'Save Log' is true Optionally specify the name to use for the current transaction's scenario +#### `shouldThrowFaultMessageException` → `Boolean` + +Optionally rollback Database operations executed until Apex action was called and save the log entry. + #### `tagsString` → `String` Optionally provide a comma-separated String of tags to dynamically assign to the log entry diff --git a/docs/apex/Logger-Engine/FlowLogEntry.md b/docs/apex/Logger-Engine/FlowLogEntry.md index 9e88e9ec6..fe137cc52 100644 --- a/docs/apex/Logger-Engine/FlowLogEntry.md +++ b/docs/apex/Logger-Engine/FlowLogEntry.md @@ -54,6 +54,10 @@ Optionally choose the save method to use when 'Save Log' is true Optionally specify the name to use for the current transaction's scenario +#### `shouldThrowFaultMessageException` → `Boolean` + +Optionally rollback Database operations executed until Apex action was called and save the log entry. + #### `tagsString` → `String` Optionally provide a comma-separated String of tags to dynamically assign to the log entry diff --git a/docs/apex/Logger-Engine/FlowLogger.md b/docs/apex/Logger-Engine/FlowLogger.md index 28b42e009..5936eeda4 100644 --- a/docs/apex/Logger-Engine/FlowLogger.md +++ b/docs/apex/Logger-Engine/FlowLogger.md @@ -82,6 +82,10 @@ String name of the instance of Logger.SaveMethod to use when 'Save Log&apos Optionally specify the scenario to use for the current transaction +###### `shouldThrowFaultMessageException` → `Boolean` + +Optionally throws an exception when value is set to True (Use it on Fault connectors of your flow). + ###### `tagsString` → `String` Comma-separated string of tags diff --git a/docs/apex/Logger-Engine/FlowRecordLogEntry.md b/docs/apex/Logger-Engine/FlowRecordLogEntry.md index d94db2d7f..ae5786d11 100644 --- a/docs/apex/Logger-Engine/FlowRecordLogEntry.md +++ b/docs/apex/Logger-Engine/FlowRecordLogEntry.md @@ -54,6 +54,10 @@ Optionally choose the save method to use when 'Save Log' is true Optionally specify the name to use for the current transaction's scenario +#### `shouldThrowFaultMessageException` → `Boolean` + +Optionally rollback Database operations executed until Apex action was called and save the log entry. + #### `tagsString` → `String` Optionally provide a comma-separated String of tags to dynamically assign to the log entry diff --git a/nebula-logger/core/main/logger-engine/classes/FlowCollectionLogEntry.cls b/nebula-logger/core/main/logger-engine/classes/FlowCollectionLogEntry.cls index b0111382b..0a15295b1 100644 --- a/nebula-logger/core/main/logger-engine/classes/FlowCollectionLogEntry.cls +++ b/nebula-logger/core/main/logger-engine/classes/FlowCollectionLogEntry.cls @@ -33,12 +33,24 @@ global inherited sharing class FlowCollectionLogEntry { @InvocableVariable(required=false label='Records') global List records; + /** + * @description Optionally specify a logging level - the default is 'DEBUG' + */ + @InvocableVariable(required=false label='(Optional) Logging Level') + global String loggingLevelName; + /** * @description Optionally log a Flow fault error message */ @InvocableVariable(required=false label='(Optional) Flow Fault Error Message') global String faultMessage; + /** + * @description Optionally rollback Database operations executed until Apex action was called and save the log entry. + */ + @InvocableVariable(required=false label='(Optional) Throw FlowException for Fault Error Message') + global Boolean shouldThrowFaultMessageException; + /** * @description Optionally choose to save any pending log entries */ @@ -51,12 +63,6 @@ global inherited sharing class FlowCollectionLogEntry { @InvocableVariable(required=false label='(Optional) Save Method') global String saveMethodName; - /** - * @description Optionally specify a logging level - the default is 'DEBUG' - */ - @InvocableVariable(required=false label='(Optional) Logging Level') - global String loggingLevelName; - /** * @description Optionally specify the name to use for the current transaction's scenario */ diff --git a/nebula-logger/core/main/logger-engine/classes/FlowLogEntry.cls b/nebula-logger/core/main/logger-engine/classes/FlowLogEntry.cls index da1708fa3..7ce639ceb 100644 --- a/nebula-logger/core/main/logger-engine/classes/FlowLogEntry.cls +++ b/nebula-logger/core/main/logger-engine/classes/FlowLogEntry.cls @@ -27,12 +27,24 @@ global inherited sharing class FlowLogEntry { @InvocableVariable(required=true label='Log Entry Message') global String message; + /** + * @description Optionally specify a logging level - the default is 'DEBUG' + */ + @InvocableVariable(required=false label='(Optional) Logging Level') + global String loggingLevelName; + /** * @description Optionally log a Flow fault error message */ @InvocableVariable(required=false label='(Optional) Flow Fault Error Message') global String faultMessage; + /** + * @description Optionally rollback Database operations executed until Apex action was called and save the log entry. + */ + @InvocableVariable(required=false label='(Optional) Throw FlowException for Fault Error Message') + global Boolean shouldThrowFaultMessageException; + /** * @description Optionally choose to save any pending log entries */ @@ -51,12 +63,6 @@ global inherited sharing class FlowLogEntry { @InvocableVariable(required=false label='(Optional) Record ID') global Id recordId; - /** - * @description Optionally specify a logging level - the default is 'DEBUG' - */ - @InvocableVariable(required=false label='(Optional) Logging Level') - global String loggingLevelName; - /** * @description Optionally specify the name to use for the current transaction's scenario */ diff --git a/nebula-logger/core/main/logger-engine/classes/FlowLogger.cls b/nebula-logger/core/main/logger-engine/classes/FlowLogger.cls index 032325265..25543d65d 100644 --- a/nebula-logger/core/main/logger-engine/classes/FlowLogger.cls +++ b/nebula-logger/core/main/logger-engine/classes/FlowLogger.cls @@ -39,15 +39,20 @@ public inherited sharing class FlowLogger { */ public String message; + /** + * @description String name of the entry's logging level + */ + public String loggingLevelName; + /** * @description String containing fault message, if applicable */ public String faultMessage; /** - * @description String name of the entry's logging level + * @description Optionally throws an exception when value is set to True (Use it on Fault connectors of your flow). */ - public String loggingLevelName; + public Boolean shouldThrowFaultMessageException; /** * @description Optionally specify the scenario to use for the current transaction @@ -140,6 +145,9 @@ public inherited sharing class FlowLogger { public static List addEntries(List flowEntries) { Boolean saveLog = false; Logger.SaveMethod saveMethod = Logger.getSaveMethod(); + Boolean shouldThrowFaultMessageException = false; + String faultMessage = ''; + for (LogEntry flowEntry : flowEntries) { flowEntry.addToLoggerBuffer(); @@ -148,6 +156,12 @@ public inherited sharing class FlowLogger { if (String.isNotBlank(flowEntry.saveMethodName) == true) { saveMethod = Logger.SaveMethod.valueOf(flowEntry.saveMethodName); } + if (flowEntry.shouldThrowFaultMessageException == true) { + shouldThrowFaultMessageException = flowEntry.shouldThrowFaultMessageException; + } + if (String.isNotBlank(flowEntry.faultMessage) == true) { + faultMessage = flowEntry.faultMessage; + } } } @@ -155,12 +169,22 @@ public inherited sharing class FlowLogger { Logger.saveLog(saveMethod); } + // Here we throw an exception so we stop synchronous database updates from happening + // avoiding inconsistencies + if (shouldThrowFaultMessageException == true) { + throw new System.FlowException(faultMessage); + } + + return setTransactionIds(flowEntries.size()); + } + + private static List setTransactionIds(Integer size) { // Event though it's the same transaction ID, Salesforce expects the returned list... // to have the same number of items as the initial input. // When there's a mismatch, Salesforce throws an error: // FLOW_ELEMENT_ERROR The number of results does not match the number of interviews that were executed in a single bulk execution request.|FlowActionCall List transactionIds = new List(); - for (Integer i = 0; i < flowEntries.size(); i++) { + for (Integer i = 0; i < size; i++) { transactionIds.add(Logger.getTransactionId()); } return transactionIds; diff --git a/nebula-logger/core/main/logger-engine/classes/FlowRecordLogEntry.cls b/nebula-logger/core/main/logger-engine/classes/FlowRecordLogEntry.cls index b667745ea..99ea96f5e 100644 --- a/nebula-logger/core/main/logger-engine/classes/FlowRecordLogEntry.cls +++ b/nebula-logger/core/main/logger-engine/classes/FlowRecordLogEntry.cls @@ -33,11 +33,24 @@ global inherited sharing class FlowRecordLogEntry { @InvocableVariable(required=false label='Record') global SObject record; + /** + * @description Optionally specify a logging level - the default is 'DEBUG' + */ + @InvocableVariable(required=false label='(Optional) Logging Level') + global String loggingLevelName; + /** * @description Optionally log a Flow fault error message */ @InvocableVariable(required=false label='(Optional) Flow Fault Error Message') global String faultMessage; + + /** + * @description Optionally rollback Database operations executed until Apex action was called and save the log entry. + */ + @InvocableVariable(required=false label='(Optional) Throw FlowException for Fault Error Message') + global Boolean shouldThrowFaultMessageException; + /** * @description Optionally choose to save any pending log entries */ @@ -50,12 +63,6 @@ global inherited sharing class FlowRecordLogEntry { @InvocableVariable(required=false label='(Optional) Save Method') global String saveMethodName; - /** - * @description Optionally specify a logging level - the default is 'DEBUG' - */ - @InvocableVariable(required=false label='(Optional) Logging Level') - global String loggingLevelName; - /** * @description Optionally specify the name to use for the current transaction's scenario */ diff --git a/nebula-logger/core/main/logger-engine/classes/Logger.cls b/nebula-logger/core/main/logger-engine/classes/Logger.cls index 58eac4848..474ea2d70 100644 --- a/nebula-logger/core/main/logger-engine/classes/Logger.cls +++ b/nebula-logger/core/main/logger-engine/classes/Logger.cls @@ -15,7 +15,7 @@ global with sharing class Logger { // There's no reliable way to get the version number dynamically in Apex @TestVisible - private static final String CURRENT_VERSION_NUMBER = 'v4.11.0'; + private static final String CURRENT_VERSION_NUMBER = 'v4.11.1'; private static final System.LoggingLevel FALLBACK_LOGGING_LEVEL = System.LoggingLevel.DEBUG; private static final Set IGNORED_APEX_CLASSES = initializeIgnoredApexClasses(); private static final List LOG_ENTRIES_BUFFER = new List(); diff --git a/nebula-logger/core/main/logger-engine/lwc/logger/logger.js b/nebula-logger/core/main/logger-engine/lwc/logger/logger.js index 9a61a5255..a2dfdf60c 100644 --- a/nebula-logger/core/main/logger-engine/lwc/logger/logger.js +++ b/nebula-logger/core/main/logger-engine/lwc/logger/logger.js @@ -6,7 +6,7 @@ import { LightningElement, api } from 'lwc'; import { createLoggerService } from './loggerService'; -const CURRENT_VERSION_NUMBER = 'v4.11.0'; +const CURRENT_VERSION_NUMBER = 'v4.11.1'; export default class Logger extends LightningElement { #loggerService = createLoggerService(); diff --git a/nebula-logger/core/tests/logger-engine/classes/FlowCollectionLogEntry_Tests.cls b/nebula-logger/core/tests/logger-engine/classes/FlowCollectionLogEntry_Tests.cls index c1e6f3ddb..de40973a9 100644 --- a/nebula-logger/core/tests/logger-engine/classes/FlowCollectionLogEntry_Tests.cls +++ b/nebula-logger/core/tests/logger-engine/classes/FlowCollectionLogEntry_Tests.cls @@ -230,6 +230,47 @@ private class FlowCollectionLogEntry_Tests { System.Assert.areEqual('Flow', publishedLogEntryEvent.OriginType__c); } + @IsTest + static void it_should_throw_exception_when_shouldThrowFaultMessageException_is_set_to_true() { + LoggerDataStore.setMock(LoggerMockDataStore.getEventBus()); + String faultMessage = ''; + System.LoggingLevel entryLoggingLevel = System.LoggingLevel.ERROR; + Logger.getUserSettings().LoggingLevel__c = entryLoggingLevel.name(); + LoggerTestConfigurator.setupMockSObjectHandlerConfigurations(); + System.Assert.areEqual(0, Logger.getBufferSize()); + System.Assert.areEqual(0, [SELECT COUNT() FROM LogEntry__c]); + FlowCollectionLogEntry flowCollectionEntry = createFlowCollectionLogEntry(); + flowCollectionEntry.flowName = 'MyFlow'; + flowCollectionEntry.message = 'hello from Flow'; + flowCollectionEntry.loggingLevelName = entryLoggingLevel.name(); + flowCollectionEntry.saveLog = true; + flowCollectionEntry.faultMessage = 'Exception message'; + flowCollectionEntry.shouldThrowFaultMessageException = true; + flowCollectionEntry.timestamp = System.now(); + System.Assert.areEqual(0, Logger.saveLogCallCount); + System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishCallCount()); + System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size()); + + try { + FlowCollectionLogEntry.addFlowCollectionEntries(new List{ flowCollectionEntry }); + + System.Assert.areEqual(0, Logger.getBufferSize()); + System.Assert.areEqual(1, Logger.saveLogCallCount); + System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishCallCount()); + System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size()); + LogEntryEvent__e publishedLogEntryEvent = (LogEntryEvent__e) LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().get(0); + System.Assert.areEqual(flowCollectionEntry.loggingLevelName, publishedLogEntryEvent.LoggingLevel__c); + System.Assert.areEqual(flowCollectionEntry.message, publishedLogEntryEvent.Message__c); + System.Assert.areEqual('Flow', publishedLogEntryEvent.OriginType__c); + System.Assert.areEqual(flowCollectionEntry.timestamp, publishedLogEntryEvent.Timestamp__c); + } catch (Exception e) { + faultMessage = e.getMessage(); + + System.Assert.areEqual(flowCollectionEntry.faultMessage, faultMessage, 'fault message its not expected to be empty'); + System.Assert.areEqual('System.FlowException', e.getTypeName(), 'Exception type must match the one we are throwing'); + } + } + @IsTest static void it_should_set_logger_scenario() { LoggerDataStore.setMock(LoggerMockDataStore.getEventBus()); diff --git a/nebula-logger/core/tests/logger-engine/classes/FlowLogEntry_Tests.cls b/nebula-logger/core/tests/logger-engine/classes/FlowLogEntry_Tests.cls index 3b4af8493..dc14a6ed2 100644 --- a/nebula-logger/core/tests/logger-engine/classes/FlowLogEntry_Tests.cls +++ b/nebula-logger/core/tests/logger-engine/classes/FlowLogEntry_Tests.cls @@ -186,6 +186,47 @@ private class FlowLogEntry_Tests { System.Assert.areEqual('Flow', publishedLogEntryEvent.OriginType__c); } + @IsTest + static void it_should_throw_exception_when_shouldThrowFaultMessageException_is_set_to_true() { + LoggerDataStore.setMock(LoggerMockDataStore.getEventBus()); + String faultMessage = ''; + System.LoggingLevel entryLoggingLevel = System.LoggingLevel.ERROR; + Logger.getUserSettings().LoggingLevel__c = entryLoggingLevel.name(); + LoggerTestConfigurator.setupMockSObjectHandlerConfigurations(); + System.Assert.areEqual(0, Logger.getBufferSize()); + System.Assert.areEqual(0, [SELECT COUNT() FROM LogEntry__c]); + FlowLogEntry flowEntry = createFlowLogEntry(); + flowEntry.flowName = 'MyFlow'; + flowEntry.message = 'hello from Flow'; + flowEntry.loggingLevelName = entryLoggingLevel.name(); + flowEntry.saveLog = true; + flowEntry.faultMessage = 'Exception message'; + flowEntry.shouldThrowFaultMessageException = true; + flowEntry.timestamp = System.now(); + System.Assert.areEqual(0, Logger.saveLogCallCount); + System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishCallCount()); + System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size()); + + try { + FlowLogEntry.addFlowEntries(new List{ flowEntry }); + + System.Assert.areEqual(0, Logger.getBufferSize()); + System.Assert.areEqual(1, Logger.saveLogCallCount); + System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishCallCount()); + System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size()); + LogEntryEvent__e publishedLogEntryEvent = (LogEntryEvent__e) LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().get(0); + System.Assert.areEqual(flowEntry.loggingLevelName, publishedLogEntryEvent.LoggingLevel__c); + System.Assert.areEqual(flowEntry.message, publishedLogEntryEvent.Message__c); + System.Assert.areEqual('Flow', publishedLogEntryEvent.OriginType__c); + System.Assert.areEqual(flowEntry.timestamp, publishedLogEntryEvent.Timestamp__c); + } catch (Exception e) { + faultMessage = e.getMessage(); + + System.Assert.areEqual(flowEntry.faultMessage, faultMessage, 'fault message its not expected to be empty'); + System.Assert.areEqual('System.FlowException', e.getTypeName(), 'Exception type must match the one we are throwing'); + } + } + @IsTest static void it_should_set_logger_scenario() { LoggerDataStore.setMock(LoggerMockDataStore.getEventBus()); diff --git a/nebula-logger/core/tests/logger-engine/classes/FlowLogger_Tests.cls b/nebula-logger/core/tests/logger-engine/classes/FlowLogger_Tests.cls index 0de7731b9..1d0803b3e 100644 --- a/nebula-logger/core/tests/logger-engine/classes/FlowLogger_Tests.cls +++ b/nebula-logger/core/tests/logger-engine/classes/FlowLogger_Tests.cls @@ -107,4 +107,45 @@ private class FlowLogger_Tests { System.Assert.areEqual('Flow', publishedLogEntryEvent.OriginType__c); System.Assert.areEqual(flowEntry.timestamp, publishedLogEntryEvent.Timestamp__c); } + + @IsTest + static void it_should_throw_exception_when_shouldThrowFaultMessageException_is_set_to_true() { + LoggerDataStore.setMock(LoggerMockDataStore.getEventBus()); + String faultMessage = ''; + System.LoggingLevel entryLoggingLevel = System.LoggingLevel.ERROR; + Logger.getUserSettings().LoggingLevel__c = entryLoggingLevel.name(); + LoggerTestConfigurator.setupMockSObjectHandlerConfigurations(); + System.Assert.areEqual(0, Logger.getBufferSize()); + System.Assert.areEqual(0, [SELECT COUNT() FROM LogEntry__c]); + FlowLogger.LogEntry flowEntry = new FlowLogger.LogEntry(); + flowEntry.flowName = 'MyFlow'; + flowEntry.message = 'hello from Flow'; + flowEntry.loggingLevelName = entryLoggingLevel.name(); + flowEntry.saveLog = true; + flowEntry.faultMessage = 'Exception message'; + flowEntry.shouldThrowFaultMessageException = true; + flowEntry.timestamp = System.now(); + System.Assert.areEqual(0, Logger.saveLogCallCount); + System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishCallCount()); + System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size()); + + try { + FlowLogger.addEntries(new List{ flowEntry }); + + System.Assert.areEqual(0, Logger.getBufferSize()); + System.Assert.areEqual(1, Logger.saveLogCallCount); + System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishCallCount()); + System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size()); + LogEntryEvent__e publishedLogEntryEvent = (LogEntryEvent__e) LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().get(0); + System.Assert.areEqual(flowEntry.loggingLevelName, publishedLogEntryEvent.LoggingLevel__c); + System.Assert.areEqual(flowEntry.message, publishedLogEntryEvent.Message__c); + System.Assert.areEqual('Flow', publishedLogEntryEvent.OriginType__c); + System.Assert.areEqual(flowEntry.timestamp, publishedLogEntryEvent.Timestamp__c); + } catch (Exception e) { + faultMessage = e.getMessage(); + + System.Assert.areEqual(flowEntry.faultMessage, faultMessage, 'fault message its not expected to be empty'); + System.Assert.areEqual('System.FlowException', e.getTypeName(), 'Exception type must match the one we are throwing'); + } + } } diff --git a/nebula-logger/core/tests/logger-engine/classes/FlowRecordLogEntry_Tests.cls b/nebula-logger/core/tests/logger-engine/classes/FlowRecordLogEntry_Tests.cls index 0b03032e1..b5d114f61 100644 --- a/nebula-logger/core/tests/logger-engine/classes/FlowRecordLogEntry_Tests.cls +++ b/nebula-logger/core/tests/logger-engine/classes/FlowRecordLogEntry_Tests.cls @@ -227,6 +227,47 @@ private class FlowRecordLogEntry_Tests { System.Assert.areEqual('Flow', publishedLogEntryEvent.OriginType__c); } + @IsTest + static void it_should_throw_exception_when_shouldThrowFaultMessageException_is_set_to_true() { + LoggerDataStore.setMock(LoggerMockDataStore.getEventBus()); + String faultMessage = ''; + System.LoggingLevel entryLoggingLevel = System.LoggingLevel.ERROR; + Logger.getUserSettings().LoggingLevel__c = entryLoggingLevel.name(); + LoggerTestConfigurator.setupMockSObjectHandlerConfigurations(); + System.Assert.areEqual(0, Logger.getBufferSize()); + System.Assert.areEqual(0, [SELECT COUNT() FROM LogEntry__c]); + FlowRecordLogEntry flowRecordEntry = createFlowRecordLogEntry(); + flowRecordEntry.flowName = 'MyFlow'; + flowRecordEntry.message = 'hello from Flow'; + flowRecordEntry.loggingLevelName = entryLoggingLevel.name(); + flowRecordEntry.saveLog = true; + flowRecordEntry.faultMessage = 'Exception message'; + flowRecordEntry.shouldThrowFaultMessageException = true; + flowRecordEntry.timestamp = System.now(); + System.Assert.areEqual(0, Logger.saveLogCallCount); + System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishCallCount()); + System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size()); + + try { + FlowRecordLogEntry.addFlowRecordEntries(new List{ flowRecordEntry }); + + System.Assert.areEqual(0, Logger.getBufferSize()); + System.Assert.areEqual(1, Logger.saveLogCallCount); + System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishCallCount()); + System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size()); + LogEntryEvent__e publishedLogEntryEvent = (LogEntryEvent__e) LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().get(0); + System.Assert.areEqual(flowRecordEntry.loggingLevelName, publishedLogEntryEvent.LoggingLevel__c); + System.Assert.areEqual(flowRecordEntry.message, publishedLogEntryEvent.Message__c); + System.Assert.areEqual('Flow', publishedLogEntryEvent.OriginType__c); + System.Assert.areEqual(flowRecordEntry.timestamp, publishedLogEntryEvent.Timestamp__c); + } catch (Exception e) { + faultMessage = e.getMessage(); + + System.Assert.areEqual(flowRecordEntry.faultMessage, faultMessage, 'fault message its not expected to be empty'); + System.Assert.areEqual('System.FlowException', e.getTypeName(), 'Exception type must match the one we are throwing'); + } + } + @IsTest static void it_should_set_logger_scenario() { LoggerDataStore.setMock(LoggerMockDataStore.getEventBus()); diff --git a/nebula-logger/managed-package/sfdx-project.json b/nebula-logger/managed-package/sfdx-project.json index 227d5e12d..e18bf694f 100644 --- a/nebula-logger/managed-package/sfdx-project.json +++ b/nebula-logger/managed-package/sfdx-project.json @@ -10,9 +10,9 @@ "definitionFile": "./config/scratch-orgs/base-scratch-def.json", "postInstallScript": "LoggerInstallHandler", "ancestorVersion": "HIGHEST", - "versionNumber": "4.11.0.NEXT", - "versionName": "Summer '23 Release", - "versionDescription": "View the v4.11.0 milestone in GitHub for the list of changes - https://github.com/jongpie/NebulaLogger/milestone/11?closed=1", + "versionNumber": "4.12.0.NEXT", + "versionName": "Winter '24 Release", + "versionDescription": "View the v4.12.0 milestone in GitHub for the list of changes - https://github.com/jongpie/NebulaLogger/milestone/12?closed=1", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases/tag/v4.11.0" } ], diff --git a/package.json b/package.json index 4746a525c..0d863f6e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nebula-logger", - "version": "4.11.0", + "version": "4.11.1", "description": "The most robust logger for Salesforce. Works with Apex, Lightning Components, Flow, Process Builder & Integrations. Designed for Salesforce admins, developers & architects.", "author": "Jonathan Gillespie", "license": "MIT", diff --git a/sfdx-project.json b/sfdx-project.json index f3a234f2b..7ab9092ed 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -13,9 +13,9 @@ "package": "Nebula Logger - Core", "path": "./nebula-logger/core", "definitionFile": "./config/scratch-orgs/base-scratch-def.json", - "versionNumber": "4.11.0.NEXT", - "versionName": "Summer '23 Release", - "versionDescription": "Updated all metadata to API v58.0, added LoggerParameter__mdt record to disable the LWC logEntryEventStream", + "versionNumber": "4.11.1.NEXT", + "versionName": "Throw Exception in Flow Actions", + "versionDescription": "Added the ability in Flow to automatically re-throw fault exception messages after saving", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases", "unpackagedMetadata": { "path": "./nebula-logger/extra-tests" @@ -148,6 +148,7 @@ "Nebula Logger - Core@4.10.5-new-custom-index-for-origin-location-field": "04t5Y0000023SCHQA2", "Nebula Logger - Core@4.10.6-more-log__c-and-logentry__c-fields": "04t5Y0000023SCqQAM", "Nebula Logger - Core@4.11.0-summer-'23-release": "04t5Y0000023SI6QAM", + "Nebula Logger - Core@4.11.1-throw-exception-in-flow-actions": "04t5Y000001TsX4QAK", "Nebula Logger - Core Plugin - Async Failure Additions": "0Ho5Y000000blO4SAI", "Nebula Logger - Core Plugin - Async Failure Additions@1.0.0": "04t5Y0000015lhiQAA", "Nebula Logger - Core Plugin - Async Failure Additions@1.0.1": "04t5Y0000015lhsQAA",