Skip to content

Commit

Permalink
Updated Logger.getUserSettings() to set defaults based on the environ…
Browse files Browse the repository at this point in the history
…ment 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)
  • Loading branch information
jongpie authored Nov 30, 2022
1 parent ebe5796 commit d91e665
Show file tree
Hide file tree
Showing 20 changed files with 277 additions and 136 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<fullName>IsApexSystemDebugLoggingEnabled__c</fullName>
<businessStatus>Active</businessStatus>
<complianceGroup>CCPA;GDPR;PII</complianceGroup>
<defaultValue>true</defaultValue>
<defaultValue>false</defaultValue>
<externalId>false</externalId>
<inlineHelpText
>When enabled, Logger will automatically call Apex&apos;s System.debug(). To help with performance, this option should be disabled in production unless you are actively troubleshooting an issue.</inlineHelpText>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<fullName>IsJavaScriptConsoleLoggingEnabled__c</fullName>
<businessStatus>Active</businessStatus>
<complianceGroup>CCPA;GDPR;PII</complianceGroup>
<defaultValue>true</defaultValue>
<defaultValue>false</defaultValue>
<externalId>false</externalId>
<inlineHelpText
>When enabled, Logger will automatically call the browser&apos;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.</inlineHelpText>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<fullName>LoggingLevel__c</fullName>
<businessStatus>Active</businessStatus>
<complianceGroup>CCPA;GDPR;PII</complianceGroup>
<defaultValue>&apos;DEBUG&apos;</defaultValue>
<defaultValue>&apos;INFO&apos;</defaultValue>
<externalId>false</externalId>
<label>Logging Level</label>
<length>255</length>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down Expand Up @@ -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());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -834,21 +827,20 @@ 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;
logEntryEvent.OrganizationNamespacePrefix__c = cachedOrganization?.NamespacePrefix;
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;
}
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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() {
Expand Down
17 changes: 13 additions & 4 deletions nebula-logger/core/main/logger-engine/classes/Logger.cls
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> IGNORED_APEX_CLASSES = initializeIgnoredApexClasses();
private static final List<LogEntryEventBuilder> LOG_ENTRIES_BUFFER = new List<LogEntryEventBuilder>();
private static final String REQUEST_ID = System.Request.getCurrent().getRequestId();
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
}

Expand Down
Loading

0 comments on commit d91e665

Please sign in to comment.