From 6453b1726894f14f717fd5faf134eb090937d856 Mon Sep 17 00:00:00 2001 From: James Simone <16430727+jamessimone@users.noreply.github.com> Date: Fri, 29 Mar 2024 12:02:36 -0400 Subject: [PATCH] Logger Performance Improvements (#660) * Benchmarking & performance improvements for transactions with many log entries * Removes duplicated field truncation from LoggerDataStore's pre-platform event publish responsibilities * Further optimizations - strip out Logging classes prior to entering LoggerStackTrace, saving an average of 3 seconds processing time over 500 log entries * Adds PMD7 suppressions where applicable * Standardizing how timestamps are added to and maintained within LogEntryEventBuilder with feedback from @jongpie * Code review feedback from @jongpie - changed LoggerParameter.StoreApexHeapSizeLimit to LoggerParameter.StoreHeapSizeLimit, standardized referring to the limit in the singular as opposed to plural, and added two more tests: 1) LogEntryEventBuilder_Tests.it_should_not_set_transaction_heap_limits_fields_when_transaction_limit_tracking_is_disabled_via_logger_parameter(), and 2) LoggerBenchmarking_Tests.it_benchmarks_without_setting_heap_limit() --- README.md | 10 +- .../configuration/classes/LoggerCache.cls | 2 +- .../configuration/classes/LoggerParameter.cls | 17 +- ...erParameter.StoreHeapSizeLimit.md-meta.xml | 25 + .../log-management/classes/LogBatchPurger.cls | 2 +- .../classes/LoggerEmailSender.cls | 2 +- .../classes/LoggerSettingsController.cls | 2 +- .../logger-engine/classes/ComponentLogger.cls | 20 +- .../main/logger-engine/classes/FlowLogger.cls | 2 +- .../classes/LogEntryEventBuilder.cls | 432 ++++++++---------- .../main/logger-engine/classes/Logger.cls | 87 ++-- .../logger-engine/classes/LoggerDataStore.cls | 94 +--- .../classes/LoggerStackTrace.cls | 13 - .../lwc/logger/logEntryBuilder.js | 2 +- .../utilities/LoggerMockDataCreator.cls | 2 +- .../classes/LogEntryEventBuilder_Tests.cls | 217 ++++----- .../classes/LoggerDataStore_Tests.cls | 63 --- .../logger-engine/classes/Logger_Tests.cls | 42 +- .../utilities/LoggerMockDataStore.cls | 13 +- .../LogEntryEventBuilder_Tests_Network.cls | 4 +- .../LogEntryEventBuilder_Tests_Security.cls | 6 +- .../tests/LoggerBenchmarking_Tests.cls | 55 +++ .../LoggerBenchmarking_Tests.cls-meta.xml | 5 + .../tests/Logger_Tests_MergeResult.cls | 2 +- .../plugin/classes/LogRetentionFilter.cls | 1 + package.json | 2 +- scripts/data/create-sample-log-entries.apex | 3 +- sfdx-project.json | 7 +- 28 files changed, 512 insertions(+), 620 deletions(-) create mode 100644 nebula-logger/core/main/configuration/customMetadata/LoggerParameter.StoreHeapSizeLimit.md-meta.xml create mode 100644 nebula-logger/extra-tests/tests/LoggerBenchmarking_Tests.cls create mode 100644 nebula-logger/extra-tests/tests/LoggerBenchmarking_Tests.cls-meta.xml diff --git a/README.md b/README.md index 1e7e7addc..34b88daac 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.13.4 +## Unlocked Package - v4.13.5 -[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001MkFBQA0) -[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001MkFBQA0) +[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001MkGnQAK) +[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001MkGnQAK) [![View Documentation](./images/btn-view-documentation.png)](https://jongpie.github.io/NebulaLogger/) -`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y000001MkFBQA0` +`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y000001MkGnQAK` -`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y000001MkFBQA0` +`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y000001MkGnQAK` --- diff --git a/nebula-logger/core/main/configuration/classes/LoggerCache.cls b/nebula-logger/core/main/configuration/classes/LoggerCache.cls index 036a39226..4380f6d3c 100644 --- a/nebula-logger/core/main/configuration/classes/LoggerCache.cls +++ b/nebula-logger/core/main/configuration/classes/LoggerCache.cls @@ -7,7 +7,7 @@ * @group Configuration * @description Class used to cache query results returned by the selector classes */ -@SuppressWarnings('PMD.ExcessivePublicCount') +@SuppressWarnings('PMD.CognitiveComplexity, PMD.ExcessivePublicCount') public without sharing class LoggerCache { private static final String DEFAULT_PARTITION_NAME = 'LoggerCache'; private static final Boolean PLATFORM_CACHE_IS_IMMUTABLE = false; diff --git a/nebula-logger/core/main/configuration/classes/LoggerParameter.cls b/nebula-logger/core/main/configuration/classes/LoggerParameter.cls index 80831de63..cc1fcb443 100644 --- a/nebula-logger/core/main/configuration/classes/LoggerParameter.cls +++ b/nebula-logger/core/main/configuration/classes/LoggerParameter.cls @@ -8,7 +8,7 @@ * @description Provides a centralized way to load parameters for SObject handlers & plugins, * and casts the parameters to common data types */ -@SuppressWarnings('PMD.CyclomaticComplexity, PMD.ExcessivePublicCount, PMD.PropertyNamingConventions') +@SuppressWarnings('PMD.CognitiveComplexity, PMD.CyclomaticComplexity, PMD.ExcessivePublicCount, PMD.PropertyNamingConventions') public class LoggerParameter { // During tests, always load this CMDT record // so that tests use the same format when calling System.debug() @@ -369,6 +369,21 @@ public class LoggerParameter { private set; } + /** + * @description Indicates if Nebula Logger will store the transaction heap limits on `LogEntry__c`, retrieved from the class `System.Limits`. + * Controlled by the custom metadata record `LoggerParameter.StoreApexHeapSizeLimit`, or `true` as the default. + * Relies on `LoggerParameter.StoreTransactionLimits` to be true, as well. + */ + public static final Boolean STORE_HEAP_SIZE_LIMIT { + get { + if (STORE_HEAP_SIZE_LIMIT == null) { + STORE_HEAP_SIZE_LIMIT = getBoolean('StoreHeapSizeLimit', true); + } + return STORE_HEAP_SIZE_LIMIT; + } + private set; + } + /** * @description Indicates if Nebula Logger will store the header values when logging an instance of `System.HttpResponse`. * Controlled by the custom metadata record `LoggerParameter.StoreHttpResponseHeaderValues`, or `true` as the default. diff --git a/nebula-logger/core/main/configuration/customMetadata/LoggerParameter.StoreHeapSizeLimit.md-meta.xml b/nebula-logger/core/main/configuration/customMetadata/LoggerParameter.StoreHeapSizeLimit.md-meta.xml new file mode 100644 index 000000000..4c15fc403 --- /dev/null +++ b/nebula-logger/core/main/configuration/customMetadata/LoggerParameter.StoreHeapSizeLimit.md-meta.xml @@ -0,0 +1,25 @@ + + + + false + + Comments__c + + + + Description__c + When set to 'true' (default), transaction heap limits are retrieved from the class System.Limits and stored on LogEntry__c. + +When set to 'false', transaction heap limits are not retrieved or stored. This drastically helps reduce CPU time usage per log entry. The 'Store Transaction Limits' Logger Parameter record must also be set to 'true' for any limit tracking to occur. + + + Value__c + true + + diff --git a/nebula-logger/core/main/log-management/classes/LogBatchPurger.cls b/nebula-logger/core/main/log-management/classes/LogBatchPurger.cls index 0a29067e4..72aff2888 100644 --- a/nebula-logger/core/main/log-management/classes/LogBatchPurger.cls +++ b/nebula-logger/core/main/log-management/classes/LogBatchPurger.cls @@ -8,7 +8,7 @@ * @description Batch class used to delete old logs, based on `Log__c.LogRetentionDate__c <= :System.today()` * @see LogBatchPurgeScheduler */ -@SuppressWarnings('PMD.AvoidGlobalModifier, PMD.CyclomaticComplexity, PMD.ExcessiveParameterList') +@SuppressWarnings('PMD.AvoidGlobalModifier, PMD.CognitiveComplexity, PMD.CyclomaticComplexity, PMD.ExcessiveParameterList') global with sharing class LogBatchPurger implements Database.Batchable, Database.Stateful { private static final Integer DEFAULT_BATCH_SIZE = 2000; private static final Date LOG_RETENTION_END_DATE = System.today(); diff --git a/nebula-logger/core/main/log-management/classes/LoggerEmailSender.cls b/nebula-logger/core/main/log-management/classes/LoggerEmailSender.cls index 29cab5c51..0221d4c3d 100644 --- a/nebula-logger/core/main/log-management/classes/LoggerEmailSender.cls +++ b/nebula-logger/core/main/log-management/classes/LoggerEmailSender.cls @@ -7,7 +7,7 @@ * @group Log Management * @description Builds and sends email notifications when internal exceptions occur within the logging system */ -@SuppressWarnings('PMD.PropertyNamingConventions') +@SuppressWarnings('PMD.CognitiveComplexity, PMD.PropertyNamingConventions') public without sharing class LoggerEmailSender { @TestVisible private static final List MOCK_NOTIFICATIONS = new List(); diff --git a/nebula-logger/core/main/log-management/classes/LoggerSettingsController.cls b/nebula-logger/core/main/log-management/classes/LoggerSettingsController.cls index c77903c47..2e7573ebf 100644 --- a/nebula-logger/core/main/log-management/classes/LoggerSettingsController.cls +++ b/nebula-logger/core/main/log-management/classes/LoggerSettingsController.cls @@ -7,7 +7,7 @@ * @group Log Management * @description Controller class for lwc `loggerSettings`, used to manage records in `LoggerSettings__c` */ -@SuppressWarnings('PMD.CyclomaticComplexity, PMD.ExcessivePublicCount') +@SuppressWarnings('PMD.CognitiveComplexity, PMD.CyclomaticComplexity, PMD.ExcessivePublicCount') public without sharing class LoggerSettingsController { @TestVisible private static final String CUSTOM_SAVE_METHOD_PREFIX = 'CustomSaveMethod'; diff --git a/nebula-logger/core/main/logger-engine/classes/ComponentLogger.cls b/nebula-logger/core/main/logger-engine/classes/ComponentLogger.cls index 7e42bc816..385be2fca 100644 --- a/nebula-logger/core/main/logger-engine/classes/ComponentLogger.cls +++ b/nebula-logger/core/main/logger-engine/classes/ComponentLogger.cls @@ -61,7 +61,7 @@ public inherited sharing class ComponentLogger { logEntryEventBuilder.setRecord(componentLogEntry.record).getLogEntryEvent(); } - logEntryEvent.Timestamp__c = componentLogEntry.timestamp; + logEntryEventBuilder.setTimestamp(componentLogEntry.timestamp); setBrowserDetails(logEntryEvent, componentLogEntry); setComponentErrorDetails(logEntryEvent, componentLogEntry.error); setOriginStackTraceDetails(logEntryEvent, componentLogEntry.stack); @@ -106,7 +106,10 @@ public inherited sharing class ComponentLogger { logEntryEvent.ExceptionSourceActionName__c = exceptionStackTrace.Source?.ActionName; logEntryEvent.ExceptionSourceApiName__c = exceptionStackTrace.Source?.ApiName; logEntryEvent.ExceptionSourceMetadataType__c = exceptionStackTrace.Source?.MetadataType.name(); - logEntryEvent.ExceptionStackTrace__c = exceptionStackTrace.ParsedStackTraceString; + logEntryEvent.ExceptionStackTrace__c = LoggerDataStore.truncateFieldValue( + Schema.LogEntryEvent__e.ExceptionStackTrace__c, + exceptionStackTrace.ParsedStackTraceString + ); } @SuppressWarnings('PMD.AvoidDeeplyNestedIfStmts, PMD.CyclomaticComplexity, PMD.CognitiveComplexity, PMD.NcssMethodCount, PMD.StdCyclomaticComplexity') @@ -127,7 +130,7 @@ public inherited sharing class ComponentLogger { // New Origin fields logEntryEvent.OriginLocation__c = originStackTrace.Location; - logEntryEvent.StackTrace__c = stackTraceString; + logEntryEvent.StackTrace__c = LoggerDataStore.truncateFieldValue(Schema.LogEntryEvent__e.StackTrace__c, stackTraceString); if (originStackTrace.Source != null) { logEntryEvent.OriginSourceActionName__c = originStackTrace.Source.ActionName; logEntryEvent.OriginSourceMetadataType__c = originStackTrace.Source.MetadataType.name(); @@ -135,17 +138,6 @@ public inherited sharing class ComponentLogger { } } - private static String truncateFieldValue(Schema.SObjectField field, String value) { - Integer fieldMaxLength = field.getDescribe().getLength(); - if (String.isBlank(value)) { - return value; - } else if (value.length() <= fieldMaxLength) { - return value; - } - - return value.left(fieldMaxLength); - } - /** * @description A DTO object used for passing `LoggerSettings__c` details to lightning components */ diff --git a/nebula-logger/core/main/logger-engine/classes/FlowLogger.cls b/nebula-logger/core/main/logger-engine/classes/FlowLogger.cls index 2ba15a83c..34ae01df8 100644 --- a/nebula-logger/core/main/logger-engine/classes/FlowLogger.cls +++ b/nebula-logger/core/main/logger-engine/classes/FlowLogger.cls @@ -132,7 +132,7 @@ public inherited sharing class FlowLogger { this.logEntryEvent.OriginSourceApiName__c = this.flowName; this.logEntryEvent.OriginSourceMetadataType__c = FLOW_SOURCE_METADATA_TYPE; this.logEntryEvent.OriginType__c = FLOW_SOURCE_METADATA_TYPE; - this.logEntryEvent.Timestamp__c = this.timestamp; + this.logEntryEventBuilder.setTimestamp(this.timestamp); // Flow does not have an equivalent to a stack trace, so always clear the fields this.logEntryEvent.ExceptionStackTrace__c = null; this.logEntryEvent.StackTrace__c = null; diff --git a/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls b/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls index 128964bd6..d050c3cae 100644 --- a/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls +++ b/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls @@ -9,7 +9,7 @@ * @see Logger */ @SuppressWarnings( - 'PMD.AvoidGlobalModifier, PMD.CognitiveComplexity, PMD.CyclomaticComplexity, PMD.ExcessiveClassLength, PMD.NcssTypeCount, PMD.PropertyNamingConventions, PMD.StdCyclomaticComplexity' + 'PMD.AvoidGlobalModifier, PMD.CognitiveComplexity, PMD.CyclomaticComplexity, PMD.ExcessiveClassLength, PMD.ExcessivePublicCount, PMD.NcssTypeCount, PMD.PropertyNamingConventions, PMD.StdCyclomaticComplexity' ) global with sharing class LogEntryEventBuilder { private static final Map CACHED_SOBJECT_NAME_TO_CLASSIFICATION = new Map(); @@ -74,22 +74,22 @@ global with sharing class LogEntryEventBuilder { set; } - private static final Schema.User CACHED_USER { + private static final TransactionLimits CACHED_TRANSACTION_LIMITS { get { - if (CACHED_USER == null) { - CACHED_USER = LoggerEngineDataSelector.getInstance().getCachedUser(); + if (CACHED_TRANSACTION_LIMITS == null) { + CACHED_TRANSACTION_LIMITS = new TransactionLimits(); } - return CACHED_USER; + return CACHED_TRANSACTION_LIMITS; } set; } - private static final LogEntryEvent__e LOG_ENTRY_EVENT_TEMPLATE { + private static final Schema.User CACHED_USER { get { - if (LOG_ENTRY_EVENT_TEMPLATE == null) { - LOG_ENTRY_EVENT_TEMPLATE = getLogEntryEventTemplate(); + if (CACHED_USER == null) { + CACHED_USER = LoggerEngineDataSelector.getInstance().getCachedUser(); } - return LOG_ENTRY_EVENT_TEMPLATE.clone(); + return CACHED_USER; } set; } @@ -114,19 +114,6 @@ global with sharing class LogEntryEventBuilder { set; } - /** - * @description `Deprecated` - Formally used by `Logger` to instantiate a new instance of `LogEntryEventBuilder` - * @param userSettings The instance of `LoggerSettings__c` for the current to use to control any feature flags - * @param entryLoggingLevel The `LoggingLevel` value to use for the log entry - * @param shouldSave Indicates if the builder's instance of `LogEntryEvent__e` should be saved - * @param ignoredOrigins A `Set` of the names of any Apex classes that should be ignored when parsing the entry's origin - */ - @SuppressWarnings('PMD.ExcessiveParameterList, PMD.NcssConstructorCount') - public LogEntryEventBuilder(LoggerSettings__c userSettings, System.LoggingLevel entryLoggingLevel, Boolean shouldSave, Set ignoredOrigins) { - // TOODO eliminate this constructor - this(userSettings, entryLoggingLevel, shouldSave); - } - /** * @description Used by `Logger` to instantiate a new instance of `LogEntryEventBuilder` * @param userSettings The instance of `LoggerSettings__c` for the current to use to control any feature flags @@ -136,45 +123,13 @@ global with sharing class LogEntryEventBuilder { @SuppressWarnings('PMD.NcssConstructorCount') public LogEntryEventBuilder(LoggerSettings__c userSettings, System.LoggingLevel entryLoggingLevel, Boolean shouldSave) { this.shouldSave = shouldSave; - if (this.shouldSave() == false) { - return; - } + if (this.shouldSave()) { + this.userSettings = userSettings; + this.entryLoggingLevel = entryLoggingLevel; - this.userSettings = userSettings; - this.entryLoggingLevel = entryLoggingLevel; - - Datetime timestamp = System.now(); - this.logEntryEvent = new LogEntryEvent__e( - EpochTimestamp__c = timestamp.getTime(), - LoggingLevel__c = entryLoggingLevel.name(), - LoggingLevelOrdinal__c = entryLoggingLevel.ordinal(), - OriginType__c = 'Apex', - Timestamp__c = timestamp, - TriggerIsExecuting__c = Trigger.isExecuting, - TriggerOperationType__c = Trigger.operationType?.name(), - TriggerSObjectType__c = Trigger.new?.getSObjectType().getDescribe().getName() - ); - - if (LoggerParameter.STORE_TRANSACTION_LIMITS) { - this.logEntryEvent.LimitsAggregateQueriesUsed__c = System.Limits.getAggregateQueries(); - this.logEntryEvent.LimitsAsyncCallsUsed__c = System.Limits.getAsyncCalls(); - this.logEntryEvent.LimitsCalloutsUsed__c = System.Limits.getCallouts(); - this.logEntryEvent.LimitsCpuTimeUsed__c = System.Limits.getCpuTime(); - this.logEntryEvent.LimitsDmlRowsUsed__c = System.Limits.getDmlRows(); - this.logEntryEvent.LimitsDmlStatementsUsed__c = System.Limits.getDmlStatements(); - this.logEntryEvent.LimitsEmailInvocationsUsed__c = System.Limits.getEmailInvocations(); - this.logEntryEvent.LimitsFutureCallsUsed__c = System.Limits.getFutureCalls(); - this.logEntryEvent.LimitsHeapSizeUsed__c = System.Limits.getHeapSize(); - this.logEntryEvent.LimitsMobilePushApexCallsUsed__c = System.Limits.getMobilePushApexCalls(); - this.logEntryEvent.LimitsQueueableJobsUsed__c = System.Limits.getQueueableJobs(); - this.logEntryEvent.LimitsPublishImmediateDmlStatementsUsed__c = System.Limits.getPublishImmediateDML(); - this.logEntryEvent.LimitsSoqlQueriesUsed__c = System.Limits.getQueries(); - this.logEntryEvent.LimitsSoqlQueryLocatorRowsUsed__c = System.Limits.getQueryLocatorRows(); - this.logEntryEvent.LimitsSoqlQueryRowsUsed__c = System.Limits.getQueryRows(); - this.logEntryEvent.LimitsSoslSearchesUsed__c = System.Limits.getSoslQueries(); - } - - this.parseStackTrace(); + this.logEntryEvent = getLogEntryEventTemplate(entryLoggingLevel); + this.setTimestamp(System.now()); + } } /** @@ -198,7 +153,7 @@ global with sharing class LogEntryEventBuilder { global LogEntryEventBuilder setMessage(String message) { // To help with debugging unit tests, always run System.debug statement in a test context if ((this.shouldSave() || System.Test.isRunningTest()) && this.logEntryEvent != null) { - String truncatedMessage = truncateFieldValue(Schema.LogEntryEvent__e.Message__c, message); + String truncatedMessage = LoggerDataStore.truncateFieldValue(Schema.LogEntryEvent__e.Message__c, message); Boolean messageTruncated = String.isNotBlank(message) && message.length() > Schema.LogEntryEvent__e.Message__c.getDescribe().getLength(); String cleanedMessage = applyDataMaskRules(this.userSettings.IsDataMaskingEnabled__c, truncatedMessage); Boolean messageMasked = cleanedMessage != truncatedMessage; @@ -221,7 +176,7 @@ global with sharing class LogEntryEventBuilder { return this; } - this.logEntryEvent.ExceptionMessage__c = apexException.getMessage(); + this.logEntryEvent.ExceptionMessage__c = LoggerDataStore.truncateFieldValue(Schema.LogEntryEvent__e.ExceptionMessage__c, apexException.getMessage()); this.logEntryEvent.ExceptionType__c = apexException.getTypeName(); LoggerStackTrace exceptionStackTrace = new LoggerStackTrace(apexException); @@ -229,7 +184,10 @@ global with sharing class LogEntryEventBuilder { this.logEntryEvent.ExceptionSourceActionName__c = exceptionStackTrace.Source?.ActionName; this.logEntryEvent.ExceptionSourceApiName__c = exceptionStackTrace.Source?.ApiName; this.logEntryEvent.ExceptionSourceMetadataType__c = exceptionStackTrace.Source?.MetadataType.name(); - this.logEntryEvent.ExceptionStackTrace__c = exceptionStackTrace.ParsedStackTraceString; + this.logEntryEvent.ExceptionStackTrace__c = LoggerDataStore.truncateFieldValue( + Schema.LogEntryEvent__e.ExceptionStackTrace__c, + exceptionStackTrace.ParsedStackTraceString + ); return this; } @@ -243,16 +201,11 @@ global with sharing class LogEntryEventBuilder { * @return The same instance of `LogEntryEventBuilder`, useful for chaining methods */ global LogEntryEventBuilder setDatabaseResult(Database.LeadConvertResult leadConvertResult) { - if (this.shouldSave() == false) { - return this; - } - - this.logEntryEvent.DatabaseResultCollectionSize__c = 1; - this.logEntryEvent.DatabaseResultCollectionType__c = 'Single'; - this.logEntryEvent.DatabaseResultJson__c = JSON.serializePretty(leadConvertResult); - this.logEntryEvent.DatabaseResultType__c = Database.LeadConvertResult.class.getName(); - - return this.setRecordId(leadConvertResult?.getLeadId()); + return this.setDatabaseDetails( + new List{ leadConvertResult }, + Database.LeadConvertResult.class, + leadConvertResult?.getLeadId() + ); } /** @@ -261,16 +214,7 @@ global with sharing class LogEntryEventBuilder { * @return The same instance of `LogEntryEventBuilder`, useful for chaining methods */ global LogEntryEventBuilder setDatabaseResult(List leadConvertResults) { - if (this.shouldSave() == false) { - return this; - } - - this.logEntryEvent.DatabaseResultCollectionSize__c = leadConvertResults.size(); - this.logEntryEvent.DatabaseResultCollectionType__c = 'List'; - this.logEntryEvent.DatabaseResultJson__c = JSON.serializePretty(leadConvertResults); - this.logEntryEvent.DatabaseResultType__c = Database.LeadConvertResult.class.getName(); - - return this; + return this.setDatabaseDetails(leadConvertResults, Database.LeadConvertResult.class, null); } /** @@ -279,16 +223,7 @@ global with sharing class LogEntryEventBuilder { * @return The same instance of `LogEntryEventBuilder`, useful for chaining methods */ global LogEntryEventBuilder setDatabaseResult(Database.DeleteResult deleteResult) { - if (this.shouldSave() == false) { - return this; - } - - this.logEntryEvent.DatabaseResultCollectionSize__c = 1; - this.logEntryEvent.DatabaseResultCollectionType__c = 'Single'; - this.logEntryEvent.DatabaseResultJson__c = JSON.serializePretty(deleteResult); - this.logEntryEvent.DatabaseResultType__c = Database.DeleteResult.class.getName(); - - return this.setRecordId(deleteResult?.getId()); + return this.setDatabaseDetails(new List{ deleteResult }, Database.DeleteResult.class, deleteResult?.getId()); } /** @@ -297,16 +232,7 @@ global with sharing class LogEntryEventBuilder { * @return The same instance of `LogEntryEventBuilder`, useful for chaining methods */ global LogEntryEventBuilder setDatabaseResult(Database.MergeResult mergeResult) { - if (this.shouldSave() == false) { - return this; - } - - this.logEntryEvent.DatabaseResultCollectionSize__c = 1; - this.logEntryEvent.DatabaseResultCollectionType__c = 'Single'; - this.logEntryEvent.DatabaseResultJson__c = JSON.serializePretty(mergeResult); - this.logEntryEvent.DatabaseResultType__c = Database.MergeResult.class.getName(); - - return this.setRecordId(mergeResult?.getId()); + return this.setDatabaseDetails(new List{ mergeResult }, Database.MergeResult.class, mergeResult?.getId()); } /** @@ -315,16 +241,7 @@ global with sharing class LogEntryEventBuilder { * @return The same instance of `LogEntryEventBuilder`, useful for chaining methods */ global LogEntryEventBuilder setDatabaseResult(Database.SaveResult saveResult) { - if (this.shouldSave() == false) { - return this; - } - - this.logEntryEvent.DatabaseResultCollectionSize__c = 1; - this.logEntryEvent.DatabaseResultCollectionType__c = 'Single'; - this.logEntryEvent.DatabaseResultJson__c = JSON.serializePretty(saveResult); - this.logEntryEvent.DatabaseResultType__c = Database.SaveResult.class.getName(); - - return this.setRecordId(saveResult?.getId()); + return this.setDatabaseDetails(new List{ saveResult }, Database.SaveResult.class, saveResult?.getId()); } /** @@ -333,19 +250,12 @@ global with sharing class LogEntryEventBuilder { * @return The same instance of `LogEntryEventBuilder`, useful for chaining methods */ global LogEntryEventBuilder setDatabaseResult(Database.UpsertResult upsertResult) { - if (this.shouldSave() == false) { - return this; + this.setDatabaseDetails(new List{ upsertResult }, Database.UpsertResult.class, upsertResult?.getId()); + if (upsertResult != null) { + String subtype = upsertResult.isCreated() ? 'Insert' : 'Update'; + this.logEntryEvent.DatabaseResultType__c += '.' + subtype; } - - // Upsert has 2 subtypes (surprise!) - insert and update - so, UpsertResult has an extra method to take into account - String subtype = upsertResult.isCreated() ? 'Insert' : 'Update'; - - this.logEntryEvent.DatabaseResultCollectionSize__c = 1; - this.logEntryEvent.DatabaseResultCollectionType__c = 'Single'; - this.logEntryEvent.DatabaseResultJson__c = JSON.serializePretty(upsertResult); - this.logEntryEvent.DatabaseResultType__c = Database.UpsertResult.class.getName() + '.' + subtype; - - return this.setRecordId(upsertResult?.getId()); + return this; } /** @@ -354,16 +264,7 @@ global with sharing class LogEntryEventBuilder { * @return The same instance of `LogEntryEventBuilder`, useful for chaining methods */ global LogEntryEventBuilder setDatabaseResult(Database.UndeleteResult undeleteResult) { - if (this.shouldSave() == false) { - return this; - } - - this.logEntryEvent.DatabaseResultCollectionSize__c = 1; - this.logEntryEvent.DatabaseResultCollectionType__c = 'Single'; - this.logEntryEvent.DatabaseResultJson__c = JSON.serializePretty(undeleteResult); - this.logEntryEvent.DatabaseResultType__c = Database.UndeleteResult.class.getName(); - - return this.setRecordId(undeleteResult?.getId()); + return this.setDatabaseDetails(new List{ undeleteResult }, Database.UndeleteResult.class, undeleteResult?.getId()); } /** @@ -372,16 +273,7 @@ global with sharing class LogEntryEventBuilder { * @return The same instance of `LogEntryEventBuilder`, useful for chaining methods */ global LogEntryEventBuilder setDatabaseResult(List deleteResults) { - if (this.shouldSave() == false) { - return this; - } - - this.logEntryEvent.DatabaseResultCollectionSize__c = deleteResults?.size(); - this.logEntryEvent.DatabaseResultCollectionType__c = 'List'; - this.logEntryEvent.DatabaseResultJson__c = JSON.serializePretty(deleteResults); - this.logEntryEvent.DatabaseResultType__c = Database.DeleteResult.class.getName(); - - return this; + return this.setDatabaseDetails(deleteResults, Database.DeleteResult.class, null); } /** @@ -390,16 +282,7 @@ global with sharing class LogEntryEventBuilder { * @return The same instance of `LogEntryEventBuilder`, useful for chaining methods */ global LogEntryEventBuilder setDatabaseResult(List mergeResults) { - if (this.shouldSave() == false) { - return this; - } - - this.logEntryEvent.DatabaseResultCollectionSize__c = mergeResults?.size(); - this.logEntryEvent.DatabaseResultCollectionType__c = 'List'; - this.logEntryEvent.DatabaseResultJson__c = JSON.serializePretty(mergeResults); - this.logEntryEvent.DatabaseResultType__c = Database.MergeResult.class.getName(); - - return this; + return this.setDatabaseDetails(mergeResults, Database.MergeResult.class, null); } /** @@ -408,16 +291,7 @@ global with sharing class LogEntryEventBuilder { * @return The same instance of `LogEntryEventBuilder`, useful for chaining methods */ global LogEntryEventBuilder setDatabaseResult(List saveResults) { - if (this.shouldSave() == false) { - return this; - } - - this.logEntryEvent.DatabaseResultCollectionSize__c = saveResults?.size(); - this.logEntryEvent.DatabaseResultCollectionType__c = 'List'; - this.logEntryEvent.DatabaseResultJson__c = JSON.serializePretty(saveResults); - this.logEntryEvent.DatabaseResultType__c = Database.SaveResult.class.getName(); - - return this; + return this.setDatabaseDetails(saveResults, Database.SaveResult.class, null); } /** @@ -426,16 +300,7 @@ global with sharing class LogEntryEventBuilder { * @return The same instance of `LogEntryEventBuilder`, useful for chaining methods */ global LogEntryEventBuilder setDatabaseResult(List upsertResults) { - if (this.shouldSave() == false) { - return this; - } - - this.logEntryEvent.DatabaseResultCollectionSize__c = upsertResults?.size(); - this.logEntryEvent.DatabaseResultCollectionType__c = 'List'; - this.logEntryEvent.DatabaseResultJson__c = JSON.serializePretty(upsertResults); - this.logEntryEvent.DatabaseResultType__c = Database.UpsertResult.class.getName(); - - return this; + return this.setDatabaseDetails(upsertResults, Database.UpsertResult.class, null); } /** @@ -444,16 +309,7 @@ global with sharing class LogEntryEventBuilder { * @return The same instance of `LogEntryEventBuilder`, useful for chaining methods */ global LogEntryEventBuilder setDatabaseResult(List undeleteResults) { - if (this.shouldSave() == false) { - return this; - } - - this.logEntryEvent.DatabaseResultCollectionSize__c = undeleteResults?.size(); - this.logEntryEvent.DatabaseResultCollectionType__c = 'List'; - this.logEntryEvent.DatabaseResultJson__c = JSON.serializePretty(undeleteResults); - this.logEntryEvent.DatabaseResultType__c = Database.UndeleteResult.class.getName(); - - return this; + return this.setDatabaseDetails(undeleteResults, Database.UndeleteResult.class, null); } /** @@ -514,7 +370,7 @@ global with sharing class LogEntryEventBuilder { this.logEntryEvent.RecordCollectionSize__c = 1; this.logEntryEvent.RecordCollectionType__c = 'Single'; - String truncatedRecordJson = truncateFieldValue( + String truncatedRecordJson = LoggerDataStore.truncateFieldValue( Schema.LogEntryEvent__e.RecordJson__c, getJson(record, this.userSettings.IsRecordFieldStrippingEnabled__c) ); @@ -551,7 +407,7 @@ global with sharing class LogEntryEventBuilder { this.logEntryEvent.RecordCollectionType__c = 'List'; Schema.SObjectType sobjectType = records?.getSObjectType(); - String truncatedRecordJson = truncateFieldValue( + String truncatedRecordJson = LoggerDataStore.truncateFieldValue( Schema.LogEntryEvent__e.RecordJson__c, getJson(records, this.userSettings.IsRecordFieldStrippingEnabled__c) ); @@ -588,7 +444,7 @@ global with sharing class LogEntryEventBuilder { List recordsList = recordIdToRecord?.values(); Schema.SObjectType sobjectType = recordIdToRecord?.size() > 0 ? recordsList.get(0)?.getSObjectType() : null; - String truncatedRecordJson = truncateFieldValue( + String truncatedRecordJson = LoggerDataStore.truncateFieldValue( Schema.LogEntryEvent__e.RecordJson__c, getJson(recordIdToRecord, this.userSettings.IsRecordFieldStrippingEnabled__c) ); @@ -620,7 +476,7 @@ global with sharing class LogEntryEventBuilder { return this; } - String truncatedRequestBody = truncateFieldValue(Schema.LogEntryEvent__e..HttpRequestBody__c, request.getBody()); + String truncatedRequestBody = LoggerDataStore.truncateFieldValue(Schema.LogEntryEvent__e.HttpRequestBody__c, request.getBody()); String cleanedRequestBody = applyDataMaskRules(this.userSettings.IsDataMaskingEnabled__c, truncatedRequestBody); Boolean requestBodyMasked = cleanedRequestBody != truncatedRequestBody; @@ -642,7 +498,7 @@ global with sharing class LogEntryEventBuilder { return this; } - String truncatedResponseBody = truncateFieldValue(Schema.LogEntryEvent__e..HttpRequestBody__c, response.getBody()); + String truncatedResponseBody = LoggerDataStore.truncateFieldValue(Schema.LogEntryEvent__e.HttpResponseBody__c, response.getBody()); String cleanedResponseBody = applyDataMaskRules(this.userSettings.IsDataMaskingEnabled__c, truncatedResponseBody); Boolean responseBodyMasked = cleanedResponseBody != truncatedResponseBody; @@ -657,7 +513,7 @@ global with sharing class LogEntryEventBuilder { this.logEntryEvent.HttpResponseBody__c = cleanedResponseBody; this.logEntryEvent.HttpResponseBodyMasked__c = responseBodyMasked; this.logEntryEvent.HttpResponseHeaderKeys__c = String.join(response.getHeaderKeys(), NEW_LINE_DELIMITER); - this.logEntryEvent.HttpResponseHeaders__c = formattedHeadersString; + this.logEntryEvent.HttpResponseHeaders__c = LoggerDataStore.truncateFieldValue(Schema.LogEntryEvent__e.HttpResponseHeaders__c, formattedHeadersString); this.logEntryEvent.HttpResponseStatus__c = response.getStatus(); this.logEntryEvent.HttpResponseStatusCode__c = response.getStatusCode(); return this; @@ -674,7 +530,7 @@ global with sharing class LogEntryEventBuilder { } String stringifiedRequestBody = request.requestBody?.toString(); - String truncatedRequestBody = truncateFieldValue(Schema.LogEntryEvent__e..RestRequestBody__c, stringifiedRequestBody); + String truncatedRequestBody = LoggerDataStore.truncateFieldValue(Schema.LogEntryEvent__e.RestRequestBody__c, stringifiedRequestBody); String cleanedRequestBody = applyDataMaskRules(this.userSettings.IsDataMaskingEnabled__c, truncatedRequestBody); Boolean requestBodyMasked = cleanedRequestBody != truncatedRequestBody; @@ -702,7 +558,7 @@ global with sharing class LogEntryEventBuilder { this.logEntryEvent.RestRequestBody__c = cleanedRequestBody; this.logEntryEvent.RestRequestBodyMasked__c = requestBodyMasked; this.logEntryEvent.RestRequestHeaderKeys__c = formattedHeaderKeysString; - this.logEntryEvent.RestRequestHeaders__c = formattedHeadersString; + this.logEntryEvent.RestRequestHeaders__c = LoggerDataStore.truncateFieldValue(Schema.LogEntryEvent__e.RestRequestHeaders__c, formattedHeadersString); this.logEntryEvent.RestRequestMethod__c = request.httpMethod; this.logEntryEvent.RestRequestParameters__c = formattedParametersString; this.logEntryEvent.RestRequestRemoteAddress__c = request.remoteAddress; @@ -722,7 +578,7 @@ global with sharing class LogEntryEventBuilder { } String stringifiedResponseBody = response.responseBody?.toString(); - String truncatedResponseBody = truncateFieldValue(Schema.LogEntryEvent__e.RestResponseBody__c, stringifiedResponseBody); + String truncatedResponseBody = LoggerDataStore.truncateFieldValue(Schema.LogEntryEvent__e.RestResponseBody__c, stringifiedResponseBody); String cleanedResponseBody = applyDataMaskRules(this.userSettings.IsDataMaskingEnabled__c, truncatedResponseBody); Boolean responseBodyMasked = cleanedResponseBody != truncatedResponseBody; @@ -742,7 +598,7 @@ global with sharing class LogEntryEventBuilder { this.logEntryEvent.RestResponseBody__c = cleanedResponseBody; this.logEntryEvent.RestResponseBodyMasked__c = responseBodyMasked; this.logEntryEvent.RestResponseHeaderKeys__c = formattedHeaderKeysString; - this.logEntryEvent.RestResponseHeaders__c = formattedHeadersString; + this.logEntryEvent.RestResponseHeaders__c = LoggerDataStore.truncateFieldValue(Schema.LogEntryEvent__e.RestResponseHeaders__c, formattedHeadersString); this.logEntryEvent.RestResponseStatusCode__c = response.statusCode; return this; } @@ -810,6 +666,38 @@ global with sharing class LogEntryEventBuilder { return this.shouldSave; } + /** + * @description **This is only intended to be used internally by Nebula Logger, and is subject to change.** + * @param loggingContext Variables specific to the current Logger state + * Sets information only available from the `Logger` class. + */ + public void setLoggingContext(LoggingContext loggingContext) { + this.logEntryEvent.ApiVersion__c = loggingContext.organizationApiVersion; + this.logEntryEvent.EntryScenario__c = loggingContext.currentEntryScenario; + this.logEntryEvent.LoggerVersionNumber__c = loggingContext.loggerVersionNumber; + this.logEntryEvent.OrganizationApiVersion__c = loggingContext.organizationApiVersion; + this.logEntryEvent.OrganizationDomainUrl__c = loggingContext.organizationDomainUrl; + this.logEntryEvent.RequestId__c = loggingContext.requestId; + this.logEntryEvent.SystemMode__c = loggingContext.systemMode?.name(); + this.logEntryEvent.TransactionEntryNumber__c = loggingContext.entryNumber; + this.logEntryEvent.TransactionId__c = loggingContext.transactionId; + this.logEntryEvent.UserLoggingLevel__c = loggingContext.userLoggingLevel.name(); + this.logEntryEvent.UserLoggingLevelOrdinal__c = loggingContext.userLoggingLevel.ordinal(); + } + + /** + * @description **This is only intended to be used internally by Nebula Logger, and is subject to change.** + * @param timestamp Datetime instance to set timestamp fields on this.logEntryEvent + */ + public void setTimestamp(Datetime timestamp) { + // Salesforce does not provide precise datetimes in Apex triggers for platform events + // Set the string value of timestamp to a second field as a workaround + // See https://developer.salesforce.com/docs/atlas.en-us.platform_events.meta/platform_events/platform_events_api_considerations.htm + this.logEntryEvent.EpochTimestamp__c = timestamp.getTime(); + this.logEntryEvent.Timestamp__c = timestamp; + this.logEntryEvent.TimestampString__c = '' + this.logEntryEvent.EpochTimestamp__c; + } + /** * @description Returns the `LogEntryEvent__e` record for this instance of LogEntryEventBuilder * @return The `LogEntryEvent__e` record @@ -821,9 +709,6 @@ global with sharing class LogEntryEventBuilder { // Lazy-loading of some details to help minimize Apex heap size usage until needed if (this.detailsAreSet == false) { - for (String fieldName : LOG_ENTRY_EVENT_TEMPLATE.getPopulatedFieldsAsMap().keySet()) { - this.logEntryEvent.put(fieldName, LOG_ENTRY_EVENT_TEMPLATE.get(fieldName)); - } if (this.userSettings.IsAnonymousModeEnabled__c == false) { setUserInfoDetails(this.logEntryEvent); setQueriedAuthSessionDetails(this.logEntryEvent, this.userSettings); @@ -843,13 +728,6 @@ global with sharing class LogEntryEventBuilder { this.tagDetailsAreSet = true; } - // Salesforce does not provide precise datetimes in Apex triggers for platform events - // Set the string value of timestamp to a second field as a workaround - // See https://developer.salesforce.com/docs/atlas.en-us.platform_events.meta/platform_events/platform_events_api_considerations.htm - if (this.logEntryEvent.Timestamp__c != null) { - this.logEntryEvent.TimestampString__c = String.valueOf(this.logEntryEvent.Timestamp__c.getTime()); - } - return this.logEntryEvent; } @@ -883,14 +761,6 @@ global with sharing class LogEntryEventBuilder { System.debug(this.entryLoggingLevel, this.debugMessage); } - private void parseStackTrace() { - if (this.shouldSave() == false || LoggerParameter.ENABLE_STACK_TRACE_PARSING == false) { - return; - } - - this.parseStackTrace(new LoggerStackTrace()); - } - private LogEntryEventBuilder parseStackTrace(LoggerStackTrace originStackTrace) { if (this.shouldSave() == false || LoggerParameter.ENABLE_STACK_TRACE_PARSING == false) { return this; @@ -900,10 +770,24 @@ global with sharing class LogEntryEventBuilder { this.logEntryEvent.OriginSourceActionName__c = originStackTrace.Source?.ActionName; this.logEntryEvent.OriginSourceApiName__c = originStackTrace.Source?.ApiName; this.logEntryEvent.OriginSourceMetadataType__c = originStackTrace.Source?.MetadataType.name(); - this.logEntryEvent.StackTrace__c = originStackTrace.ParsedStackTraceString; + this.logEntryEvent.StackTrace__c = LoggerDataStore.truncateFieldValue(Schema.LogEntryEvent__e.StackTrace__c, originStackTrace.ParsedStackTraceString); return this; } + private LogEntryEventBuilder setDatabaseDetails(List databaseResults, System.Type resultType, Id possibleRecordId) { + if (this.shouldSave() == false) { + return this; + } + + this.logEntryEvent.DatabaseResultCollectionSize__c = databaseResults.size(); + this.logEntryEvent.DatabaseResultCollectionType__c = this.logEntryEvent.DatabaseResultCollectionSize__c == 1 ? 'Single' : 'List'; + String serializedResult = JSON.serializePretty(this.logEntryEvent.DatabaseResultCollectionSize__c == 1 ? databaseResults.get(0) : databaseResults); + this.logEntryEvent.DatabaseResultJson__c = LoggerDataStore.truncateFieldValue(Schema.LogEntryEvent__e.DatabaseResultJson__c, serializedResult); + this.logEntryEvent.DatabaseResultType__c = resultType.getName(); + + return this.setRecordId(possibleRecordId); + } + private void setTagsDetails() { if (this.tags.isEmpty() || this.tagDetailsAreSet) { return; @@ -911,29 +795,60 @@ global with sharing class LogEntryEventBuilder { List sortedTags = new List(this.tags); sortedTags.sort(); - this.logEntryEvent.Tags__c = String.escapeSingleQuotes(String.join(sortedTags, NEW_LINE_DELIMITER)); + this.logEntryEvent.Tags__c = LoggerDataStore.truncateFieldValue( + Schema.LogEntryEvent__e.Tags__c, + String.escapeSingleQuotes(String.join(sortedTags, NEW_LINE_DELIMITER)) + ); } - private static LogEntryEvent__e getLogEntryEventTemplate() { - LogEntryEvent__e logEntryEventTemplate = new LogEntryEvent__e(); + private static LogEntryEvent__e getLogEntryEventTemplate(System.LoggingLevel entryLoggingLevel) { + LogEntryEvent__e logEntryEventTemplate = new LogEntryEvent__e( + LoggingLevel__c = entryLoggingLevel.name(), + LoggingLevelOrdinal__c = entryLoggingLevel.ordinal(), + OriginType__c = 'Apex', + TriggerIsExecuting__c = Trigger.isExecuting, + TriggerOperationType__c = Trigger.operationType?.name(), + TriggerSObjectType__c = Trigger.new?.getSObjectType().getDescribe().getName() + ); if (LoggerParameter.STORE_TRANSACTION_LIMITS) { - logEntryEventTemplate.LimitsAggregateQueriesMax__c = System.Limits.getLimitAggregateQueries(); - logEntryEventTemplate.LimitsAsyncCallsMax__c = System.Limits.getLimitAsyncCalls(); - logEntryEventTemplate.LimitsCalloutsMax__c = System.Limits.getLimitCallouts(); - logEntryEventTemplate.LimitsCpuTimeMax__c = System.Limits.getLimitCpuTime(); - logEntryEventTemplate.LimitsDmlRowsMax__c = System.Limits.getLimitDmlRows(); - logEntryEventTemplate.LimitsDmlStatementsMax__c = System.Limits.getLimitDmlStatements(); - logEntryEventTemplate.LimitsEmailInvocationsMax__c = System.Limits.getLimitEmailInvocations(); - logEntryEventTemplate.LimitsFutureCallsMax__c = System.Limits.getLimitFutureCalls(); - logEntryEventTemplate.LimitsHeapSizeMax__c = System.Limits.getLimitHeapSize(); - logEntryEventTemplate.LimitsMobilePushApexCallsMax__c = System.Limits.getLimitMobilePushApexCalls(); - logEntryEventTemplate.LimitsPublishImmediateDmlStatementsMax__c = System.Limits.getLimitPublishImmediateDML(); - logEntryEventTemplate.LimitsQueueableJobsMax__c = System.Limits.getLimitQueueableJobs(); - logEntryEventTemplate.LimitsSoqlQueriesMax__c = System.Limits.getLimitQueries(); - logEntryEventTemplate.LimitsSoqlQueryLocatorRowsMax__c = System.Limits.getLimitQueryLocatorRows(); - logEntryEventTemplate.LimitsSoqlQueryRowsMax__c = System.Limits.getLimitQueryRows(); - logEntryEventTemplate.LimitsSoslSearchesMax__c = System.Limits.getLimitSoslQueries(); + logEntryEventTemplate.LimitsAggregateQueriesMax__c = CACHED_TRANSACTION_LIMITS.aggregateQueriesMax; + logEntryEventTemplate.LimitsAsyncCallsMax__c = CACHED_TRANSACTION_LIMITS.asyncCallsMax; + logEntryEventTemplate.LimitsCalloutsMax__c = CACHED_TRANSACTION_LIMITS.calloutsMax; + logEntryEventTemplate.LimitsCpuTimeMax__c = CACHED_TRANSACTION_LIMITS.cpuTimeMax; + logEntryEventTemplate.LimitsDmlRowsMax__c = CACHED_TRANSACTION_LIMITS.dmlRowsMax; + logEntryEventTemplate.LimitsDmlStatementsMax__c = CACHED_TRANSACTION_LIMITS.dmlStatementsMax; + logEntryEventTemplate.LimitsEmailInvocationsMax__c = CACHED_TRANSACTION_LIMITS.emailInvocationsMax; + logEntryEventTemplate.LimitsFutureCallsMax__c = CACHED_TRANSACTION_LIMITS.futureCallsMax; + logEntryEventTemplate.LimitsHeapSizeMax__c = CACHED_TRANSACTION_LIMITS.heapSizeMax; + logEntryEventTemplate.LimitsMobilePushApexCallsMax__c = CACHED_TRANSACTION_LIMITS.mobilePushApexCallsMax; + logEntryEventTemplate.LimitsPublishImmediateDmlStatementsMax__c = CACHED_TRANSACTION_LIMITS.publishImmediateDmlStatementsMax; + logEntryEventTemplate.LimitsQueueableJobsMax__c = CACHED_TRANSACTION_LIMITS.queueableJobsMax; + logEntryEventTemplate.LimitsSoqlQueriesMax__c = CACHED_TRANSACTION_LIMITS.soqlQueriesMax; + logEntryEventTemplate.LimitsSoqlQueryLocatorRowsMax__c = CACHED_TRANSACTION_LIMITS.soqlQueryLocatorRowsMax; + logEntryEventTemplate.LimitsSoqlQueryRowsMax__c = CACHED_TRANSACTION_LIMITS.soqlQueryRowsMax; + logEntryEventTemplate.LimitsSoslSearchesMax__c = CACHED_TRANSACTION_LIMITS.soslSearchesMax; + + logEntryEventTemplate.LimitsAggregateQueriesUsed__c = System.Limits.getAggregateQueries(); + logEntryEventTemplate.LimitsAsyncCallsUsed__c = System.Limits.getAsyncCalls(); + logEntryEventTemplate.LimitsCalloutsUsed__c = System.Limits.getCallouts(); + logEntryEventTemplate.LimitsCpuTimeUsed__c = System.Limits.getCpuTime(); + logEntryEventTemplate.LimitsDmlRowsUsed__c = System.Limits.getDmlRows(); + logEntryEventTemplate.LimitsDmlStatementsUsed__c = System.Limits.getDmlStatements(); + logEntryEventTemplate.LimitsEmailInvocationsUsed__c = System.Limits.getEmailInvocations(); + logEntryEventTemplate.LimitsFutureCallsUsed__c = System.Limits.getFutureCalls(); + logEntryEventTemplate.LimitsMobilePushApexCallsUsed__c = System.Limits.getMobilePushApexCalls(); + logEntryEventTemplate.LimitsQueueableJobsUsed__c = System.Limits.getQueueableJobs(); + logEntryEventTemplate.LimitsPublishImmediateDmlStatementsUsed__c = System.Limits.getPublishImmediateDML(); + logEntryEventTemplate.LimitsSoqlQueriesUsed__c = System.Limits.getQueries(); + logEntryEventTemplate.LimitsSoqlQueryLocatorRowsUsed__c = System.Limits.getQueryLocatorRows(); + logEntryEventTemplate.LimitsSoqlQueryRowsUsed__c = System.Limits.getQueryRows(); + logEntryEventTemplate.LimitsSoslSearchesUsed__c = System.Limits.getSoslQueries(); + + // this is the most CPU-intensive Limits call BY FAR, so we gate it behind its own LoggerParameter record + if (LoggerParameter.STORE_HEAP_SIZE_LIMIT) { + logEntryEventTemplate.LimitsHeapSizeUsed__c = System.Limits.getHeapSize(); + } } return logEntryEventTemplate; @@ -1228,8 +1143,53 @@ global with sharing class LogEntryEventBuilder { return securityDecision.getRecords(); } - private static String truncateFieldValue(Schema.SObjectField field, String value) { - Integer fieldMaxLength = field.getDescribe().getLength(); - return value?.left(fieldMaxLength); + @SuppressWarnings('PMD.ApexDoc') + public class LoggingContext { + public String currentEntryScenario; + public String loggerVersionNumber; + public String organizationApiVersion; + public String organizationDomainUrl; + public String requestId; + public Integer entryNumber = 0; + public System.Quiddity systemMode; + public String transactionId; + public System.LoggingLevel userLoggingLevel; + + @SuppressWarnings('PMD.ExcessiveParameterList') + public LoggingContext( + String loggerVersionNumber, + String organizationApiVersion, + String organizationDomainUrl, + String requestId, + System.Quiddity systemMode, + String transactionId + ) { + this.loggerVersionNumber = loggerVersionNumber; + this.organizationApiVersion = organizationApiVersion; + this.organizationDomainUrl = organizationDomainUrl; + this.requestId = requestId; + this.systemMode = systemMode; + this.transactionId = transactionId; + } + } + + @SuppressWarnings('PMD.ApexDoc, PMD.TooManyFields') + private class TransactionLimits { + public final Integer aggregateQueriesMax = System.Limits.getLimitAggregateQueries(); + public final Integer asyncCallsMax = System.Limits.getLimitAsyncCalls(); + public final Integer calloutsMax = System.Limits.getLimitCallouts(); + public final Integer cpuTimeMax = System.Limits.getLimitCpuTime(); + public final Integer dmlRowsMax = System.Limits.getLimitDmlRows(); + public final Integer dmlStatementsMax = System.Limits.getLimitDmlStatements(); + public final Integer emailInvocationsMax = System.Limits.getLimitEmailInvocations(); + public final Integer futureCallsMax = System.Limits.getLimitFutureCalls(); + public final Integer heapSizeMax = System.Limits.getLimitHeapSize(); + public final Integer mobilePushApexCallsMax = System.Limits.getLimitMobilePushApexCalls(); + public final Integer publishImmediateDmlStatementsMax = System.Limits.getLimitPublishImmediateDML(); + public final Integer queueableJobsMax = System.Limits.getLimitQueueableJobs(); + public final Integer soqlQueriesMax = System.Limits.getLimitQueries(); + public final Integer soqlQueryLocatorRowsMax = System.Limits.getLimitQueryLocatorRows(); + public final Integer soqlQueryRowsMax = System.Limits.getLimitQueryRows(); + public final Integer soslSearchesMax = System.Limits.getLimitSoslQueries(); } } diff --git a/nebula-logger/core/main/logger-engine/classes/Logger.cls b/nebula-logger/core/main/logger-engine/classes/Logger.cls index 8a119d78b..b81c6f30e 100644 --- a/nebula-logger/core/main/logger-engine/classes/Logger.cls +++ b/nebula-logger/core/main/logger-engine/classes/Logger.cls @@ -10,12 +10,12 @@ * @see LogMessage */ @SuppressWarnings( - 'PMD.AvoidDebugStatements, PMD.AvoidGlobalModifier, PMD.CognitiveComplexity, PMD.CyclomaticComplexity, PMD.ExcessiveClassLength, PMD.ExcessivePublicCount, PMD.PropertyNamingConventions, PMD.StdCyclomaticComplexity' + 'PMD.AvoidDebugStatements, PMD.AvoidGlobalModifier, PMD.CognitiveComplexity, PMD.CyclomaticComplexity, PMD.ExcessiveClassLength, PMD.ExcessivePublicCount, PMD.NcssTypeCount, PMD.PropertyNamingConventions, PMD.StdCyclomaticComplexity' ) 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.13.4'; + private static final String CURRENT_VERSION_NUMBER = 'v4.13.5'; private static final System.LoggingLevel FALLBACK_LOGGING_LEVEL = System.LoggingLevel.DEBUG; private static final List LOG_ENTRIES_BUFFER = new List(); private static final String MISSING_SCENARIO_ERROR_MESSAGE = 'No logger scenario specified. A scenario is required for logging in this org.'; @@ -27,7 +27,6 @@ global with sharing class Logger { private static AsyncContext currentAsyncContext; private static String currentEntryScenario; - private static Integer currentTransactionEntryNumber = 1; @TestVisible private static String lastSaveMethodNameUsed; private static List orderedScenarios = new List(); @@ -38,6 +37,37 @@ global with sharing class Logger { private static String transactionScenario; private static LoggerSettings__c userSettings; + private static final List CLASSES_TO_IGNORE { + get { + if (CLASSES_TO_IGNORE == null) { + CLASSES_TO_IGNORE = new List{ + 'Class.' + Logger.class.getName(), + 'Class.' + LogEntryEventBuilder.class.getName(), + 'Class.' + LogMessage.class.getName() + }; + } + return CLASSES_TO_IGNORE; + } + set; + } + + private static final LogEntryEventBuilder.LoggingContext LOGGING_CONTEXT { + get { + if (LOGGING_CONTEXT == null) { + LOGGING_CONTEXT = new LogEntryEventBuilder.LoggingContext( + getVersionNumber(), + getOrganizationApiVersion(), + ORGANIZATION_DOMAIN_URL, + REQUEST_ID, + getCurrentQuiddity(), + getTransactionId() + ); + } + return LOGGING_CONTEXT; + } + set; + } + private static final String ORGANIZATION_API_VERSION { get { if (ORGANIZATION_API_VERSION == null) { @@ -54,17 +84,6 @@ global with sharing class Logger { set; } - private static final Database.DmlOptions PLATFORM_EVENT_DML_OPTIONS { - get { - if (PLATFORM_EVENT_DML_OPTIONS == null) { - PLATFORM_EVENT_DML_OPTIONS = new Database.DmlOptions(); - PLATFORM_EVENT_DML_OPTIONS.AllowFieldTruncation = true; - } - return PLATFORM_EVENT_DML_OPTIONS; - } - set; - } - private static final String USER_SESSION_ID { get { if (USER_SESSION_ID == null) { @@ -110,7 +129,6 @@ global with sharing class Logger { System.debug(System.LoggingLevel.INFO, 'Nebula Logger - Version Number: ' + getVersionNumber()); System.debug(System.LoggingLevel.INFO, 'Nebula Logger - Transaction ID: ' + getTransactionId()); System.debug(System.LoggingLevel.INFO, 'Nebula Logger - Organization API Version: ' + getOrganizationApiVersion()); - initializeIgnoredApexClasses(); setScenario(getUserSettings().DefaultScenario__c); } @@ -3197,8 +3215,9 @@ global with sharing class Logger { List logEntryEvents = new List(); for (LogEntryEventBuilder logEntryEventBuilder : LOG_ENTRIES_BUFFER) { if (logEntryEventBuilder.shouldSave()) { - finalizeEntry(logEntryEventBuilder); - logEntryEvents.add(logEntryEventBuilder.getLogEntryEvent()); + LogEntryEvent__e logEntryEvent = logEntryEventBuilder.getLogEntryEvent(); + finalizeEntry(logEntryEvent); + logEntryEvents.add(logEntryEvent); } } @@ -3222,7 +3241,7 @@ global with sharing class Logger { switch on getSaveMethod(saveMethodName) { when EVENT_BUS { - List saveResults = LoggerDataStore.getEventBus().publishRecords(logEntryEvents, PLATFORM_EVENT_DML_OPTIONS); + List saveResults = LoggerDataStore.getEventBus().publishRecords(logEntryEvents); LoggerEmailSender.sendErrorEmail(Schema.LogEntryEvent__e.SObjectType, saveResults); } when QUEUEABLE { @@ -3350,32 +3369,26 @@ global with sharing class Logger { } private static LogEntryEventBuilder newEntry(System.LoggingLevel loggingLevel, Boolean shouldSave) { - LogEntryEventBuilder logEntryEventBuilder = new LogEntryEventBuilder(getUserSettings(), loggingLevel, shouldSave); + LogEntryEventBuilder logEntryEventBuilder = new LogEntryEventBuilder(getUserSettings(), loggingLevel, shouldSave) + // Don't include the logging system's classes in the stack trace + .parseStackTrace( + new System.DmlException().getStackTraceString().replaceAll('(' + String.join(CLASSES_TO_IGNORE, '|') + ')\\..+?column 1', '').trim() + ); if (logEntryEventBuilder.shouldSave()) { if (LoggerParameter.REQUIRE_SCENARIO_USAGE && String.isBlank(currentEntryScenario)) { throw new LoggerException(MISSING_SCENARIO_ERROR_MESSAGE); } - - LogEntryEvent__e logEntryEvent = logEntryEventBuilder.getLogEntryEvent(); - logEntryEvent.ApiVersion__c = getOrganizationApiVersion(); - logEntryEvent.EntryScenario__c = currentEntryScenario; - logEntryEvent.LoggerVersionNumber__c = CURRENT_VERSION_NUMBER; - logEntryEvent.OrganizationApiVersion__c = getOrganizationApiVersion(); - logEntryEvent.OrganizationDomainUrl__c = ORGANIZATION_DOMAIN_URL; - logEntryEvent.RequestId__c = REQUEST_ID; - logEntryEvent.SystemMode__c = getCurrentQuiddity()?.name(); - logEntryEvent.TransactionEntryNumber__c = currentTransactionEntryNumber++; - logEntryEvent.TransactionId__c = getTransactionId(); - logEntryEvent.UserLoggingLevel__c = userLoggingLevel.name(); - logEntryEvent.UserLoggingLevelOrdinal__c = userLoggingLevel.ordinal(); + LOGGING_CONTEXT.currentEntryScenario = currentEntryScenario; + LOGGING_CONTEXT.entryNumber++; + LOGGING_CONTEXT.userLoggingLevel = userLoggingLevel; + logEntryEventBuilder.setLoggingContext(LOGGING_CONTEXT); LOG_ENTRIES_BUFFER.add(logEntryEventBuilder); } return logEntryEventBuilder; } - private static void finalizeEntry(LogEntryEventBuilder logEntryEventBuilder) { - LogEntryEvent__e logEntryEvent = logEntryEventBuilder.getLogEntryEvent(); + private static void finalizeEntry(LogEntryEvent__e logEntryEvent) { logEntryEvent.ParentLogTransactionId__c = getParentLogTransactionId(); logEntryEvent.TransactionScenario__c = transactionScenario; @@ -3387,10 +3400,6 @@ global with sharing class Logger { } } - private static void initializeIgnoredApexClasses() { - LoggerStackTrace.ignoreOrigins(new Set{ Logger.class, LogEntryEventBuilder.class, LogMessage.class }); - } - private static Boolean hasValidStartAndEndTimes(LoggerSettings__c settings) { Datetime nowish = System.now(); Boolean isStartTimeValid = settings.StartTime__c == null || settings.StartTime__c <= nowish; @@ -3494,7 +3503,7 @@ global with sharing class Logger { */ global void execute(System.QueueableContext queueableContext) { Logger.setAsyncContext(queueableContext); - LoggerDataStore.getEventBus().publishRecords(this.logEntryEvents, PLATFORM_EVENT_DML_OPTIONS); + LoggerDataStore.getEventBus().publishRecords(this.logEntryEvents); } } diff --git a/nebula-logger/core/main/logger-engine/classes/LoggerDataStore.cls b/nebula-logger/core/main/logger-engine/classes/LoggerDataStore.cls index 370913b99..60f469fa4 100644 --- a/nebula-logger/core/main/logger-engine/classes/LoggerDataStore.cls +++ b/nebula-logger/core/main/logger-engine/classes/LoggerDataStore.cls @@ -10,17 +10,6 @@ */ @SuppressWarnings('PMD.ExcessivePublicCount, PMD.PropertyNamingConventions') public without sharing class LoggerDataStore { - private static final Database.DmlOptions DEFAULT_PLATFORM_EVENT_DML_OPTIONS { - get { - if (DEFAULT_PLATFORM_EVENT_DML_OPTIONS == null) { - DEFAULT_PLATFORM_EVENT_DML_OPTIONS = new Database.DmlOptions(); - DEFAULT_PLATFORM_EVENT_DML_OPTIONS.AllowFieldTruncation = true; - } - return DEFAULT_PLATFORM_EVENT_DML_OPTIONS; - } - set; - } - private static Database databaseInstance { get { if (databaseInstance == null) { @@ -51,6 +40,16 @@ public without sharing class LoggerDataStore { set; } + /** + * @description Truncates a string field using the max field length allowed for that `Schema.SObjectField` + * @param field The `Schema.SObjectField` token to base the max field length off of + * @param value The `String` value to truncate + * @return The truncated value or null + */ + public static String truncateFieldValue(Schema.SObjectField field, String value) { + return value?.left(field.getDescribe().getLength()); + } + /** * @description The instance `LoggerDataStore.Database` used for any DML * operations in the current transaction. @@ -294,96 +293,27 @@ public without sharing class LoggerDataStore { */ @SuppressWarnings('PMD.StdCyclomaticComplexity') public virtual class EventBus { - private final Map> sobjectTypeToStringFieldNameToMaxLength = new Map>(); - @SuppressWarnings('PMD.EmptyStatementBlock') protected EventBus() { } /** - * @description Publishes a single platform event record, using `EventBus.publish(SObject record); + * @description Publishes a single platform event record, using `EventBus.publish(SObject record);` * @param platformEvent The platform event record to publish * @return The instance of `Database.SaveResult`, generated by the platform when publishing the platform event record */ public virtual Database.SaveResult publishRecord(SObject platformEvent) { - this.finalizeRecords(new List{ platformEvent }, DEFAULT_PLATFORM_EVENT_DML_OPTIONS); return System.EventBus.publish(platformEvent); } /** - * @description Publishes a list of platform event records, using `EventBus.publish(List records)` + * @description Publishes a list of platform event records, using `EventBus.publish(List records);` * @param platformEvents The list of platform event records to publish * @return The instance of `List`, generated by the platform when publishing the platform event records */ public virtual List publishRecords(List platformEvents) { - return this.publishRecords(platformEvents, DEFAULT_PLATFORM_EVENT_DML_OPTIONS); - } - - /** - * @description Publishes a list of platform event records, using `EventBus.publish(List records)`. The provided - * instance of `Database.DmlOptions` is used to control truncating of string fields before publishing the records. - * @param platformEvents The list of platform event records to publish - * @param dmlOptions An instance of `Database.DmlOptions`, used to control truncating of string fields - * @return The instance of `List`, generated by the platform when publishing the platform event records - */ - public virtual List publishRecords(List platformEvents, Database.DmlOptions dmlOptions) { - this.finalizeRecords(platformEvents, dmlOptions); return System.EventBus.publish(platformEvents); } - - protected void finalizeRecords(List platformEvents, Database.DmlOptions dmlOptions) { - if (dmlOptions == null) { - dmlOptions = DEFAULT_PLATFORM_EVENT_DML_OPTIONS; - } - - if (dmlOptions.AllowFieldTruncation == true) { - this.truncateStringFields(platformEvents); - } - } - - @SuppressWarnings('PMD.CognitiveComplexity, PMD.CyclomaticComplexity, PMD.StdCyclomaticComplexity') - private void truncateStringFields(List platformEvents) { - if (platformEvents == null || platformEvents.isEmpty()) { - return; - } - - Schema.SObjectType sobjectType = platformEvents.get(0)?.getSObjectType(); - if (sobjectType == null) { - return; - } - - Map stringFieldNameToMaxLength = this.getStringFieldNameToMaxLength(sobjectType); - for (SObject platformEvent : platformEvents) { - Map populatedFieldsAsMap = platformEvent.getPopulatedFieldsAsMap(); - for (String stringFieldName : stringFieldNameToMaxLength.keySet()) { - String stringValue = (String) populatedFieldsAsMap.get(stringFieldName); - - if (stringValue == null) { - continue; - } - - Integer fieldMaxLength = stringFieldNameToMaxLength.get(stringFieldName); - // String.abbreviate() will throw a StringException if the target length is less than 4 - String truncatedStringValue = fieldMaxLength < 4 ? stringValue.left(fieldMaxLength) : stringValue.abbreviate(fieldMaxLength); - platformEvent.put(stringFieldName, truncatedStringValue); - } - } - } - - private Map getStringFieldNameToMaxLength(Schema.SObjectType sobjectType) { - Map stringFieldNameToMaxLength = this.sobjectTypeToStringFieldNameToMaxLength.get(sobjectType); - if (stringFieldNameToMaxLength == null) { - stringFieldNameToMaxLength = new Map(); - for (Schema.SObjectField field : sobjectType.getDescribe().fields.getMap().values()) { - Schema.DescribeFieldResult fieldDescribe = field.getDescribe(); - if (fieldDescribe.getSoapType() == Schema.SoapType.STRING && fieldDescribe.isCreateable()) { - stringFieldNameToMaxLength.put(fieldDescribe.getName(), fieldDescribe.getLength()); - } - } - this.sobjectTypeToStringFieldNameToMaxLength.put(sobjectType, stringFieldNameToMaxLength); - } - return stringFieldNameToMaxLength; - } } /** diff --git a/nebula-logger/core/main/logger-engine/classes/LoggerStackTrace.cls b/nebula-logger/core/main/logger-engine/classes/LoggerStackTrace.cls index 1e96743a8..6731b1f3c 100644 --- a/nebula-logger/core/main/logger-engine/classes/LoggerStackTrace.cls +++ b/nebula-logger/core/main/logger-engine/classes/LoggerStackTrace.cls @@ -85,18 +85,6 @@ public without sharing class LoggerStackTrace { } } - /** - * @description Adds the specified Apex types to the list of ignored origin locations for the current transaction. - * Any ignored types will be removed from the StackTrace__c field, and will be skipped when determining - * the log entry's origin location - * @param apexTypes A `Set` containing the Apex types of the classes to ignore - */ - public static void ignoreOrigins(Set apexTypes) { - for (System.Type apexType : apexTypes) { - ignoreOrigin(apexType); - } - } - /** * @description Constructor that automatically generates & parses stack trace information * based on the calling code @@ -343,7 +331,6 @@ public without sharing class LoggerStackTrace { languageIgnoredOrigins = IGNORED_JAVASCRIPT_ORIGINS; } } - // Don't include the logging system's classes in the stack trace Boolean ignoreLine = false; for (String ignoredOrigin : languageIgnoredOrigins) { String formattedOrigin; diff --git a/nebula-logger/core/main/logger-engine/lwc/logger/logEntryBuilder.js b/nebula-logger/core/main/logger-engine/lwc/logger/logEntryBuilder.js index c7127b616..4417dd44f 100644 --- a/nebula-logger/core/main/logger-engine/lwc/logger/logEntryBuilder.js +++ b/nebula-logger/core/main/logger-engine/lwc/logger/logEntryBuilder.js @@ -4,7 +4,7 @@ //------------------------------------------------------------------------------------------------// import FORM_FACTOR from '@salesforce/client/formFactor'; -const CURRENT_VERSION_NUMBER = 'v4.13.4'; +const CURRENT_VERSION_NUMBER = 'v4.13.5'; // JavaScript equivalent to the Apex class ComponentLogger.ComponentLogEntry const ComponentLogEntry = class { diff --git a/nebula-logger/core/tests/configuration/utilities/LoggerMockDataCreator.cls b/nebula-logger/core/tests/configuration/utilities/LoggerMockDataCreator.cls index 723afbbca..6a8628436 100644 --- a/nebula-logger/core/tests/configuration/utilities/LoggerMockDataCreator.cls +++ b/nebula-logger/core/tests/configuration/utilities/LoggerMockDataCreator.cls @@ -11,7 +11,7 @@ * @see LoggerMockDataStore * @see LoggerTestConfigurator */ -@SuppressWarnings('PMD.CyclomaticComplexity, PMD.ExcessivePublicCount, PMD.MethodNamingConventions, PMD.PropertyNamingConventions') +@SuppressWarnings('PMD.CyclomaticComplexity, PMD.CognitiveComplexity, PMD.ExcessivePublicCount, PMD.MethodNamingConventions, PMD.PropertyNamingConventions') @IsTest public class LoggerMockDataCreator { private static final Map> SOBJECT_TYPE_TO_ALL_FIELDS = new Map>(); diff --git a/nebula-logger/core/tests/logger-engine/classes/LogEntryEventBuilder_Tests.cls b/nebula-logger/core/tests/logger-engine/classes/LogEntryEventBuilder_Tests.cls index 6203f9620..7f748adba 100644 --- a/nebula-logger/core/tests/logger-engine/classes/LogEntryEventBuilder_Tests.cls +++ b/nebula-logger/core/tests/logger-engine/classes/LogEntryEventBuilder_Tests.cls @@ -4,7 +4,7 @@ //------------------------------------------------------------------------------------------------// @SuppressWarnings( - 'PMD.ApexDoc, PMD.ApexAssertionsShouldIncludeMessage, PMD.CyclomaticComplexity, PMD.ExcessiveParameterList, PMD.MethodNamingConventions, PMD.NcssMethodCount' + 'PMD.ApexDoc, PMD.ApexAssertionsShouldIncludeMessage, PMD.CognitiveComplexity, PMD.CyclomaticComplexity, PMD.ExcessiveParameterList, PMD.MethodNamingConventions, PMD.NcssMethodCount, PMD.NcssTypeCount' ) @IsTest(IsParallel=false) private class LogEntryEventBuilder_Tests { @@ -14,7 +14,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_short_circuit_when_disabled() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.DEBUG, false, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.DEBUG, false); // Run all public and global methods to make sure no errors occur when not enabled (it's happened before) System.Assert.isNull(builder.setMessage(getLogMessage()).getLogEntryEvent()); @@ -41,13 +41,13 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_short_circuit_when_enabled_logging_level_above_called_level() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.FINE, false, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.FINE, false); System.Assert.isNull(builder.getLogEntryEvent()); } @IsTest static void it_should_not_short_circuit_when_enabled() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.FINE, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.FINE, true); System.Assert.isNotNull(builder.getLogEntryEvent()); } @@ -65,9 +65,7 @@ private class LogEntryEventBuilder_Tests { userSettings.IsEnabled__c = false; System.Assert.areEqual(0, System.Limits.getQueries()); - new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, userSettings.IsEnabled__c, new Set()) - .setMessage('some message') - .getLogEntryEvent(); + new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, userSettings.IsEnabled__c).setMessage('some message').getLogEntryEvent(); System.Assert.areEqual(0, System.Limits.getQueries()); } @@ -75,7 +73,9 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_transaction_limits_fields_when_enabled_via_logger_parameter() { LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'StoreTransactionLimits', Value__c = JSON.serialize(true))); + LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'StoreHeapSizeLimit', Value__c = JSON.serialize(true))); System.Assert.isTrue(LoggerParameter.STORE_TRANSACTION_LIMITS); + System.Assert.isTrue(LoggerParameter.STORE_HEAP_SIZE_LIMIT); // Capture these limits first, before creating an instance of LogEntryEventBuilder - the builder runs several queries internally, // so capturing afterwards leads to inaccurate numbers Integer expectedQueryCount = System.Limits.getQueries(); @@ -120,6 +120,28 @@ private class LogEntryEventBuilder_Tests { System.Assert.areEqual(System.Limits.getLimitSoslQueries(), logEntryEvent.LimitsSoslSearchesMax__c); } + @IsTest + static void it_should_not_set_transaction_heap_limits_fields_when_disabled_via_logger_parameter() { + LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'StoreTransactionLimits', Value__c = JSON.serialize(true))); + LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'StoreHeapSizeLimit', Value__c = JSON.serialize(false))); + System.Assert.isTrue(LoggerParameter.STORE_TRANSACTION_LIMITS); + + LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true).getLogEntryEvent(); + + System.Assert.isNull(logEntryEvent.LimitsHeapSizeUsed__c); + } + + @IsTest + static void it_should_not_set_transaction_heap_limits_fields_when_transaction_limit_tracking_is_disabled_via_logger_parameter() { + LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'StoreTransactionLimits', Value__c = JSON.serialize(false))); + LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'StoreHeapSizeLimit', Value__c = JSON.serialize(true))); + System.Assert.isFalse(LoggerParameter.STORE_TRANSACTION_LIMITS); + + LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true).getLogEntryEvent(); + + System.Assert.isNull(logEntryEvent.LimitsHeapSizeUsed__c); + } + @IsTest static void it_should_not_set_transaction_limits_fields_when_disabled_via_logger_parameter() { LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'StoreTransactionLimits', Value__c = JSON.serialize(false))); @@ -169,7 +191,7 @@ private class LogEntryEventBuilder_Tests { LoggerEngineDataSelector.setMock(mockSelector); System.Assert.areEqual(0, mockSelector.getCachedAuthSessionQueryCount()); - LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()) + LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true) .setMessage('some message') .getLogEntryEvent(); @@ -194,7 +216,7 @@ private class LogEntryEventBuilder_Tests { LoggerEngineDataSelector.setMock(mockSelector); System.Assert.areEqual(0, mockSelector.getCachedAuthSessionQueryCount()); - LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()) + LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true) .setMessage('some message') .getLogEntryEvent(); @@ -220,7 +242,7 @@ private class LogEntryEventBuilder_Tests { LoggerEngineDataSelector.setMock(mockSelector); System.Assert.areEqual(0, mockSelector.getCachedOrganizationQueryCount()); - LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()) + LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true) .setMessage('some message') .getLogEntryEvent(); @@ -240,7 +262,7 @@ private class LogEntryEventBuilder_Tests { LoggerEngineDataSelector.setMock(mockSelector); System.Assert.areEqual(0, mockSelector.getCachedOrganizationQueryCount()); - LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()) + LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true) .setMessage('some message') .getLogEntryEvent(); @@ -261,7 +283,7 @@ private class LogEntryEventBuilder_Tests { LoggerEngineDataSelector.setMock(mockSelector); System.Assert.areEqual(0, mockSelector.getCachedUserQueryCount()); - LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()) + LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true) .setMessage('some message') .getLogEntryEvent(); @@ -282,7 +304,7 @@ private class LogEntryEventBuilder_Tests { LoggerEngineDataSelector.setMock(mockSelector); System.Assert.areEqual(0, mockSelector.getCachedUserQueryCount()); - LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()) + LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true) .setMessage('some message') .getLogEntryEvent(); @@ -296,25 +318,9 @@ private class LogEntryEventBuilder_Tests { System.Assert.areEqual(cachedUser.UserRole?.Name, logEntryEvent.UserRoleName__c); } - @IsTest - static void it_should_keep_timestamp_string_in_sync_with_timestamp() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()) - .setMessage('some message'); - - for (Integer i = 0; i < 5; i++) { - builder.getLogEntryEvent().Timestamp__c = builder.getLogEntryEvent().Timestamp__c.addSeconds(i); - - System.Assert.areEqual( - String.valueOf(builder.getLogEntryEvent().Timestamp__c.getTime()), - builder.getLogEntryEvent().TimestampString__c, - 'Timestamp string was inaccurate when i ==' + i - ); - } - } - @IsTest static void it_should_set_message_fields_for_logMessage() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isFalse(builder.getLogEntryEvent().MessageTruncated__c); System.Assert.isFalse(builder.getLogEntryEvent().MessageMasked__c); System.Assert.isNull(builder.getLogEntryEvent().Message__c); @@ -329,7 +335,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_message_fields_for_null_logMessage() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isFalse(builder.getLogEntryEvent().MessageTruncated__c); System.Assert.isFalse(builder.getLogEntryEvent().MessageMasked__c); System.Assert.isNull(builder.getLogEntryEvent().Message__c); @@ -344,7 +350,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_message_fields_for_string() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isFalse(builder.getLogEntryEvent().MessageTruncated__c); System.Assert.isFalse(builder.getLogEntryEvent().MessageMasked__c); System.Assert.isNull(builder.getLogEntryEvent().Message__c); @@ -359,7 +365,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_message_fields_for_null_string() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isFalse(builder.getLogEntryEvent().MessageTruncated__c); System.Assert.isFalse(builder.getLogEntryEvent().MessageMasked__c); System.Assert.isNull(builder.getLogEntryEvent().Message__c); @@ -374,7 +380,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_truncate_message_field_when_string_is_too_long() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isFalse(builder.getLogEntryEvent().MessageTruncated__c); System.Assert.isFalse(builder.getLogEntryEvent().MessageMasked__c); System.Assert.isNull(builder.getLogEntryEvent().Message__c); @@ -400,7 +406,7 @@ private class LogEntryEventBuilder_Tests { Schema.Account account = new Schema.Account(Name = message); String accountJson = JSON.serializePretty(account); - LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true); builder.setMessage(message).setRecord(account); System.Assert.isFalse(builder.getLogEntryEvent().MessageMasked__c, builder.getLogEntryEvent().Message__c); @@ -420,7 +426,7 @@ private class LogEntryEventBuilder_Tests { Schema.Account account = new Schema.Account(Name = message); String accountJson = JSON.serializePretty(account); - LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true); builder.setMessage(message).setRecord(account); System.Assert.isFalse(builder.getLogEntryEvent().MessageMasked__c); @@ -439,7 +445,7 @@ private class LogEntryEventBuilder_Tests { String sensitiveString = 'Something, something, and my social is 400 11 9999 in case you want to steal my identity'; String expectedSanitizedString = 'Something, something, and my social is XXX-XX-9999 in case you want to steal my identity'; - LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true); builder.setMessage(sensitiveString); System.Assert.isTrue(builder.getLogEntryEvent().MessageMasked__c); @@ -460,7 +466,7 @@ private class LogEntryEventBuilder_Tests { String accountJson = JSON.serializePretty(account); String expectedSanitizedAccountJson = JSON.serializePretty(new Schema.Account(Name = expectedSanitizedString)); - LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true); builder.setRecord(account); System.Assert.isTrue(builder.getLogEntryEvent().RecordJsonMasked__c); @@ -481,7 +487,7 @@ private class LogEntryEventBuilder_Tests { List accounts = new List{ new Schema.Account(Name = sensitiveString) }; String accountListJson = JSON.serializePretty(accounts); String expectedSanitizedAccountListJson = JSON.serializePretty(new List{ new Schema.Account(Name = expectedSanitizedString) }); - LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true); builder.setRecord(accounts); System.Assert.isTrue(builder.getLogEntryEvent().RecordJsonMasked__c); @@ -501,7 +507,7 @@ private class LogEntryEventBuilder_Tests { System.HttpRequest httpRequest = LoggerMockDataCreator.createHttpRequest(); httpRequest.setBody(sensitiveString); - LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true); builder.setHttpRequestDetails(httpRequest); System.Assert.isTrue(builder.getLogEntryEvent().HttpRequestBodyMasked__c); @@ -521,7 +527,7 @@ private class LogEntryEventBuilder_Tests { System.HttpResponse httpResponse = LoggerMockDataCreator.createHttpResponse(); httpResponse.setBody(sensitiveString); - LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true); builder.setHttpResponseDetails(httpResponse); System.Assert.isTrue(builder.getLogEntryEvent().HttpResponseBodyMasked__c); @@ -541,7 +547,7 @@ private class LogEntryEventBuilder_Tests { System.RestRequest restRequest = new System.RestRequest(); restRequest.requestBody = Blob.valueOf(sensitiveString); - LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true); builder.setRestRequestDetails(restRequest); System.Assert.isTrue(builder.getLogEntryEvent().RestRequestBodyMasked__c); @@ -561,7 +567,7 @@ private class LogEntryEventBuilder_Tests { System.RestResponse restResponse = new System.RestResponse(); restResponse.responseBody = Blob.valueOf(sensitiveString); - LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true); builder.setRestResponseDetails(restResponse); System.Assert.isTrue(builder.getLogEntryEvent().RestResponseBodyMasked__c); @@ -571,7 +577,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_truncate_message_for_long_logMessage() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isFalse(builder.getLogEntryEvent().MessageTruncated__c); System.Assert.isFalse(builder.getLogEntryEvent().MessageMasked__c); System.Assert.isNull(builder.getLogEntryEvent().Message__c); @@ -589,7 +595,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_truncate_message_for_long_string() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isFalse(builder.getLogEntryEvent().MessageTruncated__c); System.Assert.isFalse(builder.getLogEntryEvent().MessageMasked__c); System.Assert.isNull(builder.getLogEntryEvent().Message__c); @@ -605,7 +611,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_skip_setting_exception_fields_when_exception_is_null() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().ExceptionMessage__c); System.Assert.isNull(builder.getLogEntryEvent().ExceptionType__c); @@ -618,7 +624,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_exception_fields_for_dmlException() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().ExceptionMessage__c); System.Assert.isNull(builder.getLogEntryEvent().ExceptionType__c); @@ -634,7 +640,7 @@ private class LogEntryEventBuilder_Tests { Database.LeadConvertResult leadConvertResult = LoggerMockDataCreator.createDatabaseLeadConvertResult(true); System.Assert.isNotNull(leadConvertResult); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.setDatabaseResult(leadConvertResult); System.Assert.areEqual(1, builder.getLogEntryEvent().DatabaseResultCollectionSize__c); @@ -648,7 +654,7 @@ private class LogEntryEventBuilder_Tests { Database.DeleteResult deleteResult = LoggerMockDataCreator.createDatabaseDeleteResult(true); System.Assert.isNotNull(deleteResult); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.setDatabaseResult(deleteResult); System.Assert.areEqual(1, builder.getLogEntryEvent().DatabaseResultCollectionSize__c); @@ -662,7 +668,7 @@ private class LogEntryEventBuilder_Tests { Database.MergeResult mergeResult = LoggerMockDataCreator.createDatabaseMergeResult(true); System.Assert.isNotNull(mergeResult); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.setDatabaseResult(mergeResult); System.Assert.areEqual(1, builder.getLogEntryEvent().DatabaseResultCollectionSize__c); @@ -676,7 +682,7 @@ private class LogEntryEventBuilder_Tests { Database.SaveResult saveResult = LoggerMockDataCreator.createDatabaseSaveResult(true); System.Assert.isNotNull(saveResult); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.setDatabaseResult(saveResult); System.Assert.areEqual(1, builder.getLogEntryEvent().DatabaseResultCollectionSize__c); @@ -690,7 +696,7 @@ private class LogEntryEventBuilder_Tests { Database.UndeleteResult undeleteResult = LoggerMockDataCreator.createDatabaseUndeleteResult(true); System.Assert.isNotNull(undeleteResult); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.setDatabaseResult(undeleteResult); System.Assert.areEqual(1, builder.getLogEntryEvent().DatabaseResultCollectionSize__c); @@ -705,7 +711,7 @@ private class LogEntryEventBuilder_Tests { System.Assert.isNotNull(upsertResult); System.Assert.isTrue(upsertResult.isCreated()); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.setDatabaseResult(upsertResult); System.Assert.areEqual(1, builder.getLogEntryEvent().DatabaseResultCollectionSize__c); @@ -720,7 +726,7 @@ private class LogEntryEventBuilder_Tests { System.Assert.isNotNull(upsertResult); System.Assert.isFalse(upsertResult.isCreated()); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.setDatabaseResult(upsertResult); System.Assert.areEqual(1, builder.getLogEntryEvent().DatabaseResultCollectionSize__c); @@ -736,7 +742,7 @@ private class LogEntryEventBuilder_Tests { leadConvertResults.add(LoggerMockDataCreator.createDatabaseLeadConvertResult(false)); } - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.setDatabaseResult(leadConvertResults); System.Assert.areEqual(leadConvertResults.size(), builder.getLogEntryEvent().DatabaseResultCollectionSize__c); @@ -752,7 +758,7 @@ private class LogEntryEventBuilder_Tests { deleteResults.add(LoggerMockDataCreator.createDatabaseDeleteResult(false)); } - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.setDatabaseResult(deleteResults); System.Assert.areEqual(deleteResults.size(), builder.getLogEntryEvent().DatabaseResultCollectionSize__c); @@ -768,7 +774,7 @@ private class LogEntryEventBuilder_Tests { mergeResults.add(LoggerMockDataCreator.createDatabaseMergeResult(false)); } - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.setDatabaseResult(mergeResults); System.Assert.areEqual(mergeResults.size(), builder.getLogEntryEvent().DatabaseResultCollectionSize__c); @@ -784,7 +790,7 @@ private class LogEntryEventBuilder_Tests { saveResults.add(LoggerMockDataCreator.createDatabaseSaveResult(false)); } - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.setDatabaseResult(saveResults); System.Assert.areEqual(saveResults.size(), builder.getLogEntryEvent().DatabaseResultCollectionSize__c); @@ -800,7 +806,7 @@ private class LogEntryEventBuilder_Tests { undeleteResults.add(LoggerMockDataCreator.createDatabaseUndeleteResult(false)); } - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.setDatabaseResult(undeleteResults); System.Assert.areEqual(undeleteResults.size(), builder.getLogEntryEvent().DatabaseResultCollectionSize__c); @@ -816,7 +822,7 @@ private class LogEntryEventBuilder_Tests { upsertResults.add(LoggerMockDataCreator.createDatabaseUpsertResult(false, false)); } - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.setDatabaseResult(upsertResults); System.Assert.areEqual(upsertResults.size(), builder.getLogEntryEvent().DatabaseResultCollectionSize__c); @@ -827,7 +833,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_recordId_when_standard_object() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -848,7 +854,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_recordId_when_template_standard_object() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -869,7 +875,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_recordId_when_custom_object() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -889,7 +895,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_recordId_when_custom_metadata_type() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -909,7 +915,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_record_when_null() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -931,7 +937,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_record_when_standard_object() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -952,7 +958,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_record_when_custom_object() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -972,7 +978,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_record_when_custom_metadata_type() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -992,7 +998,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_record_when_platform_event() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -1020,7 +1026,7 @@ private class LogEntryEventBuilder_Tests { System.runAs(standardUser) { LoggerSettings__c userSettings = getUserSettings(); userSettings.IsRecordFieldStrippingEnabled__c = true; - builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()).setRecord(mockAggregateResult); + builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true).setRecord(mockAggregateResult); } System.Assert.areEqual(JSON.serializePretty(mockAggregateResult), builder.getLogEntryEvent().RecordJson__c); @@ -1035,7 +1041,7 @@ private class LogEntryEventBuilder_Tests { System.runAs(standardUser) { LoggerSettings__c userSettings = getUserSettings(); userSettings.IsRecordFieldStrippingEnabled__c = true; - builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()).setRecord(mockAggregateResults); + builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true).setRecord(mockAggregateResults); } System.Assert.areEqual(JSON.serializePretty(mockAggregateResults), builder.getLogEntryEvent().RecordJson__c); @@ -1043,7 +1049,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_list_of_records_when_list_is_null() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -1063,7 +1069,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_list_of_records_when_list_is_empty() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -1083,7 +1089,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_list_of_records_when_first_record_is_null() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -1105,7 +1111,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_list_of_records_when_populated() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -1124,7 +1130,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_map_of_sobject_records_when_map_is_null() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -1145,7 +1151,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_map_of_sobject_records_when_map_is_empty() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -1166,7 +1172,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_map_of_sobject_records_when_map_contains_null_key() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -1187,7 +1193,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_map_of_sobject_records_when_first_record_is_null() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -1213,7 +1219,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_record_fields_for_map_of_user_records_when_populated() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); System.Assert.isNull(builder.getLogEntryEvent().RecordJson__c); System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectClassification__c); @@ -1233,7 +1239,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_skip_setting_http_request_fields_when_request_is_null() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestBody__c); System.Assert.isFalse(builder.getLogEntryEvent().HttpRequestCompressed__c); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestEndpoint__c); @@ -1250,7 +1256,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_http_request_fields_when_request_is_populated() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestBody__c); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestEndpoint__c); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestMethod__c); @@ -1270,7 +1276,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_truncate_http_request_body_field_when_string_is_too_long() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestBody__c); String excessivelyLongRequestBody = 'a'.repeat(Schema.LogEntryEvent__e.HttpRequestBody__c.getDescribe().getLength() + 1); System.HttpRequest request = new System.HttpRequest(); @@ -1290,7 +1296,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_skip_setting_http_response_fields_when_response_is_null() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestBody__c); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestEndpoint__c); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestMethod__c); @@ -1310,7 +1316,7 @@ private class LogEntryEventBuilder_Tests { LoggerParameter__mdt mockParameter = new LoggerParameter__mdt(DeveloperName = 'StoreHttpResponseHeaderValues', Value__c = String.valueOf(true)); LoggerParameter.setMock(mockParameter); System.Assert.isTrue(LoggerParameter.STORE_HTTP_RESPONSE_HEADER_VALUES); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestBody__c); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestEndpoint__c); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestMethod__c); @@ -1339,7 +1345,7 @@ private class LogEntryEventBuilder_Tests { LoggerParameter__mdt mockParameter = new LoggerParameter__mdt(DeveloperName = 'StoreHttpResponseHeaderValues', Value__c = String.valueOf(false)); LoggerParameter.setMock(mockParameter); System.Assert.isFalse(LoggerParameter.STORE_HTTP_RESPONSE_HEADER_VALUES); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestBody__c); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestEndpoint__c); System.Assert.isNull(builder.getLogEntryEvent().HttpRequestMethod__c); @@ -1361,7 +1367,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_truncate_http_response_body_field_when_string_is_too_long() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().HttpResponseBody__c); String excessivelyLongResponseBody = 'a'.repeat(Schema.LogEntryEvent__e.HttpResponseBody__c.getDescribe().getLength() + 1); System.HttpResponse response = new System.HttpResponse(); @@ -1381,7 +1387,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_skip_setting_rest_response_fields_when_response_is_null() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RestResponseBody__c); System.Assert.isNull(builder.getLogEntryEvent().RestResponseHeaderKeys__c); System.Assert.isNull(builder.getLogEntryEvent().RestResponseHeaders__c); @@ -1401,7 +1407,7 @@ private class LogEntryEventBuilder_Tests { LoggerParameter__mdt mockParameter = new LoggerParameter__mdt(DeveloperName = 'StoreRestRequestHeaderValues', Value__c = String.valueOf(true)); LoggerParameter.setMock(mockParameter); System.Assert.isTrue(LoggerParameter.STORE_Rest_REQUEST_HEADER_VALUES); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RestRequestBody__c); System.Assert.isNull(builder.getLogEntryEvent().RestRequestHeaderKeys__c); System.Assert.isNull(builder.getLogEntryEvent().RestRequestHeaders__c); @@ -1444,7 +1450,7 @@ private class LogEntryEventBuilder_Tests { LoggerParameter__mdt mockParameter = new LoggerParameter__mdt(DeveloperName = 'StoreRestRequestHeaderValues', Value__c = String.valueOf(false)); LoggerParameter.setMock(mockParameter); System.Assert.isFalse(LoggerParameter.STORE_REST_REQUEST_HEADER_VALUES); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RestRequestBody__c); System.Assert.isNull(builder.getLogEntryEvent().RestRequestHeaderKeys__c); System.Assert.isNull(builder.getLogEntryEvent().RestRequestHeaders__c); @@ -1480,7 +1486,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_truncate_rest_request_body_field_when_string_is_too_long() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RestRequestBody__c); String excessivelyLongRequestBody = 'a'.repeat(Schema.LogEntryEvent__e.RestRequestBody__c.getDescribe().getLength() + 1); System.RestRequest request = new System.RestRequest(); @@ -1503,7 +1509,7 @@ private class LogEntryEventBuilder_Tests { LoggerParameter__mdt mockParameter = new LoggerParameter__mdt(DeveloperName = 'StoreRestResponseHeaderValues', Value__c = String.valueOf(true)); LoggerParameter.setMock(mockParameter); System.Assert.isTrue(LoggerParameter.STORE_Rest_RESPONSE_HEADER_VALUES); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RestResponseBody__c); System.Assert.isNull(builder.getLogEntryEvent().RestResponseHeaderKeys__c); System.Assert.isNull(builder.getLogEntryEvent().RestResponseHeaders__c); @@ -1530,7 +1536,7 @@ private class LogEntryEventBuilder_Tests { LoggerParameter__mdt mockParameter = new LoggerParameter__mdt(DeveloperName = 'StoreRestResponseHeaderValues', Value__c = String.valueOf(false)); LoggerParameter.setMock(mockParameter); System.Assert.isFalse(LoggerParameter.STORE_REST_RESPONSE_HEADER_VALUES); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RestResponseBody__c); System.Assert.isNull(builder.getLogEntryEvent().RestResponseHeaderKeys__c); System.Assert.isNull(builder.getLogEntryEvent().RestResponseHeaders__c); @@ -1551,7 +1557,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_truncate_rest_response_body_field_when_string_is_too_long() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().RestResponseBody__c); String excessivelyLongResponseBody = 'a'.repeat(Schema.LogEntryEvent__e.RestResponseBody__c.getDescribe().getLength() + 1); System.RestResponse response = new System.RestResponse(); @@ -1571,7 +1577,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_set_tags_string_for_list_of_tags() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().Tags__c); List tags = new List{ 'some-tag', 'another One', 'here\'s one more!' }; @@ -1584,7 +1590,7 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_deduplicate_and_sort_tags() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().Tags__c); List tags = new List{ 'duplicate-tag', 'duplicate-tag', 'another One' }; @@ -1606,7 +1612,7 @@ private class LogEntryEventBuilder_Tests { LoggerParameter.setMock(mockParameter); System.Assert.isFalse(LoggerParameter.ENABLE_STACK_TRACE_PARSING); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isNull(builder.getLogEntryEvent().OriginLocation__c); System.Assert.isNull(builder.getLogEntryEvent().StackTrace__c); @@ -1623,7 +1629,7 @@ private class LogEntryEventBuilder_Tests { LoggerParameter__mdt mockParameter = new LoggerParameter__mdt(DeveloperName = 'EnableStackTraceParsing', Value__c = String.valueOf(false)); LoggerParameter.setMock(mockParameter); System.Assert.isFalse(LoggerParameter.ENABLE_STACK_TRACE_PARSING); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); builder.parseStackTrace('AnonymousBlock: line 1, column 1'); @@ -1641,7 +1647,7 @@ private class LogEntryEventBuilder_Tests { DebugStringExample constructedClass = new DebugStringExample(); LoggerStackTrace originStackTrace = new LoggerStackTrace(constructedClass.getStackTraceString()); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.FINE, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.FINE, true); builder.getLogEntryEvent().OriginLocation__c = null; builder.getLogEntryEvent().OriginSourceActionName__c = null; builder.getLogEntryEvent().OriginSourceApiName__c = null; @@ -1667,7 +1673,7 @@ private class LogEntryEventBuilder_Tests { System.DmlException someException = new System.DmlException('Whoops, it broke 😭'); LoggerStackTrace exceptionStackTrace = new LoggerStackTrace(someException); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.FINE, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.FINE, true); builder.getLogEntryEvent().ExceptionLocation__c = null; builder.getLogEntryEvent().ExceptionSourceActionName__c = null; builder.getLogEntryEvent().ExceptionSourceApiName__c = null; @@ -1685,13 +1691,13 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_return_value_of_shouldSave_when_true() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); System.Assert.isTrue(builder.shouldSave()); } @IsTest static void it_should_return_value_of_shouldSave_when_false() { - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, false, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, false); System.Assert.isFalse(builder.shouldSave()); } @@ -1703,7 +1709,7 @@ private class LogEntryEventBuilder_Tests { String organizationEnvironmentType = LoggerMockDataCreator.getOrganizationEnvironmentType(); Schema.User user = LoggerMockDataCreator.getUser(); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); // Verify organization fields System.Assert.areEqual(organizationEnvironmentType, builder.getLogEntryEvent().OrganizationEnvironmentType__c); @@ -1728,7 +1734,7 @@ private class LogEntryEventBuilder_Tests { LoggerSettings__c userSettings = getUserSettings(); userSettings.IsAnonymousModeEnabled__c = true; - LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.DEBUG, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.DEBUG, true); System.Assert.isNull(builder.getLogEntryEvent().Locale__c); System.Assert.isNull(builder.getLogEntryEvent().LoggedById__c); @@ -1822,7 +1828,8 @@ private class LogEntryEventBuilder_Tests { } public LogEntryEventBuilder myMethod(LoggerSettings__c userSettings) { - return new LogEntryEventBuilder(userSettings, System.LoggingLevel.DEBUG, true, new Set{ LogEntryEventBuilder.class.getName() }) + return new LogEntryEventBuilder(userSettings, System.LoggingLevel.DEBUG, true) + .parseStackTrace(new System.DmlException().getStackTraceString()) .setMessage(loggingString); } } diff --git a/nebula-logger/core/tests/logger-engine/classes/LoggerDataStore_Tests.cls b/nebula-logger/core/tests/logger-engine/classes/LoggerDataStore_Tests.cls index dda3c7b85..6eed144be 100644 --- a/nebula-logger/core/tests/logger-engine/classes/LoggerDataStore_Tests.cls +++ b/nebula-logger/core/tests/logger-engine/classes/LoggerDataStore_Tests.cls @@ -525,69 +525,6 @@ private class LoggerDataStore_Tests { } } - @IsTest - static void it_should_automatically_truncate_platform_event_string_fields_when_dml_options_not_provided() { - List logEntryEventsToPublish = new List(); - String originalValue = 'a'.repeat(Schema.LogEntryEvent__e.TransactionId__c.getDescribe().getLength() + 1); - String expectedTruncatedValue = originalValue.abbreviate(Schema.LogEntryEvent__e.TransactionId__c.getDescribe().getLength()); - LogEntryEvent__e logEntryEvent = (LogEntryEvent__e) LoggerMockDataCreator.createDataBuilder(Schema.LogEntryEvent__e.SObjectType) - .populateRequiredFields() - .getRecord(); - logEntryEvent.TransactionId__c = originalValue; - logEntryEventsToPublish.add(logEntryEvent); - System.Assert.areEqual(0, System.Limits.getPublishImmediateDml()); - - List results = LoggerDataStore.getEventBus().publishRecords(logEntryEventsToPublish); - - System.Assert.areEqual(logEntryEventsToPublish.size(), results.size()); - System.Assert.isTrue(results.get(0).isSuccess()); - System.Assert.areEqual(1, System.Limits.getPublishImmediateDml(), results.toString()); - System.Assert.areNotEqual(originalValue, logEntryEvent.TransactionId__c); - System.Assert.areEqual(expectedTruncatedValue, logEntryEvent.TransactionId__c); - } - - @IsTest - static void it_should_automatically_truncate_platform_event_string_fields_when_allow_truncation_dml_option_is_true() { - List logEntryEventsToPublish = new List(); - String originalValue = 'a'.repeat(Schema.LogEntryEvent__e.TransactionId__c.getDescribe().getLength() + 1); - String expectedTruncatedValue = originalValue.abbreviate(Schema.LogEntryEvent__e.TransactionId__c.getDescribe().getLength()); - LogEntryEvent__e logEntryEvent = (LogEntryEvent__e) LoggerMockDataCreator.createDataBuilder(Schema.LogEntryEvent__e.SObjectType) - .populateRequiredFields() - .getRecord(); - logEntryEvent.TransactionId__c = originalValue; - logEntryEventsToPublish.add(logEntryEvent); - System.Assert.areEqual(0, System.Limits.getPublishImmediateDml()); - - Database.DmlOptions truncationDmlOptions = new Database.DmlOptions(); - truncationDmlOptions.AllowFieldTruncation = true; - List results = LoggerDataStore.getEventBus().publishRecords(logEntryEventsToPublish, truncationDmlOptions); - - System.Assert.areEqual(logEntryEventsToPublish.size(), results.size()); - System.Assert.isTrue(results.get(0).isSuccess()); - System.Assert.areEqual(1, System.Limits.getPublishImmediateDml(), results.toString()); - System.Assert.areNotEqual(originalValue, logEntryEvent.TransactionId__c); - System.Assert.areEqual(expectedTruncatedValue, logEntryEvent.TransactionId__c); - } - - @IsTest - static void it_should_not_automatically_truncate_platform_event_string_fields_when_allow_truncation_dml_option_is_false() { - List logEntryEventsToPublish = new List(); - LogEntryEvent__e logEntryEvent = (LogEntryEvent__e) LoggerMockDataCreator.createDataBuilder(Schema.LogEntryEvent__e.SObjectType) - .populateRequiredFields() - .getRecord(); - logEntryEvent.TransactionId__c = 'a'.repeat(Schema.LogEntryEvent__e.TransactionId__c.getDescribe().getLength() + 1); - logEntryEventsToPublish.add(logEntryEvent); - System.Assert.areEqual(0, System.Limits.getPublishImmediateDml()); - - Database.DmlOptions truncationDmlOptions = new Database.DmlOptions(); - truncationDmlOptions.AllowFieldTruncation = false; - List results = LoggerDataStore.getEventBus().publishRecords(logEntryEventsToPublish, truncationDmlOptions); - - System.Assert.areEqual(logEntryEventsToPublish.size(), results.size()); - System.Assert.isFalse(results.get(0).isSuccess()); - System.Assert.areEqual(System.StatusCode.STRING_TOO_LONG, results.get(0).getErrors().get(0).getStatusCode()); - } - // Queueable tests @IsTest static void it_should_enqueue_job() { diff --git a/nebula-logger/core/tests/logger-engine/classes/Logger_Tests.cls b/nebula-logger/core/tests/logger-engine/classes/Logger_Tests.cls index ee0ca5a90..6c1aa5284 100644 --- a/nebula-logger/core/tests/logger-engine/classes/Logger_Tests.cls +++ b/nebula-logger/core/tests/logger-engine/classes/Logger_Tests.cls @@ -1029,26 +1029,6 @@ private class Logger_Tests { System.Assert.areEqual(0, System.Limits.getDmlStatements()); } - @IsTest - static void it_should_pass_dml_options_to_data_store_when_saving_via_event_bus() { - LoggerDataStore.setMock(LoggerMockDataStore.getEventBus()); - System.Assert.areEqual(0, Logger.getBufferSize()); - System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size()); - System.Assert.areEqual(Logger.SaveMethod.EVENT_BUS.name(), Logger.getUserSettings().DefaultSaveMethod__c); - System.Assert.isTrue(Logger.getUserSettings().IsSavingEnabled__c); - System.Assert.isTrue(Logger.isDebugEnabled()); - Logger.debug('test log entry'); - System.Assert.areEqual(1, Logger.getBufferSize()); - - Logger.saveLog(); - - System.Assert.areEqual(0, Logger.getBufferSize()); - System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size()); - Database.DmlOptions lastUsedDmlOptions = LoggerMockDataStore.getEventBus().getLastUsedDmlOptions(); - System.Assert.isNotNull(lastUsedDmlOptions); - System.Assert.areEqual(true, lastUsedDmlOptions?.AllowFieldTruncation); - } - @IsTest static void it_should_save_via_event_bus_when_defaulted() { // TODO eliminate references to Log__c, find alternative way to assert on expected data @@ -7163,7 +7143,7 @@ private class Logger_Tests { System.Assert.isTrue(returnedBuilder.shouldSave()); System.Assert.areEqual(message, returnedBuilder.getLogEntryEvent().Message__c); System.Assert.areEqual(1, returnedBuilder.getLogEntryEvent().DatabaseResultCollectionSize__c); - String expectedDatabaseResultJson = JSON.serializePretty(new List{ unsuccessfulResult }); + String expectedDatabaseResultJson = JSON.serializePretty(unsuccessfulResult); System.Assert.areEqual(expectedDatabaseResultJson, returnedBuilder.getLogEntryEvent().DatabaseResultJson__c); } @@ -7256,7 +7236,7 @@ private class Logger_Tests { System.Assert.isTrue(returnedBuilder.shouldSave()); System.Assert.areEqual(logMessage.getMessage(), returnedBuilder.getLogEntryEvent().Message__c); System.Assert.areEqual(1, returnedBuilder.getLogEntryEvent().DatabaseResultCollectionSize__c); - String expectedDatabaseResultJson = JSON.serializePretty(new List{ unsuccessfulResult }); + String expectedDatabaseResultJson = JSON.serializePretty(unsuccessfulResult); System.Assert.areEqual(expectedDatabaseResultJson, returnedBuilder.getLogEntryEvent().DatabaseResultJson__c); } @@ -7313,7 +7293,7 @@ private class Logger_Tests { System.Assert.isTrue(returnedBuilder.shouldSave()); System.Assert.areEqual(message, returnedBuilder.getLogEntryEvent().Message__c); System.Assert.areEqual(1, returnedBuilder.getLogEntryEvent().DatabaseResultCollectionSize__c); - String expectedDatabaseResultJson = JSON.serializePretty(new List{ unsuccessfulResult }); + String expectedDatabaseResultJson = JSON.serializePretty(unsuccessfulResult); System.Assert.areEqual(expectedDatabaseResultJson, returnedBuilder.getLogEntryEvent().DatabaseResultJson__c); } @@ -7370,7 +7350,7 @@ private class Logger_Tests { System.Assert.isTrue(returnedBuilder.shouldSave()); System.Assert.areEqual(logMessage.getMessage(), returnedBuilder.getLogEntryEvent().Message__c); System.Assert.areEqual(1, returnedBuilder.getLogEntryEvent().DatabaseResultCollectionSize__c); - String expectedDatabaseResultJson = JSON.serializePretty(new List{ unsuccessfulResult }); + String expectedDatabaseResultJson = JSON.serializePretty(unsuccessfulResult); System.Assert.areEqual(expectedDatabaseResultJson, returnedBuilder.getLogEntryEvent().DatabaseResultJson__c); } @@ -7427,7 +7407,7 @@ private class Logger_Tests { System.Assert.isTrue(returnedBuilder.shouldSave()); System.Assert.areEqual(message, returnedBuilder.getLogEntryEvent().Message__c); System.Assert.areEqual(1, returnedBuilder.getLogEntryEvent().DatabaseResultCollectionSize__c); - String expectedDatabaseResultJson = JSON.serializePretty(new List{ unsuccessfulResult }); + String expectedDatabaseResultJson = JSON.serializePretty(unsuccessfulResult); System.Assert.areEqual(expectedDatabaseResultJson, returnedBuilder.getLogEntryEvent().DatabaseResultJson__c); } @@ -7484,7 +7464,7 @@ private class Logger_Tests { System.Assert.isTrue(returnedBuilder.shouldSave()); System.Assert.areEqual(logMessage.getMessage(), returnedBuilder.getLogEntryEvent().Message__c); System.Assert.areEqual(1, returnedBuilder.getLogEntryEvent().DatabaseResultCollectionSize__c); - String expectedDatabaseResultJson = JSON.serializePretty(new List{ unsuccessfulResult }); + String expectedDatabaseResultJson = JSON.serializePretty(unsuccessfulResult); System.Assert.areEqual(expectedDatabaseResultJson, returnedBuilder.getLogEntryEvent().DatabaseResultJson__c); } @@ -7541,7 +7521,7 @@ private class Logger_Tests { System.Assert.isTrue(returnedBuilder.shouldSave()); System.Assert.areEqual(message, returnedBuilder.getLogEntryEvent().Message__c); System.Assert.areEqual(1, returnedBuilder.getLogEntryEvent().DatabaseResultCollectionSize__c); - String expectedDatabaseResultJson = JSON.serializePretty(new List{ unsuccessfulResult }); + String expectedDatabaseResultJson = JSON.serializePretty(unsuccessfulResult); System.Assert.areEqual(expectedDatabaseResultJson, returnedBuilder.getLogEntryEvent().DatabaseResultJson__c); } @@ -7598,7 +7578,7 @@ private class Logger_Tests { System.Assert.isTrue(returnedBuilder.shouldSave()); System.Assert.areEqual(logMessage.getMessage(), returnedBuilder.getLogEntryEvent().Message__c); System.Assert.areEqual(1, returnedBuilder.getLogEntryEvent().DatabaseResultCollectionSize__c); - String expectedDatabaseResultJson = JSON.serializePretty(new List{ unsuccessfulResult }); + String expectedDatabaseResultJson = JSON.serializePretty(unsuccessfulResult); System.Assert.areEqual(expectedDatabaseResultJson, returnedBuilder.getLogEntryEvent().DatabaseResultJson__c); } @@ -7655,7 +7635,7 @@ private class Logger_Tests { System.Assert.isTrue(returnedBuilder.shouldSave()); System.Assert.areEqual(message, returnedBuilder.getLogEntryEvent().Message__c); System.Assert.areEqual(1, returnedBuilder.getLogEntryEvent().DatabaseResultCollectionSize__c); - String expectedDatabaseResultJson = JSON.serializePretty(new List{ unsuccessfulResult }); + String expectedDatabaseResultJson = JSON.serializePretty(unsuccessfulResult); System.Assert.areEqual(expectedDatabaseResultJson, returnedBuilder.getLogEntryEvent().DatabaseResultJson__c); } @@ -7712,7 +7692,7 @@ private class Logger_Tests { System.Assert.isTrue(returnedBuilder.shouldSave()); System.Assert.areEqual(logMessage.getMessage(), returnedBuilder.getLogEntryEvent().Message__c); System.Assert.areEqual(1, returnedBuilder.getLogEntryEvent().DatabaseResultCollectionSize__c); - String expectedDatabaseResultJson = JSON.serializePretty(new List{ unsuccessfulResult }); + String expectedDatabaseResultJson = JSON.serializePretty(unsuccessfulResult); System.Assert.areEqual(expectedDatabaseResultJson, returnedBuilder.getLogEntryEvent().DatabaseResultJson__c); } @@ -7769,7 +7749,7 @@ private class Logger_Tests { System.Assert.isTrue(returnedBuilder.shouldSave()); System.Assert.areEqual(message, returnedBuilder.getLogEntryEvent().Message__c); System.Assert.areEqual(1, returnedBuilder.getLogEntryEvent().DatabaseResultCollectionSize__c); - String expectedDatabaseResultJson = JSON.serializePretty(new List{ unsuccessfulResult }); + String expectedDatabaseResultJson = JSON.serializePretty(unsuccessfulResult); System.Assert.areEqual(expectedDatabaseResultJson, returnedBuilder.getLogEntryEvent().DatabaseResultJson__c); } // End logDatabaseErrors() test methods diff --git a/nebula-logger/core/tests/logger-engine/utilities/LoggerMockDataStore.cls b/nebula-logger/core/tests/logger-engine/utilities/LoggerMockDataStore.cls index 86a597200..c748d657e 100644 --- a/nebula-logger/core/tests/logger-engine/utilities/LoggerMockDataStore.cls +++ b/nebula-logger/core/tests/logger-engine/utilities/LoggerMockDataStore.cls @@ -12,7 +12,7 @@ * @see LoggerMockDataCreator * @see LoggerTestConfigurator */ -@SuppressWarnings('PMD.ApexDoc, PMD.EmptyStatementBlock') +@SuppressWarnings('PMD.ApexDoc, PMD.CognitiveComplexity, PMD.EmptyStatementBlock') @IsTest public without sharing class LoggerMockDataStore { private static final Map> SOBJECT_TYPE_TO_ALL_FIELDS = new Map>(); @@ -67,7 +67,6 @@ public without sharing class LoggerMockDataStore { } public class MockEventBus extends LoggerDataStore.EventBus { - private Database.DmlOptions lastUsedDmlOptions; private List publishedPlatformEvents; private Integer publishCount; @@ -76,10 +75,6 @@ public without sharing class LoggerMockDataStore { this.publishCount = 0; } - public Database.DmlOptions getLastUsedDmlOptions() { - return this.lastUsedDmlOptions; - } - public Integer getPublishCallCount() { return this.publishCount; } @@ -93,15 +88,9 @@ public without sharing class LoggerMockDataStore { } public override List publishRecords(List platformEvents) { - return this.publishRecords(platformEvents, null); - } - - public override List publishRecords(List platformEvents, Database.DmlOptions dmlOptions) { this.publishCount++; this.publishedPlatformEvents.addAll(platformEvents); - this.lastUsedDmlOptions = dmlOptions; - this.finalizeRecords(platformEvents, dmlOptions); List mockSaveResults = new List(); for (SObject platformEvent : platformEvents) { mockSaveResults.add(validateBeforeSave(platformEvent, false)); diff --git a/nebula-logger/extra-tests/tests/LogEntryEventBuilder_Tests_Network.cls b/nebula-logger/extra-tests/tests/LogEntryEventBuilder_Tests_Network.cls index c1e06b20c..86fef9d64 100644 --- a/nebula-logger/extra-tests/tests/LogEntryEventBuilder_Tests_Network.cls +++ b/nebula-logger/extra-tests/tests/LogEntryEventBuilder_Tests_Network.cls @@ -24,7 +24,7 @@ private class LogEntryEventBuilder_Tests_Network { LogEntryEvent__e logEntryEvent; System.runAs(experienceSiteUser) { - logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()).getLogEntryEvent(); + logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true).getLogEntryEvent(); } System.Assert.areEqual(networkRecord.get('Id'), logEntryEvent.NetworkId__c); @@ -51,7 +51,7 @@ private class LogEntryEventBuilder_Tests_Network { LogEntryEvent__e logEntryEvent; System.runAs(experienceSiteUser) { - logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()).getLogEntryEvent(); + logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true).getLogEntryEvent(); } System.Assert.isNull(logEntryEvent.NetworkName__c); diff --git a/nebula-logger/extra-tests/tests/LogEntryEventBuilder_Tests_Security.cls b/nebula-logger/extra-tests/tests/LogEntryEventBuilder_Tests_Security.cls index bb252bd28..7baaffd03 100644 --- a/nebula-logger/extra-tests/tests/LogEntryEventBuilder_Tests_Security.cls +++ b/nebula-logger/extra-tests/tests/LogEntryEventBuilder_Tests_Security.cls @@ -33,7 +33,7 @@ private class LogEntryEventBuilder_Tests_Security { LoggerSettings__c userSettings = getUserSettings(); userSettings.IsRecordFieldStrippingEnabled__c = true; - builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()).setRecord(mockAccountBrand); + builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true).setRecord(mockAccountBrand); } System.Assert.areNotEqual( @@ -80,7 +80,7 @@ private class LogEntryEventBuilder_Tests_Security { LoggerSettings__c userSettings = getUserSettings(); userSettings.IsRecordFieldStrippingEnabled__c = true; - builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()).setRecord(mockAccountBrands); + builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true).setRecord(mockAccountBrands); } System.Assert.areNotEqual(JSON.serializePretty(mockAccountBrands), builder.getLogEntryEvent().RecordJson__c, 'Record JSON is incorrect.'); @@ -126,7 +126,7 @@ private class LogEntryEventBuilder_Tests_Security { LoggerSettings__c userSettings = getUserSettings(); userSettings.IsRecordFieldStrippingEnabled__c = true; - builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()).setRecord(mockIdToAccountBrand); + builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true).setRecord(mockIdToAccountBrand); } System.Assert.areEqual(JSON.serializePretty(mockIdStringToStrippedAccountBrand), builder.getLogEntryEvent().RecordJson__c, 'Record JSON is incorrect.'); diff --git a/nebula-logger/extra-tests/tests/LoggerBenchmarking_Tests.cls b/nebula-logger/extra-tests/tests/LoggerBenchmarking_Tests.cls new file mode 100644 index 000000000..432e73c1a --- /dev/null +++ b/nebula-logger/extra-tests/tests/LoggerBenchmarking_Tests.cls @@ -0,0 +1,55 @@ +@SuppressWarnings('PMD.MethodNamingConventions') +@IsTest +private class LoggerBenchmarking_Tests { + private static final LoggerParameter__mdt ORG_LIMIT_PARAM = new LoggerParameter__mdt(DeveloperName = 'StoreOrganizationLimits'); + private static final LoggerParameter__mdt HEAP_LIMIT_PARAM = new LoggerParameter__mdt(DeveloperName = 'StoreHeapSizeLimit'); + private static final LoggerParameter__mdt TRANSACTION_LIMIT_PARAM = new LoggerParameter__mdt(DeveloperName = 'StoreTransactionLimits'); + + @IsTest + static void it_benchmarks_while_setting_transaction_limits() { + TRANSACTION_LIMIT_PARAM.Value__c = String.valueOf(true); + HEAP_LIMIT_PARAM.Value__c = TRANSACTION_LIMIT_PARAM.Value__c; + ORG_LIMIT_PARAM.Value__c = TRANSACTION_LIMIT_PARAM.Value__c; + + logForEntries(500); + + System.Assert.isTrue(true, 'Made it here without an uncatchable System.LimitException being thrown'); + } + + @IsTest + static void it_benchmarks_without_setting_heap_limit() { + TRANSACTION_LIMIT_PARAM.Value__c = String.valueOf(true); + HEAP_LIMIT_PARAM.Value__c = String.valueOf(false); + ORG_LIMIT_PARAM.Value__c = TRANSACTION_LIMIT_PARAM.Value__c; + + logForEntries(500); + + System.Assert.isTrue(true, 'Made it here without an uncatchable System.LimitException being thrown'); + } + + @IsTest + static void it_benchmarks_without_setting_limit_info() { + // the majority of the time it takes for Log Entries to be created is actually due to the System.Limits + // invocations within LogEntryEventBuilder. When those calls are disabled, Logger is MUCH more performant in tests + TRANSACTION_LIMIT_PARAM.Value__c = String.valueOf(false); + HEAP_LIMIT_PARAM.Value__c = TRANSACTION_LIMIT_PARAM.Value__c; + ORG_LIMIT_PARAM.Value__c = TRANSACTION_LIMIT_PARAM.Value__c; + + logForEntries(800); + + System.Assert.isTrue(true, 'Made it here without an uncatchable System.LimitException being thrown'); + } + + static void logForEntries(Integer numberOfEntries) { + LoggerParameter.setMock(HEAP_LIMIT_PARAM); + LoggerParameter.setMock(ORG_LIMIT_PARAM); + LoggerParameter.setMock(TRANSACTION_LIMIT_PARAM); + + ContactPointAddress record = new ContactPointAddress(Name = 'Benchmarking'); + insert record; + for (Integer index = 0; index < numberOfEntries; index++) { + Logger.info('Creating complex message using arguments').setRecord(record); + } + Logger.saveLog(); + } +} diff --git a/nebula-logger/extra-tests/tests/LoggerBenchmarking_Tests.cls-meta.xml b/nebula-logger/extra-tests/tests/LoggerBenchmarking_Tests.cls-meta.xml new file mode 100644 index 000000000..df13efa80 --- /dev/null +++ b/nebula-logger/extra-tests/tests/LoggerBenchmarking_Tests.cls-meta.xml @@ -0,0 +1,5 @@ + + + 60.0 + Active + diff --git a/nebula-logger/extra-tests/tests/Logger_Tests_MergeResult.cls b/nebula-logger/extra-tests/tests/Logger_Tests_MergeResult.cls index 10d2b3adb..d2be05d78 100644 --- a/nebula-logger/extra-tests/tests/Logger_Tests_MergeResult.cls +++ b/nebula-logger/extra-tests/tests/Logger_Tests_MergeResult.cls @@ -17,7 +17,7 @@ private class Logger_Tests_MergeResult { } static List getMergeResultList() { - return new List{ LoggerMockDataCreator.createDatabaseMergeResult(true) }; + return new List{ LoggerMockDataCreator.createDatabaseMergeResult(true), LoggerMockDataCreator.createDatabaseMergeResult(true) }; } @IsTest diff --git a/nebula-logger/plugins/log-retention-rules/plugin/classes/LogRetentionFilter.cls b/nebula-logger/plugins/log-retention-rules/plugin/classes/LogRetentionFilter.cls index 95921b215..d4aaa0a50 100644 --- a/nebula-logger/plugins/log-retention-rules/plugin/classes/LogRetentionFilter.cls +++ b/nebula-logger/plugins/log-retention-rules/plugin/classes/LogRetentionFilter.cls @@ -11,6 +11,7 @@ * the value of `Log__c.LogRetentionDate__c` for any records that match the filters. * @see LogRententionRulesPlugin */ +@SuppressWarnings('PMD.CognitiveComplexity') public without sharing class LogRetentionFilter { private final SObject record; private final LogRetentionRule__mdt rule; diff --git a/package.json b/package.json index 5ff765a20..e1d1c3488 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nebula-logger", - "version": "4.13.4", + "version": "4.13.5", "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/scripts/data/create-sample-log-entries.apex b/scripts/data/create-sample-log-entries.apex index df7e0272e..46f0e191f 100644 --- a/scripts/data/create-sample-log-entries.apex +++ b/scripts/data/create-sample-log-entries.apex @@ -1,5 +1,3 @@ - -LoggerStackTrace.ignoreOrigins(new Set{ Logger.class, LogEntryEventBuilder.class, LogMessage.class}); // Logger.getUserSettings().DefaultSaveMethod__c = Logger.SaveMethod.SYNCHRONOUS_DML.name(); // Logger.getUserSettings().DefaultSaveMethod__c = Logger.SaveMethod.EVENT_BUS.name(); @@ -51,3 +49,4 @@ Logger.info('logging an HTTP response').setHttpResponseDetails(response); Logger.saveLog(); // throw new System.DmlException('aahhhhh!'); + diff --git a/sfdx-project.json b/sfdx-project.json index 891f55fc0..aba2ca86e 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -14,9 +14,9 @@ "path": "./nebula-logger/core", "definitionFile": "./config/scratch-orgs/base-scratch-def.json", "scopeProfiles": true, - "versionNumber": "4.13.4.NEXT", - "versionName": "Logger Parameter Comments", - "versionDescription": "Added new field LoggerParameter__mdt.Comments__c to provide a place to add comments & notes about customizations made to LoggerParameter__mdt records", + "versionNumber": "4.13.5.NEXT", + "versionName": "Performance improvements", + "versionDescription": "Added LoggerBenchmarking_Tests and optimized Logger performance when creating large numbers of log entries", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases", "unpackagedMetadata": { "path": "./nebula-logger/extra-tests" @@ -172,6 +172,7 @@ "Nebula Logger - Core@4.13.2-capture-organization-limits-usage": "04t5Y000001MkEmQAK", "Nebula Logger - Core@4.13.3-optionally-enforce-scenario-usage": "04t5Y000001MkEwQAK", "Nebula Logger - Core@4.13.4-logger-parameter-comments": "04t5Y000001MkFBQA0", + "Nebula Logger - Core@4.13.5-performance-improvements": "04t5Y000001MkGnQAK", "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",