diff --git a/README.md b/README.md index d6fa004c5..238f3b84e 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,15 @@ The most robust observability solution for Salesforce experts. Built 100% natively on the platform, and designed to work seamlessly with Apex, Lightning Components, Flow, OmniStudio, and integrations. -## Unlocked Package - v4.14.17 +## Unlocked Package - v4.14.18 -[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015ocRQAQ) -[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015ocRQAQ) +[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015ocbQAA) +[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015ocbQAA) [![View Documentation](./images/btn-view-documentation.png)](https://github.com/jongpie/NebulaLogger/wiki) -`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y0000015ocRQAQ` +`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y0000015ocbQAA` -`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y0000015ocRQAQ` +`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y0000015ocbQAA` --- diff --git a/docs/apex/Logger-Engine/LogEntryEventBuilder.md b/docs/apex/Logger-Engine/LogEntryEventBuilder.md index da9ee226c..83e374938 100644 --- a/docs/apex/Logger-Engine/LogEntryEventBuilder.md +++ b/docs/apex/Logger-Engine/LogEntryEventBuilder.md @@ -632,6 +632,26 @@ LogEntryEventBuilder The same instance of `LogEntryEventBuilder`, useful for chaining methods +#### `setRecord(System.Iterable recordsIds)` → `LogEntryEventBuilder` + +Sets the log entry event's record fields + +##### Parameters + +| Param | Description | +| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------- | +| `recordsIds` | The Set of `SObject` records ids related to the entry. Will be converted to list and the JSON of the list is automatically added to the entry | + +##### Return + +**Type** + +LogEntryEventBuilder + +**Description** + +The same instance of `LogEntryEventBuilder`, useful for chaining methods + #### `setRecordId(Id recordId)` → `LogEntryEventBuilder` Deprecated - use `setRecord(Id recordId)` instead diff --git a/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls b/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls index d93a099c3..9cdc0af3a 100644 --- a/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls +++ b/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls @@ -462,6 +462,29 @@ global with sharing class LogEntryEventBuilder { return this; } + /** + * @description Sets the log entry event's record fields + * @param recordsIds The Set of `SObject` records ids related to the entry. Will be converted to list and the JSON of the list is automatically added to the entry + * @return The same instance of `LogEntryEventBuilder`, useful for chaining methods + */ + global LogEntryEventBuilder setRecord(System.Iterable recordsIds) { + if (this.shouldSave() == false) { + return this; + } + + List records; + if (recordsIds != null) { + records = new List(); + for (Id recordId : recordsIds) { + SObject record = recordId.getSObjectType().newSObject(); + record.Id = recordId; + records.add(record); + } + } + + return this.setRecord(records); + } + /** * @description Sets the log entry event's HTTP Request fields * @param request The instance of `HttpRequest` to log diff --git a/nebula-logger/core/main/logger-engine/classes/Logger.cls b/nebula-logger/core/main/logger-engine/classes/Logger.cls index 511bf659d..8fb5a3616 100644 --- a/nebula-logger/core/main/logger-engine/classes/Logger.cls +++ b/nebula-logger/core/main/logger-engine/classes/Logger.cls @@ -15,7 +15,7 @@ global with sharing class Logger { // There's no reliable way to get the version number dynamically in Apex @TestVisible - private static final String CURRENT_VERSION_NUMBER = 'v4.14.17'; + private static final String CURRENT_VERSION_NUMBER = 'v4.14.18'; 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.'; diff --git a/nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js b/nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js index fa66a9ad9..2b4fc838f 100644 --- a/nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js +++ b/nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js @@ -10,7 +10,7 @@ import LoggerServiceTaskQueue from './loggerServiceTaskQueue'; import getSettings from '@salesforce/apex/ComponentLogger.getSettings'; import saveComponentLogEntries from '@salesforce/apex/ComponentLogger.saveComponentLogEntries'; -const CURRENT_VERSION_NUMBER = 'v4.14.17'; +const CURRENT_VERSION_NUMBER = 'v4.14.18'; const CONSOLE_OUTPUT_CONFIG = { messagePrefix: `%c Nebula Logger ${CURRENT_VERSION_NUMBER} `, 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 4878d6669..cdf789f91 100644 --- a/nebula-logger/core/tests/logger-engine/classes/LogEntryEventBuilder_Tests.cls +++ b/nebula-logger/core/tests/logger-engine/classes/LogEntryEventBuilder_Tests.cls @@ -35,6 +35,7 @@ private class LogEntryEventBuilder_Tests { System.Assert.isNull(builder.setRecord(System.UserInfo.getUserId()).getLogEntryEvent()); System.Assert.isNull(builder.setRecord(new Schema.User(Id = System.UserInfo.getUserId())).getLogEntryEvent()); System.Assert.isNull(builder.setRecord(new List{ new Schema.User(Id = System.UserInfo.getUserId()) }).getLogEntryEvent()); + System.Assert.isNull(builder.setRecord(new Set{ System.UserInfo.getUserId() }).getLogEntryEvent()); System.Assert.isNull(builder.addTags(new List{ 'tag-1', 'tag-2' }).getLogEntryEvent()); System.Assert.isNull(builder.parseStackTrace(new System.DmlException().getStackTraceString()).getLogEntryEvent()); } @@ -1249,6 +1250,66 @@ private class LogEntryEventBuilder_Tests { System.Assert.areEqual(Schema.User.SObjectType.getDescribe().getName(), builder.getLogEntryEvent().RecordSObjectType__c); } + @IsTest + static void it_should_set_record_fields_for_iterable_ids_when_null() { + 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); + System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectType__c); + System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectTypeNamespace__c); + + System.Iterable nullIterableIds = null; + builder.setRecord(nullIterableIds); + + System.Assert.isNull(builder.getLogEntryEvent().RecordCollectionSize__c); + System.Assert.areEqual('List', builder.getLogEntryEvent().RecordCollectionType__c); + System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); + System.Assert.areEqual('null', builder.getLogEntryEvent().RecordJson__c); + System.Assert.areEqual('Unknown', builder.getLogEntryEvent().RecordSObjectClassification__c); + System.Assert.areEqual('Unknown', builder.getLogEntryEvent().RecordSObjectType__c); + } + + @IsTest + static void it_should_set_record_fields_for_list_of_id_records_when_populated() { + 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); + System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectType__c); + System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectTypeNamespace__c); + + List userIdList = new List(new Map([SELECT Id, Name, Username, IsActive FROM User LIMIT 5]).keySet()); + builder.setRecord(userIdList); + + System.Assert.areEqual(userIdList.size(), builder.getLogEntryEvent().RecordCollectionSize__c); + System.Assert.areEqual('List', builder.getLogEntryEvent().RecordCollectionType__c); + System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); + System.Assert.isNotNull(builder.getLogEntryEvent().RecordJson__c); + System.Assert.areEqual('Unknown', builder.getLogEntryEvent().RecordSObjectClassification__c); + System.Assert.areEqual('Unknown', builder.getLogEntryEvent().RecordSObjectType__c); + } + + @IsTest + static void it_should_set_record_fields_for_set_of_id_records_when_populated() { + 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); + System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectType__c); + System.Assert.isNull(builder.getLogEntryEvent().RecordSObjectTypeNamespace__c); + + Set userIdSet = new Map([SELECT Id, Name, Username, IsActive FROM User LIMIT 5]).keySet(); + builder.setRecord(userIdSet); + + System.Assert.areEqual(userIdSet.size(), builder.getLogEntryEvent().RecordCollectionSize__c); + System.Assert.areEqual('List', builder.getLogEntryEvent().RecordCollectionType__c); + System.Assert.isNull(builder.getLogEntryEvent().RecordId__c); + System.Assert.isNotNull(builder.getLogEntryEvent().RecordJson__c); + System.Assert.areEqual('Unknown', builder.getLogEntryEvent().RecordSObjectClassification__c); + System.Assert.areEqual('Unknown', builder.getLogEntryEvent().RecordSObjectType__c); + } + @IsTest static void it_should_skip_setting_http_request_fields_when_request_is_null() { LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true); diff --git a/nebula-logger/extra-tests/classes/name-shadowing/System/Iterable.cls b/nebula-logger/extra-tests/classes/name-shadowing/System/Iterable.cls new file mode 100644 index 000000000..868750e18 --- /dev/null +++ b/nebula-logger/extra-tests/classes/name-shadowing/System/Iterable.cls @@ -0,0 +1,10 @@ +//------------------------------------------------------------------------------------------------// +// This file is part of the Nebula Logger project, released under the MIT License. // +// See LICENSE file or go to https://github.com/jongpie/NebulaLogger for full license details. // +//------------------------------------------------------------------------------------------------// + +// This class intentionally does nothing - it's here to ensure that any references +// in Nebula Logger's codebase use `System.Iterable` instead of just `Iterable` +@SuppressWarnings('PMD.ApexDoc, PMD.EmptyStatementBlock') +public without sharing class Iterable { +} diff --git a/nebula-logger/extra-tests/classes/name-shadowing/System/Iterable.cls-meta.xml b/nebula-logger/extra-tests/classes/name-shadowing/System/Iterable.cls-meta.xml new file mode 100644 index 000000000..651b17293 --- /dev/null +++ b/nebula-logger/extra-tests/classes/name-shadowing/System/Iterable.cls-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + Active + diff --git a/package.json b/package.json index 69875359a..cc6141e9e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nebula-logger", - "version": "4.14.17", + "version": "4.14.18", "description": "The most robust logger for Salesforce. Works with Apex, Lightning Components, Flow, Process Builder & Integrations. Designed for Salesforce admins, developers & architects.", "author": "Jonathan Gillespie", "license": "MIT", diff --git a/sfdx-project.json b/sfdx-project.json index 73eeeceb1..fc0e511cc 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -9,9 +9,9 @@ "path": "./nebula-logger/core", "definitionFile": "./config/scratch-orgs/base-scratch-def.json", "scopeProfiles": true, - "versionNumber": "4.14.17.NEXT", - "versionName": "Improved JavaScript Console Output", - "versionDescription": "Added more details to the component log entry JSON that's printed using console statements. The stringified object now includes more details, such as the exception, tags, and scenario.", + "versionNumber": "4.14.18.NEXT", + "versionName": "Added setRecord() Overload for List and Set Parameters", + "versionDescription": "Added a new overload setRecord(System.Iterable recordsIds) in LogEntryEventBuilder to make it easy to log List and Set.", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases", "unpackagedMetadata": { "path": "./nebula-logger/extra-tests" @@ -202,6 +202,7 @@ "Nebula Logger - Core@4.14.15-create-log-entry-for-asyncapexcontext": "04t5Y0000015obxQAA", "Nebula Logger - Core@4.14.16-callablelogger-enhancements": "04t5Y0000015ocHQAQ", "Nebula Logger - Core@4.14.17-improved-javascript-console-output": "04t5Y0000015ocRQAQ", + "Nebula Logger - Core@4.14.18-added-setrecord()-overload-for-list-and-set-parameters": "04t5Y0000015ocbQAA", "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",