From d91e66522020759b0cae41ad27e2158007c79596 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Wed, 30 Nov 2022 09:07:22 -0500 Subject: [PATCH] Updated Logger.getUserSettings() to set defaults based on the environment type (#417) * Updated LoggerSettings__c fields LoggingLevel__c, IsApexSystemDebugLoggingEnabled__c, and IsJavaScriptConsoleLoggingEnabled__c to make the default values be the recommended values for production orgs * Closed #364 by updating Logger.getUserSettings() to set some field values based on if the current org is a sandbox - this also applies when using the included LWC loggerSettings * Updated `LoggerEngineDataSelector class to still leverage data cached in Platform Cache (if available), even if querying is disabled for a particular method * Added the System namespace to all references to the FeatureManagement class * Removed some lingering references to Logger in LogEntryBuilder & LogEntryBuilder_Tests, which finishes up some ongoing tech debt cleanup to make LogEntryEventBuilder independent/unaware of `Logger` * Made test execution faster in the pipeline by updating build.yml to skip unnecessary code coverage calculations for all test runs except for the final synchronous run in the Experience Cloud scratch org (when code coverage data is uploaded to Codecov.io) --- .github/workflows/build.yml | 6 +- README.md | 6 +- ...ystemDebugLoggingEnabled__c.field-meta.xml | 2 +- ...iptConsoleLoggingEnabled__c.field-meta.xml | 2 +- .../fields/LoggingLevel__c.field-meta.xml | 2 +- .../classes/LogBatchPurgeController.cls | 4 +- .../classes/LoggerSettingsController.cls | 6 +- .../classes/LogEntryEventBuilder.cls | 76 +++++++-------- .../main/logger-engine/classes/Logger.cls | 17 +++- .../classes/LoggerEngineDataSelector.cls | 44 ++++----- .../classes/LogBatchPurgeController_Tests.cls | 7 +- .../LoggerSettingsController_Tests.cls | 22 ++++- .../classes/LogEntryEventBuilder_Tests.cls | 85 ++++++++++------- .../logger-engine/classes/Logger_Tests.cls | 95 +++++++++++++++++-- .../classes/ExampleInboundEmailHandler.cls | 4 +- .../extra-tests/classes/FeatureManagement.cls | 10 ++ .../classes/FeatureManagement.cls-meta.xml | 5 + ...oggerSettingsController_Tests_Security.cls | 13 ++- package.json | 2 +- sfdx-project.json | 5 +- 20 files changed, 277 insertions(+), 136 deletions(-) create mode 100644 nebula-logger/extra-tests/classes/FeatureManagement.cls create mode 100644 nebula-logger/extra-tests/classes/FeatureManagement.cls-meta.xml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 35d1f3a68..1b6fffb4c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -175,10 +175,10 @@ jobs: # Utlimately, this could/should probably be better mocked during tests, but the AuthSession is read-only in Apex, so it's a bit difficult to work with. # Running the Apex tests sync & async serves as an extra level of integration testing to ensure that everything works with or without an active session. - name: 'Run Apex Tests Asynchronously' - run: npm run test:apex + run: npm run test:apex:nocoverage - name: 'Run Apex Tests Synchronously' - run: npm run test:apex -- --synchronous + run: npm run test:apex:nocoverage -- --synchronous - name: 'Delete Base Scratch Org' run: npm run org:delete:noprompt @@ -239,7 +239,7 @@ jobs: # Utlimately, this could/should probably be better mocked during tests, but the AuthSession is read-only in Apex, so it's a bit difficult to work with. # Running the Apex tests sync & async serves as an extra level of integration testing to ensure that everything works with or without an active session. - name: 'Run Apex Tests Asynchronously' - run: npm run test:apex + run: npm run test:apex:nocoverage - name: 'Run Apex Tests Synchronously' run: npm run test:apex -- --synchronous diff --git a/README.md b/README.md index a6db30db9..254cc0b74 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,10 @@ The most robust logger for Salesforce. Works with Apex, Lightning Components, Flow, Process Builder & Integrations. Designed for Salesforce admins, developers & architects. -## Unlocked Package - v4.9.5 +## Unlocked Package - v4.9.6 -[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000023R9KQAU) -[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000023R9KQAU) +[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000023R9eQAE) +[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000023R9eQAE) [![View Documentation](./images/btn-view-documentation.png)](https://jongpie.github.io/NebulaLogger/) ## Managed Package - v4.9.0 diff --git a/nebula-logger/core/main/configuration/objects/LoggerSettings__c/fields/IsApexSystemDebugLoggingEnabled__c.field-meta.xml b/nebula-logger/core/main/configuration/objects/LoggerSettings__c/fields/IsApexSystemDebugLoggingEnabled__c.field-meta.xml index d68dee288..81a06bb58 100644 --- a/nebula-logger/core/main/configuration/objects/LoggerSettings__c/fields/IsApexSystemDebugLoggingEnabled__c.field-meta.xml +++ b/nebula-logger/core/main/configuration/objects/LoggerSettings__c/fields/IsApexSystemDebugLoggingEnabled__c.field-meta.xml @@ -3,7 +3,7 @@ IsApexSystemDebugLoggingEnabled__c Active CCPA;GDPR;PII - true + false false When enabled, Logger will automatically call Apex's System.debug(). To help with performance, this option should be disabled in production unless you are actively troubleshooting an issue. diff --git a/nebula-logger/core/main/configuration/objects/LoggerSettings__c/fields/IsJavaScriptConsoleLoggingEnabled__c.field-meta.xml b/nebula-logger/core/main/configuration/objects/LoggerSettings__c/fields/IsJavaScriptConsoleLoggingEnabled__c.field-meta.xml index 847c91691..77e92c2a1 100644 --- a/nebula-logger/core/main/configuration/objects/LoggerSettings__c/fields/IsJavaScriptConsoleLoggingEnabled__c.field-meta.xml +++ b/nebula-logger/core/main/configuration/objects/LoggerSettings__c/fields/IsJavaScriptConsoleLoggingEnabled__c.field-meta.xml @@ -3,7 +3,7 @@ IsJavaScriptConsoleLoggingEnabled__c Active CCPA;GDPR;PII - true + false false When enabled, Logger will automatically call the browser's console.log() function when logging via lightning components. To help with performance, this option should be disabled in production unless you are actively troubleshooting an issue. diff --git a/nebula-logger/core/main/configuration/objects/LoggerSettings__c/fields/LoggingLevel__c.field-meta.xml b/nebula-logger/core/main/configuration/objects/LoggerSettings__c/fields/LoggingLevel__c.field-meta.xml index 2173a1ba2..b6427f1fd 100644 --- a/nebula-logger/core/main/configuration/objects/LoggerSettings__c/fields/LoggingLevel__c.field-meta.xml +++ b/nebula-logger/core/main/configuration/objects/LoggerSettings__c/fields/LoggingLevel__c.field-meta.xml @@ -3,7 +3,7 @@ LoggingLevel__c Active CCPA;GDPR;PII - 'DEBUG' + 'INFO' false 255 diff --git a/nebula-logger/core/main/log-management/classes/LogBatchPurgeController.cls b/nebula-logger/core/main/log-management/classes/LogBatchPurgeController.cls index 40325da9d..ca2054a59 100644 --- a/nebula-logger/core/main/log-management/classes/LogBatchPurgeController.cls +++ b/nebula-logger/core/main/log-management/classes/LogBatchPurgeController.cls @@ -130,9 +130,9 @@ public with sharing class LogBatchPurgeController { * @return true if the current user has delete permission on the Log__c object. */ @AuraEnabled - public static boolean canUserRunLogBatchPurger() { + public static Boolean canUserRunLogBatchPurger() { return Schema.Log__c.SObjectType.getDescribe().isDeletable() == true || - FeatureManagement.checkPermission(CAN_EXECUTE_LOG_BATCH_PURGER_PERMISSION) == true; + System.FeatureManagement.checkPermission(CAN_EXECUTE_LOG_BATCH_PURGER_PERMISSION) == true; } /** diff --git a/nebula-logger/core/main/log-management/classes/LoggerSettingsController.cls b/nebula-logger/core/main/log-management/classes/LoggerSettingsController.cls index 8caf749d0..e6445bfdd 100644 --- a/nebula-logger/core/main/log-management/classes/LoggerSettingsController.cls +++ b/nebula-logger/core/main/log-management/classes/LoggerSettingsController.cls @@ -29,7 +29,7 @@ public without sharing class LoggerSettingsController { @AuraEnabled(cacheable=true) public static Boolean canUserModifyLoggerSettings() { return Schema.LoggerSettings__c.SObjectType.getDescribe().isUpdateable() == true || - FeatureManagement.checkPermission('CanModifyLoggerSettings') == true; + System.FeatureManagement.checkPermission('CanModifyLoggerSettings') == true; } /** @@ -85,7 +85,9 @@ public without sharing class LoggerSettingsController { */ @AuraEnabled(cacheable=true) public static LoggerSettings__c createRecord() { - return (LoggerSettings__c) Schema.LoggerSettings__c.SObjectType.newSObject(null, true); + // By passing an empty User record, it ensures that the returned LoggerSettings__c record + // is not tied to a specific User or Profile (or Organization) + return Logger.getUserSettings(new User()); } /** diff --git a/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls b/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls index 0e426794f..67f376d2f 100644 --- a/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls +++ b/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls @@ -16,11 +16,14 @@ global with sharing class LogEntryEventBuilder { private static final User CURRENT_USER = new User(Id = System.UserInfo.getUserId(), ProfileId = System.UserInfo.getProfileId()); private static final String NEW_LINE_DELIMITER = '\n'; + private static String cachedOrganizationEnvironmentType; + @TestVisible private static Id networkId = System.Network.getNetworkId(); private final LogEntryEvent__e logEntryEvent; private final System.LoggingLevel entryLoggingLevel; + private final String organizationEnvironmentType; private final LoggerSettings__c userSettings; @TestVisible @@ -41,16 +44,6 @@ global with sharing class LogEntryEventBuilder { set; } - private static final String CACHED_ORGANIZATION_ENVIRONMENT_TYPE { - get { - if (CACHED_ORGANIZATION_ENVIRONMENT_TYPE == null) { - CACHED_ORGANIZATION_ENVIRONMENT_TYPE = getOrganizationEnvironmentType(); - } - return CACHED_ORGANIZATION_ENVIRONMENT_TYPE; - } - set; - } - private static final LogEntryEvent__e LOG_ENTRY_EVENT_TEMPLATE { get { if (LOG_ENTRY_EVENT_TEMPLATE == null) { @@ -106,6 +99,7 @@ global with sharing class LogEntryEventBuilder { } this.userSettings = userSettings; + this.organizationEnvironmentType = getOrganizationEnvironmentType(userSettings); this.entryLoggingLevel = entryLoggingLevel; if (ignoredOrigins != null) { this.ignoredApexClasses.addAll(ignoredOrigins); @@ -655,6 +649,13 @@ global with sharing class LogEntryEventBuilder { 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); + setQueriedUserDetails(this.logEntryEvent, this.userSettings); + } + setQueriedNetworkDetails(this.logEntryEvent, this.userSettings); + setQueriedOrganizationDetails(this.logEntryEvent, this.userSettings); this.detailsAreSet = true; } @@ -679,7 +680,7 @@ global with sharing class LogEntryEventBuilder { @SuppressWarnings('PMD.AvoidDebugStatements') private void logToApexDebug(String message) { - if (Logger.getUserSettings().IsApexSystemDebugLoggingEnabled__c == false) { + if (this.userSettings.IsApexSystemDebugLoggingEnabled__c == false) { return; } @@ -769,19 +770,11 @@ global with sharing class LogEntryEventBuilder { OrganizationDomainUrl__c = Url.getOrgDomainUrl()?.toExternalForm() ); - if (Logger.getUserSettings().IsAnonymousModeEnabled__c == false) { - setUserInfoDetails(templateLogEntryEvent); - setQueriedAuthSessionDetails(templateLogEntryEvent); - setQueriedUserDetails(templateLogEntryEvent); - } - setQueriedNetworkDetails(templateLogEntryEvent); - setQueriedOrganizationDetails(templateLogEntryEvent); - return templateLogEntryEvent; } - private static void setQueriedAuthSessionDetails(LogEntryEvent__e logEntryEvent) { - if (LoggerParameter.QUERY_AUTH_SESSION_DATA_SYNCHRONOUSLY == false) { + private static void setQueriedAuthSessionDetails(LogEntryEvent__e logEntryEvent, LoggerSettings__c userSettings) { + if (userSettings.IsEnabled__c == false || LoggerParameter.QUERY_AUTH_SESSION_DATA_SYNCHRONOUSLY == false) { return; } @@ -806,8 +799,8 @@ global with sharing class LogEntryEventBuilder { } } - private static void setQueriedNetworkDetails(LogEntryEvent__e logEntryEvent) { - if (LoggerParameter.QUERY_NETWORK_DATA_SYNCHRONOUSLY == false || String.isBlank(networkId) == true) { + private static void setQueriedNetworkDetails(LogEntryEvent__e logEntryEvent, LoggerSettings__c userSettings) { + if (userSettings.IsEnabled__c == false || LoggerParameter.QUERY_NETWORK_DATA_SYNCHRONOUSLY == false || String.isBlank(networkId) == true) { return; } @@ -824,8 +817,8 @@ global with sharing class LogEntryEventBuilder { logEntryEvent.NetworkUrlPathPrefix__c = cachedNetworkProxy.UrlPathPrefix; } - private static void setQueriedOrganizationDetails(LogEntryEvent__e logEntryEvent) { - if (LoggerParameter.QUERY_ORGANIZATION_DATA_SYNCHRONOUSLY == false) { + private static void setQueriedOrganizationDetails(LogEntryEvent__e logEntryEvent, LoggerSettings__c userSettings) { + if (userSettings.IsEnabled__c == false || LoggerParameter.QUERY_ORGANIZATION_DATA_SYNCHRONOUSLY == false) { return; } @@ -834,7 +827,7 @@ global with sharing class LogEntryEventBuilder { return; } - logEntryEvent.OrganizationEnvironmentType__c = CACHED_ORGANIZATION_ENVIRONMENT_TYPE; + logEntryEvent.OrganizationEnvironmentType__c = getOrganizationEnvironmentType(userSettings); logEntryEvent.OrganizationId__c = cachedOrganization?.Id; logEntryEvent.OrganizationInstanceName__c = cachedOrganization?.InstanceName; logEntryEvent.OrganizationName__c = cachedOrganization?.Name; @@ -842,13 +835,12 @@ global with sharing class LogEntryEventBuilder { logEntryEvent.OrganizationType__c = cachedOrganization?.OrganizationType; } - private static void setQueriedUserDetails(LogEntryEvent__e logEntryEvent) { - if (LoggerParameter.QUERY_USER_DATA_SYNCHRONOUSLY == false) { + private static void setQueriedUserDetails(LogEntryEvent__e logEntryEvent, LoggerSettings__c userSettings) { + if (userSettings.IsEnabled__c == false || LoggerParameter.QUERY_USER_DATA_SYNCHRONOUSLY == false) { return; } User cachedUser = LoggerEngineDataSelector.getInstance().getCachedUser(); - if (cachedUser == null) { return; } @@ -878,8 +870,8 @@ global with sharing class LogEntryEventBuilder { CACHED_DATA_MASK_RULES.put(dataMaskRule.DeveloperName, dataMaskRule); } - private static String applyDataMaskRules(String dataInput) { - if (Logger.getUserSettings().IsDataMaskingEnabled__c == false || String.isBlank(dataInput) == true) { + private String applyDataMaskRules(String dataInput) { + if (this.userSettings.IsDataMaskingEnabled__c == false || String.isBlank(dataInput) == true) { return dataInput; } @@ -918,19 +910,27 @@ global with sharing class LogEntryEventBuilder { return userJson.substringAfter('/data/').substringBefore('/sobjects/User'); } - private static String getOrganizationEnvironmentType() { + private static String getOrganizationEnvironmentType(LoggerSettings__c userSettings) { + if (cachedOrganizationEnvironmentType != null) { + return cachedOrganizationEnvironmentType; + } + + if (userSettings.IsEnabled__c == false || LoggerParameter.QUERY_ORGANIZATION_DATA_SYNCHRONOUSLY == false) { + return ''; + } + Organization cachedOrganization = LoggerEngineDataSelector.getInstance().getCachedOrganization(); - String orgEnvironmentType; + String cachedOrganizationEnvironmentType; if (cachedOrganization == null) { - return ''; + cachedOrganizationEnvironmentType = ''; } else if (cachedOrganization.IsSandbox == true && cachedOrganization.TrialExpirationDate != null) { - orgEnvironmentType = 'Scratch Org'; + cachedOrganizationEnvironmentType = 'Scratch Org'; } else if (cachedOrganization.IsSandbox == true) { - orgEnvironmentType = 'Sandbox'; + cachedOrganizationEnvironmentType = 'Sandbox'; } else { - orgEnvironmentType = 'Production'; + cachedOrganizationEnvironmentType = 'Production'; } - return orgEnvironmentType; + return cachedOrganizationEnvironmentType; } private static String getNamespacePrefix() { diff --git a/nebula-logger/core/main/logger-engine/classes/Logger.cls b/nebula-logger/core/main/logger-engine/classes/Logger.cls index ff0cb326f..678fc7159 100644 --- a/nebula-logger/core/main/logger-engine/classes/Logger.cls +++ b/nebula-logger/core/main/logger-engine/classes/Logger.cls @@ -15,8 +15,8 @@ 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.9.5'; - private static final System.LoggingLevel DEFAULT_LOGGING_LEVEL = System.LoggingLevel.DEBUG; + private static final String CURRENT_VERSION_NUMBER = 'v4.9.6'; + private static final System.LoggingLevel FALLBACK_LOGGING_LEVEL = System.LoggingLevel.DEBUG; private static final Set IGNORED_APEX_CLASSES = initializeIgnoredApexClasses(); private static final List LOG_ENTRIES_BUFFER = new List(); private static final String REQUEST_ID = System.Request.getCurrent().getRequestId(); @@ -106,6 +106,7 @@ global with sharing class Logger { return CURRENT_VERSION_NUMBER; } + // TODO delete /** * @description Returns the current namespace of Nebula Logger * @return The current namespace prefix, or an empty string when no namespace is being used @@ -281,6 +282,14 @@ global with sharing class Logger { loggingUserSettings = LoggerSettings__c.getOrgDefaults(); } else { loggingUserSettings = (LoggerSettings__c) Schema.LoggerSettings__c.SObjectType.newSObject(null, true); + if ( + LoggerParameter.QUERY_ORGANIZATION_DATA_SYNCHRONOUSLY == true && + LoggerEngineDataSelector.getInstance().getCachedOrganization()?.IsSandbox == true + ) { + loggingUserSettings.LoggingLevel__c = System.LoggingLevel.FINEST.name(); + loggingUserSettings.IsApexSystemDebugLoggingEnabled__c = true; + loggingUserSettings.IsJavaScriptConsoleLoggingEnabled__c = true; + } } // If the settings were loaded from the org or profile level, clear the ID and make the user the SetupOwnerId (since the method is getUserSettings) @@ -2880,11 +2889,11 @@ global with sharing class Logger { LogMessage logMessage = new LogMessage( 'Logger - Unknown logging level {0} specified, using {1}', loggingLevelName, - DEFAULT_LOGGING_LEVEL.name() + FALLBACK_LOGGING_LEVEL.name() ); finest(logMessage); } - return DEFAULT_LOGGING_LEVEL; + return FALLBACK_LOGGING_LEVEL; } } diff --git a/nebula-logger/core/main/logger-engine/classes/LoggerEngineDataSelector.cls b/nebula-logger/core/main/logger-engine/classes/LoggerEngineDataSelector.cls index 391f08f4b..a0f8fb621 100644 --- a/nebula-logger/core/main/logger-engine/classes/LoggerEngineDataSelector.cls +++ b/nebula-logger/core/main/logger-engine/classes/LoggerEngineDataSelector.cls @@ -69,18 +69,17 @@ public without sharing virtual class LoggerEngineDataSelector { * @return The cached `AuthSession` record */ public virtual LoggerSObjectProxy.AuthSession getCachedAuthSessionProxy() { - if (LoggerParameter.QUERY_AUTH_SESSION_DATA == false) { - return null; - } - Id userId = System.UserInfo.getUserId(); String cacheKey = 'AuthSession' + userId; if (LoggerCache.getSessionCache().contains(cacheKey) == true) { return (LoggerSObjectProxy.AuthSession) LoggerCache.getSessionCache().get(cacheKey); } - LoggerSObjectProxy.AuthSession authSession = getAuthSessionProxies(new List{ userId }).get(userId); - LoggerCache.getSessionCache().put(cacheKey, authSession); + LoggerSObjectProxy.AuthSession authSession; + if (LoggerParameter.QUERY_AUTH_SESSION_DATA == true) { + authSession = getAuthSessionProxies(new List{ userId }).get(userId); + LoggerCache.getSessionCache().put(cacheKey, authSession); + } return authSession; } @@ -111,10 +110,6 @@ public without sharing virtual class LoggerEngineDataSelector { * @return The cached `Network` record */ public virtual LoggerSObjectProxy.Network getCachedNetworkProxy(Id networkId) { - if (LoggerParameter.QUERY_NETWORK_DATA == false) { - return null; - } - if (networkId == null || IS_EXPERIENCE_CLOUD_ENABLED == false) { return null; } @@ -124,8 +119,11 @@ public without sharing virtual class LoggerEngineDataSelector { return (LoggerSObjectProxy.Network) LoggerCache.getOrganizationCache().get(cacheKey); } - LoggerSObjectProxy.Network networkProxy = getNetworkProxies(new List{ networkId }).get(networkId); - LoggerCache.getOrganizationCache().put(cacheKey, networkProxy); + LoggerSObjectProxy.Network networkProxy; + if (LoggerParameter.QUERY_NETWORK_DATA == false) { + networkProxy = getNetworkProxies(new List{ networkId }).get(networkId); + LoggerCache.getOrganizationCache().put(cacheKey, networkProxy); + } return networkProxy; } @@ -134,17 +132,16 @@ public without sharing virtual class LoggerEngineDataSelector { * @return The cached `Organization` record */ public virtual Organization getCachedOrganization() { - if (LoggerParameter.QUERY_ORGANIZATION_DATA == false) { - return null; - } - String cacheKey = 'Organization'; if (LoggerCache.getOrganizationCache().contains(cacheKey) == true) { return (Organization) LoggerCache.getOrganizationCache().get(cacheKey); } - Organization organization = [SELECT Id, InstanceName, IsSandbox, Name, NamespacePrefix, OrganizationType, TrialExpirationDate FROM Organization]; - LoggerCache.getOrganizationCache().put(cacheKey, organization); + Organization organization; + if (LoggerParameter.QUERY_ORGANIZATION_DATA == true) { + organization = [SELECT Id, InstanceName, IsSandbox, Name, NamespacePrefix, OrganizationType, TrialExpirationDate FROM Organization]; + LoggerCache.getOrganizationCache().put(cacheKey, organization); + } return organization; } @@ -179,18 +176,17 @@ public without sharing virtual class LoggerEngineDataSelector { * @return The cached `User` record for the current user */ public virtual User getCachedUser() { - if (LoggerParameter.QUERY_USER_DATA == false) { - return null; - } - Id userId = System.UserInfo.getUserId(); String cacheKey = 'User' + userId; if (LoggerCache.getSessionCache().contains(cacheKey) == true) { return (User) LoggerCache.getSessionCache().get(cacheKey); } - User user = getUsers(new List{ userId }).get(userId); - LoggerCache.getSessionCache().put(cacheKey, user); + User user; + if (LoggerParameter.QUERY_USER_DATA == true) { + user = getUsers(new List{ userId }).get(userId); + LoggerCache.getSessionCache().put(cacheKey, user); + } return user; } diff --git a/nebula-logger/core/tests/log-management/classes/LogBatchPurgeController_Tests.cls b/nebula-logger/core/tests/log-management/classes/LogBatchPurgeController_Tests.cls index 4439743a9..de44779a1 100644 --- a/nebula-logger/core/tests/log-management/classes/LogBatchPurgeController_Tests.cls +++ b/nebula-logger/core/tests/log-management/classes/LogBatchPurgeController_Tests.cls @@ -336,7 +336,10 @@ private class LogBatchPurgeController_Tests { insert new List{ setupEntityAccess, permissionSetAssignment }; System.runAs(standardUser) { - System.Assert.isTrue(FeatureManagement.checkPermission(CAN_EXECUTE_LOG_BATCH_PURGER_PERMISSION), JSON.serializePretty(permissionSetAssignment)); + System.Assert.isTrue( + System.FeatureManagement.checkPermission(CAN_EXECUTE_LOG_BATCH_PURGER_PERMISSION), + JSON.serializePretty(permissionSetAssignment) + ); System.Assert.areEqual( true, LogBatchPurgeController.canUserRunLogBatchPurger(), @@ -375,7 +378,7 @@ private class LogBatchPurgeController_Tests { insert new List{ setupEntityAccess }; System.runAs(standardUser) { - System.Assert.isFalse(FeatureManagement.checkPermission(CAN_EXECUTE_LOG_BATCH_PURGER_PERMISSION), 'permission set assigned'); + System.Assert.isFalse(System.FeatureManagement.checkPermission(CAN_EXECUTE_LOG_BATCH_PURGER_PERMISSION), 'permission set assigned'); System.Assert.areEqual( false, LogBatchPurgeController.canUserRunLogBatchPurger(), diff --git a/nebula-logger/core/tests/log-management/classes/LoggerSettingsController_Tests.cls b/nebula-logger/core/tests/log-management/classes/LoggerSettingsController_Tests.cls index 56046a7ea..53dc1423b 100644 --- a/nebula-logger/core/tests/log-management/classes/LoggerSettingsController_Tests.cls +++ b/nebula-logger/core/tests/log-management/classes/LoggerSettingsController_Tests.cls @@ -8,9 +8,10 @@ private class LoggerSettingsController_Tests { @IsTest static void it_should_return_loggingLevel_picklist_options() { - // Integer expectedLoggingLevelSize = System.LoggingLevel.values().size() - 1; // LoggingLEVEL.NONE and System.LoggingLevel.INTERNAL are ignored, '--NONE--' is automatically included + List picklistOptions = LoggerSettingsController.getPicklistOptions().loggingLevelOptions; + System.Assert.areEqual(expectedLoggingLevelSize, picklistOptions.size()); for (LoggerSettingsController.PicklistOption picklistOption : picklistOptions) { if (String.isBlank(picklistOption.value) == true) { @@ -54,7 +55,9 @@ private class LoggerSettingsController_Tests { @IsTest static void it_should_return_loggerSaveMethod_picklist_options() { Integer expectedLoggerSaveMethodSize = Logger.SaveMethod.values().size() + 1; // '--NONE--' is automatically included + List picklistOptions = LoggerSettingsController.getPicklistOptions().saveMethodOptions; + System.Assert.areEqual(expectedLoggerSaveMethodSize, picklistOptions.size()); for (LoggerSettingsController.PicklistOption picklistOption : picklistOptions) { if (String.isBlank(picklistOption.value) == true) { @@ -127,7 +130,9 @@ private class LoggerSettingsController_Tests { static void it_should_return_setupOwnerType_picklist_options() { Set expectedSetupOwnerType = new Set{ 'Organization', 'Profile', 'User' }; Integer expectedSetupOwnerTypeSize = 4; // Options are org, profile, and user, and '--NONE--' is automatically included + List picklistOptions = LoggerSettingsController.getPicklistOptions().setupOwnerTypeOptions; + System.Assert.areEqual(expectedSetupOwnerTypeSize, picklistOptions.size()); for (LoggerSettingsController.PicklistOption picklistOption : picklistOptions) { if (String.isBlank(picklistOption.value) == true) { @@ -149,7 +154,9 @@ private class LoggerSettingsController_Tests { } } Integer expectedShareAccessLevelSize = expectedShareAccessLevels.size() + 1; // 'All' value is ignored, and '--NONE--' is automatically included + List picklistOptions = LoggerSettingsController.getPicklistOptions().shareAccessLevelOptions; + System.Assert.areEqual(expectedShareAccessLevelSize, picklistOptions.size(), picklistOptions.toString()); for (LoggerSettingsController.PicklistOption picklistOption : picklistOptions) { if (String.isBlank(picklistOption.value) == true) { @@ -164,7 +171,9 @@ private class LoggerSettingsController_Tests { @IsTest static void it_should_return_empty_settings_records_list_when_not_configured() { System.Assert.areEqual(0, [SELECT COUNT() FROM LoggerSettings__c]); + List records = LoggerSettingsController.getRecords(); + System.Assert.areEqual(0, records.size()); } @@ -179,6 +188,7 @@ private class LoggerSettingsController_Tests { Map testSettingsRecordsById = queryLoggerSettingsRecords(testSettingsRecords); List recordResults = LoggerSettingsController.getRecords(); + System.Assert.isFalse(recordResults.isEmpty()); System.Assert.areEqual(testSettingsRecordsById.size(), recordResults.size()); for (LoggerSettingsController.SettingsRecordResult result : recordResults) { @@ -192,8 +202,10 @@ private class LoggerSettingsController_Tests { @IsTest static void it_should_create_new_record() { - LoggerSettings__c expectedNewRecord = (LoggerSettings__c) Schema.LoggerSettings__c.SObjectType.newSObject(null, true); + LoggerSettings__c expectedNewRecord = Logger.getUserSettings(new User()); + LoggerSettings__c newRecord = LoggerSettingsController.createRecord(); + System.Assert.areEqual(expectedNewRecord, newRecord); System.Assert.isNull(newRecord.Id); System.Assert.isNull(newRecord.SetupOwnerId); @@ -206,6 +218,7 @@ private class LoggerSettingsController_Tests { System.Assert.isNull(newRecord.Id); LoggerSettingsController.saveRecord(newRecord); + System.Assert.isNotNull(newRecord.Id); } @@ -291,6 +304,7 @@ private class LoggerSettingsController_Tests { Profile currentProfile = [SELECT Id, Name FROM Profile WHERE Id = :System.UserInfo.getProfileId()]; String searchTerm = '%' + currentProfile.Name.left(4) + '%'; Map expectedResultsById = new Map([SELECT Id, Name, UserLicense.Name FROM Profile WHERE Name LIKE :searchTerm]); + List results = LoggerSettingsController.searchForSetupOwner('Profile', searchTerm); System.Assert.isFalse(results.isEmpty()); @@ -308,7 +322,9 @@ private class LoggerSettingsController_Tests { @IsTest static void it_should_return_empty_user_search_results_list_when_no_matches_found() { String nonsenseSearchTerm = 'asdfqwert;lkhpoiy'; + List results = LoggerSettingsController.searchForSetupOwner('User', nonsenseSearchTerm); + System.Assert.areEqual(0, results.size()); } @@ -318,6 +334,7 @@ private class LoggerSettingsController_Tests { Map expectedResultsById = new Map( [SELECT Id, Name, Username, SmallPhotoUrl FROM User WHERE Name LIKE :searchTerm OR Username LIKE :searchTerm] ); + List results = LoggerSettingsController.searchForSetupOwner('User', searchTerm); System.Assert.isFalse(results.isEmpty()); @@ -349,7 +366,6 @@ private class LoggerSettingsController_Tests { } } - // Helper methods private static Map queryLoggerSettingsRecords(List recordsToQuery) { return 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 a2bf3774b..2b5a2fee1 100644 --- a/nebula-logger/core/tests/logger-engine/classes/LogEntryEventBuilder_Tests.cls +++ b/nebula-logger/core/tests/logger-engine/classes/LogEntryEventBuilder_Tests.cls @@ -48,18 +48,23 @@ private class LogEntryEventBuilder_Tests { } @IsTest - static void it_should_not_run_queries_when_logging_disabled() { + static void it_should_not_run_queries_when_logging_is_disabled_via_logger_settings() { LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'QueryAuthSessionDataSynchronously', Value__c = String.valueOf(true))); + System.Assert.isTrue(LoggerParameter.QUERY_AUTH_SESSION_DATA_SYNCHRONOUSLY); LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'QueryNetworkDataSynchronously', Value__c = String.valueOf(true))); + System.Assert.isTrue(LoggerParameter.QUERY_NETWORK_DATA_SYNCHRONOUSLY); LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'QueryOrganizationDataSynchronously', Value__c = String.valueOf(true))); + System.Assert.isTrue(LoggerParameter.QUERY_ORGANIZATION_DATA_SYNCHRONOUSLY); LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'QueryUserDataSynchronously', Value__c = String.valueOf(true))); - Logger.getUserSettings().IsEnabled__c = false; - System.Assert.isFalse(Logger.isEnabled()); + System.Assert.isTrue(LoggerParameter.QUERY_USER_DATA_SYNCHRONOUSLY); + LoggerSettings__c userSettings = getUserSettings(); + userSettings.IsEnabled__c = false; System.Assert.areEqual(0, System.Limits.getQueries()); - new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, Logger.getUserSettings().IsEnabled__c, new Set()) + new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, userSettings.IsEnabled__c, new Set()) .setMessage('some message') .getLogEntryEvent(); + System.Assert.areEqual(0, System.Limits.getQueries()); } @@ -276,7 +281,8 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_not_apply_data_mask_rule_when_rule_disabled() { - Logger.getUserSettings().IsDataMaskingEnabled__c = true; + LoggerSettings__c userSettings = getUserSettings(); + userSettings.IsDataMaskingEnabled__c = true; LogEntryDataMaskRule__mdt rule = getSocialSecurityNumberDataMaskRule(); rule.IsEnabled__c = false; LogEntryEventBuilder.setMockDataMaskRule(rule); @@ -284,7 +290,7 @@ private class LogEntryEventBuilder_Tests { Account account = new Account(Name = message); String accountJson = JSON.serializePretty(account); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); builder.setMessage(message).setRecord(account); System.Assert.isFalse(builder.getLogEntryEvent().MessageMasked__c, builder.getLogEntryEvent().Message__c); @@ -295,7 +301,8 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_not_apply_data_mask_rule_when_disabled_for_user() { - Logger.getUserSettings().IsDataMaskingEnabled__c = false; + LoggerSettings__c userSettings = getUserSettings(); + userSettings.IsDataMaskingEnabled__c = false; LogEntryDataMaskRule__mdt rule = getSocialSecurityNumberDataMaskRule(); rule.IsEnabled__c = true; LogEntryEventBuilder.setMockDataMaskRule(rule); @@ -303,7 +310,7 @@ private class LogEntryEventBuilder_Tests { Account account = new Account(Name = message); String accountJson = JSON.serializePretty(account); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); builder.setMessage(message).setRecord(account); System.Assert.isFalse(builder.getLogEntryEvent().MessageMasked__c); @@ -314,14 +321,15 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_apply_data_mask_rule_to_message_when_enabled() { - Logger.getUserSettings().IsDataMaskingEnabled__c = true; + LoggerSettings__c userSettings = getUserSettings(); + userSettings.IsDataMaskingEnabled__c = true; LogEntryDataMaskRule__mdt rule = getSocialSecurityNumberDataMaskRule(); rule.IsEnabled__c = true; LogEntryEventBuilder.setMockDataMaskRule(rule); 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(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); builder.setMessage(sensitiveString); System.Assert.isTrue(builder.getLogEntryEvent().MessageMasked__c); @@ -331,7 +339,8 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_apply_data_mask_rule_to_record_json_when_enabled() { - Logger.getUserSettings().IsDataMaskingEnabled__c = true; + LoggerSettings__c userSettings = getUserSettings(); + userSettings.IsDataMaskingEnabled__c = true; LogEntryDataMaskRule__mdt rule = getSocialSecurityNumberDataMaskRule(); rule.IsEnabled__c = true; LogEntryEventBuilder.setMockDataMaskRule(rule); @@ -341,7 +350,7 @@ private class LogEntryEventBuilder_Tests { String accountJson = JSON.serializePretty(account); String expectedSanitizedAccountJson = JSON.serializePretty(new Account(Name = expectedSanitizedString)); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); builder.setRecord(account); System.Assert.isTrue(builder.getLogEntryEvent().RecordJsonMasked__c); @@ -351,7 +360,8 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_apply_data_mask_rule_to_record_list_json_when_enabled() { - Logger.getUserSettings().IsDataMaskingEnabled__c = true; + LoggerSettings__c userSettings = getUserSettings(); + userSettings.IsDataMaskingEnabled__c = true; LogEntryDataMaskRule__mdt rule = getSocialSecurityNumberDataMaskRule(); rule.IsEnabled__c = true; LogEntryEventBuilder.setMockDataMaskRule(rule); @@ -361,7 +371,7 @@ private class LogEntryEventBuilder_Tests { List accounts = new List{ new Account(Name = sensitiveString) }; String accountListJson = JSON.serializePretty(accounts); String expectedSanitizedAccountListJson = JSON.serializePretty(new List{ new Account(Name = expectedSanitizedString) }); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); builder.setRecord(accounts); System.Assert.isTrue(builder.getLogEntryEvent().RecordJsonMasked__c); @@ -371,7 +381,8 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_apply_data_mask_rule_to_http_request_body_when_enabled() { - Logger.getUserSettings().IsDataMaskingEnabled__c = true; + LoggerSettings__c userSettings = getUserSettings(); + userSettings.IsDataMaskingEnabled__c = true; LogEntryDataMaskRule__mdt rule = getSocialSecurityNumberDataMaskRule(); rule.IsEnabled__c = true; LogEntryEventBuilder.setMockDataMaskRule(rule); @@ -380,7 +391,7 @@ private class LogEntryEventBuilder_Tests { System.HttpRequest httpRequest = LoggerMockDataCreator.createHttpRequest(); httpRequest.setBody(sensitiveString); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); builder.setHttpRequestDetails(httpRequest); System.Assert.isTrue(builder.getLogEntryEvent().HttpRequestBodyMasked__c); @@ -390,7 +401,8 @@ private class LogEntryEventBuilder_Tests { @IsTest static void it_should_apply_data_mask_rule_to_http_response_body_when_enabled() { - Logger.getUserSettings().IsDataMaskingEnabled__c = true; + LoggerSettings__c userSettings = getUserSettings(); + userSettings.IsDataMaskingEnabled__c = true; LogEntryDataMaskRule__mdt rule = getSocialSecurityNumberDataMaskRule(); rule.IsEnabled__c = true; LogEntryEventBuilder.setMockDataMaskRule(rule); @@ -399,7 +411,7 @@ private class LogEntryEventBuilder_Tests { System.HttpResponse httpResponse = LoggerMockDataCreator.createHttpResponse(); httpResponse.setBody(sensitiveString); - LogEntryEventBuilder builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()); builder.setHttpResponseDetails(httpResponse); System.Assert.isTrue(builder.getLogEntryEvent().HttpResponseBodyMasked__c); @@ -813,8 +825,9 @@ private class LogEntryEventBuilder_Tests { LogEntryEventBuilder builder; System.runAs(standardUser) { - Logger.getUserSettings().IsRecordFieldStrippingEnabled__c = true; - builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()).setRecord(mockAggregateResult); + LoggerSettings__c userSettings = getUserSettings(); + userSettings.IsRecordFieldStrippingEnabled__c = true; + builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()).setRecord(mockAggregateResult); } System.Assert.areEqual(JSON.serializePretty(mockAggregateResult), builder.getLogEntryEvent().RecordJson__c); @@ -827,8 +840,9 @@ private class LogEntryEventBuilder_Tests { LogEntryEventBuilder builder; System.runAs(standardUser) { - Logger.getUserSettings().IsRecordFieldStrippingEnabled__c = true; - builder = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true, new Set()).setRecord(mockAggregateResults); + LoggerSettings__c userSettings = getUserSettings(); + userSettings.IsRecordFieldStrippingEnabled__c = true; + builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.INFO, true, new Set()).setRecord(mockAggregateResults); } System.Assert.areEqual(JSON.serializePretty(mockAggregateResults), builder.getLogEntryEvent().RecordJson__c); @@ -1018,7 +1032,7 @@ private class LogEntryEventBuilder_Tests { static void it_should_not_set_stack_trace_for_new_builder_instance_when_disabled_via_logger_parameter() { // Don't bother testing stack trace logic when using a namespace prefix - there are // some platform limitations that prevent these tests from behaving as expected - if (String.isNotBlank(Logger.getNamespacePrefix()) == true) { + if (LogEntryEventBuilder.class.getName().contains('.') == true) { return; } @@ -1036,7 +1050,7 @@ private class LogEntryEventBuilder_Tests { static void it_should_not_set_stack_trace_for_parseStackTrace_method_when_disabled_via_logger_parameter() { // Don't bother testing stack trace logic when using a namespace prefix - there are // some platform limitations that prevent these tests from behaving as expected - if (String.isNotBlank(Logger.getNamespacePrefix()) == true) { + if (LogEntryEventBuilder.class.getName().contains('.') == true) { return; } @@ -1055,7 +1069,7 @@ private class LogEntryEventBuilder_Tests { static void it_should_set_stack_trace_and_origin_location_for_class_constructor_trace_string() { // Don't bother testing stack trace logic when using a namespace prefix - there are // some platform limitations that prevent these tests from behaving as expected - if (String.isNotBlank(Logger.getNamespacePrefix()) == true) { + if (LogEntryEventBuilder.class.getName().contains('.') == true) { return; } @@ -1079,7 +1093,7 @@ private class LogEntryEventBuilder_Tests { static void it_should_set_stack_trace_and_origin_location_for_method_stack_trace_string() { // Don't bother testing stack trace logic when using a namespace prefix - there are // some platform limitations that prevent these tests from behaving as expected - if (String.isNotBlank(Logger.getNamespacePrefix()) == true) { + if (LogEntryEventBuilder.class.getName().contains('.') == true) { return; } @@ -1218,10 +1232,11 @@ private class LogEntryEventBuilder_Tests { } @IsTest - static void it_should_not_set_user_fields_when_anonymous_mode_enabled() { - Logger.getUserSettings().IsAnonymousModeEnabled__c = true; + static void it_should_not_set_user_fields_when_anonymous_mode_is_enabled() { + LoggerSettings__c userSettings = getUserSettings(); + userSettings.IsAnonymousModeEnabled__c = true; - LogEntryEventBuilder builder = Logger.debug('test log entry'); + LogEntryEventBuilder builder = new LogEntryEventBuilder(userSettings, System.LoggingLevel.DEBUG, true, new Set()); System.Assert.isNull(builder.getLogEntryEvent().Locale__c); System.Assert.isNull(builder.getLogEntryEvent().LoggedById__c); @@ -1253,7 +1268,7 @@ private class LogEntryEventBuilder_Tests { static void it_should_use_configured_log_entry_event_fields_for_debug_string() { // Don't bother testing stack trace logic when using a namespace prefix - there are // some platform limitations that prevent these tests from behaving as expected - if (String.isNotBlank(Logger.getNamespacePrefix()) == true) { + if (LogEntryEventBuilder.class.getName().contains('.') == true) { return; } @@ -1262,7 +1277,9 @@ private class LogEntryEventBuilder_Tests { ); DebugStringExample example = new DebugStringExample(); - LogEntryEventBuilder builder = example.myMethod(); + LoggerSettings__c userSettings = getUserSettings(); + userSettings.IsApexSystemDebugLoggingEnabled__c = true; + LogEntryEventBuilder builder = example.myMethod(userSettings); System.Assert.areEqual( DebugStringExample.class.getName() + @@ -1311,15 +1328,15 @@ private class LogEntryEventBuilder_Tests { public DebugStringExample() { this.stackTraceHandler = new System.DmlException(); - Logger.debug('Logging in a constructor'); } public String getStackTraceString() { return this.stackTraceHandler.getStackTraceString(); } - public LogEntryEventBuilder myMethod() { - return Logger.debug(loggingString); + public LogEntryEventBuilder myMethod(LoggerSettings__c userSettings) { + return new LogEntryEventBuilder(userSettings, System.LoggingLevel.DEBUG, true, new Set{ LogEntryEventBuilder.class.getName() }) + .setMessage(loggingString); } } 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 28d51b260..21b471f70 100644 --- a/nebula-logger/core/tests/logger-engine/classes/Logger_Tests.cls +++ b/nebula-logger/core/tests/logger-engine/classes/Logger_Tests.cls @@ -28,20 +28,85 @@ private class Logger_Tests { @IsTest static void it_should_use_in_memory_default_settings_when_not_configured() { LoggerSettings__c expectedSettings = (LoggerSettings__c) LoggerSettings__c.SObjectType.newSObject(null, true); + if (LoggerEngineDataSelector.getInstance().getCachedOrganization()?.IsSandbox == true) { + expectedSettings.LoggingLevel__c = System.LoggingLevel.FINEST.name(); + expectedSettings.IsApexSystemDebugLoggingEnabled__c = true; + expectedSettings.IsJavaScriptConsoleLoggingEnabled__c = true; + } + expectedSettings.SetupOwnerId = System.UserInfo.getUserId(); + + LoggerSettings__c returnedSettings = Logger.getUserSettings(); + + System.Assert.areEqual(expectedSettings, returnedSettings); + System.Assert.isNull(returnedSettings.Id); + List existingSettings = [SELECT Id FROM LoggerSettings__c]; + System.Assert.areEqual(0, existingSettings.size(), 'LoggerSettings__c record should not have been saved'); + } + + @IsTest + static void it_should_settings_default_field_values_when_organization_is_a_sandbox() { + Organization mockOrganization = (Schema.Organization) LoggerMockDataCreator.setReadOnlyField(new Organization(), Schema.Organization.IsSandbox, true); + System.Assert.isTrue(mockOrganization.IsSandbox); + MockLoggerEngineDataSelector mockSelector = new MockLoggerEngineDataSelector(); + mockSelector.setCachedOrganization(mockOrganization); + LoggerEngineDataSelector.setMock(mockSelector); + LoggerSettings__c expectedSettings = (LoggerSettings__c) LoggerSettings__c.SObjectType.newSObject(null, true); + expectedSettings.LoggingLevel__c = System.LoggingLevel.FINEST.name(); + expectedSettings.IsApexSystemDebugLoggingEnabled__c = true; + expectedSettings.IsJavaScriptConsoleLoggingEnabled__c = true; + expectedSettings.SetupOwnerId = System.UserInfo.getUserId(); + + LoggerSettings__c returnedSettings = Logger.getUserSettings(); + + System.Assert.areEqual(expectedSettings, returnedSettings); + System.Assert.isNull(returnedSettings.Id); + List existingSettings = [SELECT Id FROM LoggerSettings__c]; + System.Assert.areEqual(0, existingSettings.size(), 'LoggerSettings__c record should not have been saved'); + } + + @IsTest + static void it_should_settings_default_field_values_when_organization_is_not_a_sandbox() { + Organization mockOrganization = (Schema.Organization) LoggerMockDataCreator.setReadOnlyField(new Organization(), Schema.Organization.IsSandbox, false); + System.Assert.isFalse(mockOrganization.IsSandbox); + MockLoggerEngineDataSelector mockSelector = new MockLoggerEngineDataSelector(); + mockSelector.setCachedOrganization(mockOrganization); + LoggerEngineDataSelector.setMock(mockSelector); + LoggerSettings__c expectedSettings = (LoggerSettings__c) LoggerSettings__c.SObjectType.newSObject(null, true); + expectedSettings.LoggingLevel__c = System.LoggingLevel.INFO.name(); + expectedSettings.IsApexSystemDebugLoggingEnabled__c = false; + expectedSettings.IsJavaScriptConsoleLoggingEnabled__c = false; expectedSettings.SetupOwnerId = System.UserInfo.getUserId(); LoggerSettings__c returnedSettings = Logger.getUserSettings(); + System.Assert.areEqual(expectedSettings, returnedSettings); + System.Assert.isNull(returnedSettings.Id); List existingSettings = [SELECT Id FROM LoggerSettings__c]; System.Assert.areEqual(0, existingSettings.size(), 'LoggerSettings__c record should not have been saved'); + } + + @IsTest + static void it_should_settings_default_field_values_when_querying_organization_synchronously_is_disabled() { + LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'QueryOrganizationDataSynchronously', Value__c = String.valueOf(false))); + System.Assert.isFalse(LoggerParameter.QUERY_ORGANIZATION_DATA_SYNCHRONOUSLY); + LoggerSettings__c expectedSettings = (LoggerSettings__c) LoggerSettings__c.SObjectType.newSObject(null, true); + expectedSettings.LoggingLevel__c = System.LoggingLevel.INFO.name(); + expectedSettings.IsApexSystemDebugLoggingEnabled__c = false; + expectedSettings.IsJavaScriptConsoleLoggingEnabled__c = false; + expectedSettings.SetupOwnerId = System.UserInfo.getUserId(); + + LoggerSettings__c returnedSettings = Logger.getUserSettings(); + System.Assert.areEqual(expectedSettings, returnedSettings); System.Assert.isNull(returnedSettings.Id); + List existingSettings = [SELECT Id FROM LoggerSettings__c]; + System.Assert.areEqual(0, existingSettings.size(), 'LoggerSettings__c record should not have been saved'); } @IsTest static void it_should_use_org_default_settings_when_configured() { LoggerSettings__c expectedSettings = LoggerSettings__c.getOrgDefaults(); - expectedSettings.LoggingLevel__c = System.LoggingLevel.FINEST.name(); + expectedSettings.LoggingLevel__c = System.LoggingLevel.FINE.name(); insert expectedSettings; expectedSettings = LoggerSettings__c.getOrgDefaults(); expectedSettings.Id = null; @@ -743,8 +808,9 @@ private class Logger_Tests { @IsTest static void it_should_return_the_buffer_size() { System.Assert.areEqual(0, Logger.getBufferSize()); + System.Assert.isTrue(Logger.isInfoEnabled()); - Logger.debug('test log entry'); + Logger.info('test log entry'); Logger.warn('another test log entry'); System.Assert.areEqual(2, Logger.getBufferSize()); @@ -1144,8 +1210,9 @@ private class Logger_Tests { ) ); List logEntryEvents = new List(); - logEntryEvents.add(Logger.debug('test log entry').getLogEntryEvent()); - logEntryEvents.add(Logger.debug('another test log entry').getLogEntryEvent()); + System.Assert.isTrue(Logger.isInfoEnabled()); + logEntryEvents.add(Logger.info('test log entry').getLogEntryEvent()); + logEntryEvents.add(Logger.info('another test log entry').getLogEntryEvent()); System.Test.startTest(); System.Assert.areEqual(0, System.Limits.getPublishImmediateDml()); System.Assert.areEqual(0, System.Limits.getQueueableJobs()); @@ -1196,8 +1263,8 @@ private class Logger_Tests { ) ); List logEntryEvents = new List(); - logEntryEvents.add(Logger.debug('test log entry').getLogEntryEvent()); - logEntryEvents.add(Logger.debug('another test log entry').getLogEntryEvent()); + logEntryEvents.add(Logger.info('test log entry').getLogEntryEvent()); + logEntryEvents.add(Logger.info('another test log entry').getLogEntryEvent()); System.Test.startTest(); System.Assert.areEqual(0, System.Limits.getPublishImmediateDml()); System.Assert.areEqual(0, System.Limits.getQueueableJobs()); @@ -1238,8 +1305,8 @@ private class Logger_Tests { @IsTest static void it_should_flush_buffer() { - Logger.debug('test log entry'); - Logger.debug('another test log entry'); + Logger.info('test log entry'); + Logger.info('another test log entry'); System.Assert.areEqual(2, Logger.getBufferSize()); Logger.flushBuffer(); @@ -7003,6 +7070,18 @@ private class Logger_Tests { } } + private class MockLoggerEngineDataSelector extends LoggerEngineDataSelector { + private Organization cachedOrganization; + + public override Organization getCachedOrganization() { + return this.cachedOrganization; + } + + public void setCachedOrganization(Schema.Organization organization) { + this.cachedOrganization = organization; + } + } + public class MockSObjectHandler extends LoggerSObjectHandler { public Integer executionCount = 0; public TriggerOperation executedTriggerOperationType; diff --git a/nebula-logger/extra-tests/classes/ExampleInboundEmailHandler.cls b/nebula-logger/extra-tests/classes/ExampleInboundEmailHandler.cls index b3de67764..93c810748 100644 --- a/nebula-logger/extra-tests/classes/ExampleInboundEmailHandler.cls +++ b/nebula-logger/extra-tests/classes/ExampleInboundEmailHandler.cls @@ -27,9 +27,9 @@ global with sharing class ExampleInboundEmailHandler implements Messaging.Inboun Logger.error(logEntryMessage, apexException); } finally { result.success = true; - Logger.debug('Logger buffer size before save: ' + Logger.getBufferSize()); + Logger.info('Logger buffer size before save: ' + Logger.getBufferSize()); Logger.saveLog(); - Logger.debug('Logger buffer size after save: ' + Logger.getBufferSize()); + Logger.info('Logger buffer size after save: ' + Logger.getBufferSize()); } return result; diff --git a/nebula-logger/extra-tests/classes/FeatureManagement.cls b/nebula-logger/extra-tests/classes/FeatureManagement.cls new file mode 100644 index 000000000..37f4988b7 --- /dev/null +++ b/nebula-logger/extra-tests/classes/FeatureManagement.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.FeatureManagement` instead of just `FeatureManagement` +@SuppressWarnings('PMD.ApexDoc, PMD.EmptyStatementBlock') +public class FeatureManagement { +} diff --git a/nebula-logger/extra-tests/classes/FeatureManagement.cls-meta.xml b/nebula-logger/extra-tests/classes/FeatureManagement.cls-meta.xml new file mode 100644 index 000000000..1248daa86 --- /dev/null +++ b/nebula-logger/extra-tests/classes/FeatureManagement.cls-meta.xml @@ -0,0 +1,5 @@ + + + 56.0 + Active + diff --git a/nebula-logger/extra-tests/tests/LoggerSettingsController_Tests_Security.cls b/nebula-logger/extra-tests/tests/LoggerSettingsController_Tests_Security.cls index e19f61081..c599b98c0 100644 --- a/nebula-logger/extra-tests/tests/LoggerSettingsController_Tests_Security.cls +++ b/nebula-logger/extra-tests/tests/LoggerSettingsController_Tests_Security.cls @@ -24,7 +24,10 @@ private class LoggerSettingsController_Tests_Security { insert new List{ setupEntityAccess, permissionSetAssignment }; System.runAs(standardUser) { - System.Assert.isTrue(FeatureManagement.checkPermission(CAN_MODIFY_LOGGER_SETTINGS_PERMISSION_NAME), JSON.serializePretty(permissionSetAssignment)); + System.Assert.isTrue( + System.FeatureManagement.checkPermission(CAN_MODIFY_LOGGER_SETTINGS_PERMISSION_NAME), + JSON.serializePretty(permissionSetAssignment) + ); System.Assert.isTrue(LoggerSettingsController.canUserModifyLoggerSettings()); } } @@ -36,7 +39,7 @@ private class LoggerSettingsController_Tests_Security { LoggerTestConfigurator.assignAdminPermissionSet(standardUser.Id); System.runAs(standardUser) { - System.Assert.isTrue(FeatureManagement.checkPermission(CAN_MODIFY_LOGGER_SETTINGS_PERMISSION_NAME)); + System.Assert.isTrue(System.FeatureManagement.checkPermission(CAN_MODIFY_LOGGER_SETTINGS_PERMISSION_NAME)); System.Assert.isTrue(LoggerSettingsController.canUserModifyLoggerSettings()); } } @@ -48,7 +51,7 @@ private class LoggerSettingsController_Tests_Security { LoggerTestConfigurator.assignLogViewerPermissionSet(standardUser.Id); System.runAs(standardUser) { - System.Assert.isFalse(FeatureManagement.checkPermission(CAN_MODIFY_LOGGER_SETTINGS_PERMISSION_NAME)); + System.Assert.isFalse(System.FeatureManagement.checkPermission(CAN_MODIFY_LOGGER_SETTINGS_PERMISSION_NAME)); System.Assert.isFalse(LoggerSettingsController.canUserModifyLoggerSettings()); } } @@ -60,7 +63,7 @@ private class LoggerSettingsController_Tests_Security { LoggerTestConfigurator.assignEndUserPermissionSet(standardUser.Id); System.runAs(standardUser) { - System.Assert.isFalse(FeatureManagement.checkPermission(CAN_MODIFY_LOGGER_SETTINGS_PERMISSION_NAME)); + System.Assert.isFalse(System.FeatureManagement.checkPermission(CAN_MODIFY_LOGGER_SETTINGS_PERMISSION_NAME)); System.Assert.isFalse(LoggerSettingsController.canUserModifyLoggerSettings()); } } @@ -72,7 +75,7 @@ private class LoggerSettingsController_Tests_Security { LoggerTestConfigurator.assignLogCreatorPermissionSet(standardUser.Id); System.runAs(standardUser) { - System.Assert.isFalse(FeatureManagement.checkPermission(CAN_MODIFY_LOGGER_SETTINGS_PERMISSION_NAME)); + System.Assert.isFalse(System.FeatureManagement.checkPermission(CAN_MODIFY_LOGGER_SETTINGS_PERMISSION_NAME)); System.Assert.isFalse(LoggerSettingsController.canUserModifyLoggerSettings()); } } diff --git a/package.json b/package.json index df37bc54a..495825249 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nebula-logger", - "version": "4.9.5", + "version": "4.9.6", "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 0af76f2e3..de4dd9f0e 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -14,8 +14,8 @@ "package": "Nebula Logger - Core", "path": "./nebula-logger/core", "definitionFile": "./config/scratch-orgs/base-scratch-def.json", - "versionNumber": "4.9.5.NEXT", - "versionName": "Configurable Platform Cache Partition Name", + "versionNumber": "4.9.6.NEXT", + "versionName": "Environment-Aware Default Field Values For Logger Settings", "versionDescription": "Added new CMDT record LoggerParameter.PlatformCachePartitionName to control which platform cache partition is used for caching", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases", "unpackagedMetadata": { @@ -149,6 +149,7 @@ "Nebula Logger - Core@4.9.3-new-indicator-icons": "04t5Y0000023R7sQAE", "Nebula Logger - Core@4.9.4-new-indicator-icons": "04t5Y0000023R8WQAU", "Nebula Logger - Core@4.9.5-configurable-platform-cache-partition-name": "04t5Y0000023R9KQAU", + "Nebula Logger - Core@4.9.6-environment-aware-default-field-values-for-logger-settings": "04t5Y0000023R9eQAE", "Nebula Logger - Plugin - Async Failure Additions": "0Ho5Y000000blO4SAI", "Nebula Logger - Plugin - Async Failure Additions@1.0.0": "04t5Y0000015lhiQAA", "Nebula Logger - Plugin - Async Failure Additions@1.0.1": "04t5Y0000015lhsQAA",