Skip to content

Commit

Permalink
Reduced SingleEmailMessage limit usage (#570)
Browse files Browse the repository at this point in the history
* Fixed #369 by using instance method Messaging.SingleEmailMessage.setTargetObjectId() when sending failure emails to internal users

* Updated build.yml to delete all profiles in the unsorted directory before generating package versions, because they sometimes upset the sf cli ᕕ( ᐛ )ᕗ
  • Loading branch information
jongpie authored Oct 15, 2023
1 parent f2fe85c commit 77fe275
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 113 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,9 @@ jobs:
# TODO remove this after the plugin @salesforce/packaging has been upgraded
# to a new version that only looks at package directories
- name: 'Temporarily delete problematic metadata'
run: rm -rf ./config/experience-cloud
run: |
rm -rf ./config/experience-cloud/
rm -rf ./nebula-logger/unsorted/main/default/profiles/
- name: 'Create Beta Managed Package Version'
run: npm run package:version:create:managed
Expand Down Expand Up @@ -352,7 +354,9 @@ jobs:
# TODO remove this after the plugin @salesforce/packaging has been upgraded
# to a new version that only looks at package directories
- name: 'Temporarily delete problematic metadata'
run: rm -rf ./config/experience-cloud
run: |
rm -rf ./config/experience-cloud/
rm -rf ./nebula-logger/unsorted/main/default/profiles/
- name: 'Create & Install Package Version'
run: npx pwsh ./scripts/build/create-and-install-package-version.ps1 -targetpackagealias '"Nebula Logger - Core"' -targetreadme ./README.md -targetusername nebula-logger-package-demo
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@

The most robust logger for Salesforce. Works with Apex, Lightning Components, Flow, Process Builder & Integrations. Designed for Salesforce admins, developers & architects.

## Unlocked Package - v4.11.10
## Unlocked Package - v4.11.11

[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001OigxQAC)
[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001OigxQAC)
[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001Oih7QAC)
[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001Oih7QAC)
[![View Documentation](./images/btn-view-documentation.png)](https://jongpie.github.io/NebulaLogger/)

`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y000001OigxQAC`
`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y000001Oih7QAC`

`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y000001OigxQAC`
`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y000001Oih7QAC`

---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public without sharing class LoggerEmailSender {
private static final List<Messaging.SingleEmailMessage> SENT_EMAILS = new List<Messaging.SingleEmailMessage>();

@TestVisible
private static final List<String> CACHED_APEX_ERROR_RECIPIENTS {
private static final List<ApexEmailNotification> CACHED_APEX_ERROR_RECIPIENTS {
get {
if (CACHED_APEX_ERROR_RECIPIENTS == null) {
CACHED_APEX_ERROR_RECIPIENTS = queryApexErrrorRecipients();
Expand Down Expand Up @@ -82,18 +82,30 @@ public without sharing class LoggerEmailSender {
return;
}

if (CACHED_APEX_ERROR_RECIPIENTS.isEmpty()) {
if (LoggerParameter.ENABLE_SYSTEM_MESSAGES) {
Logger.info('Logger - no Apex email recipients configured, skipping sending email');
if (CACHED_APEX_ERROR_RECIPIENTS.isEmpty() == true) {
if (LoggerParameter.ENABLE_SYSTEM_MESSAGES == true) {
// One of a few limited places in the codebase (except tests) that should use System.debug()
// The rest of the codebase should use a method in Logger.cls
System.debug(System.LoggingLevel.WARN, 'Nebula Logger - no Apex email recipients configured, skipping sending email'); // NOPMD
}
return;
}

Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
message.setToAddresses(CACHED_APEX_ERROR_RECIPIENTS);
message.setSubject(buildSubject(errorMessages));
message.setHtmlBody(buildHtmlBody(sobjectType, errorMessages));
sendEmail(message);
List<Messaging.SingleEmailMessage> messages = new List<Messaging.SingleEmailMessage>();
for (Schema.ApexEmailNotification notification : CACHED_APEX_ERROR_RECIPIENTS) {
Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
message.setSubject(buildSubject(errorMessages));
message.setHtmlBody(buildHtmlBody(sobjectType, errorMessages));

if (notification.UserId != null) {
message.setTargetObjectId(notification.UserId);
message.setSaveAsActivity(false);
} else if (String.isNotBlank(notification.Email) == true) {
message.setToAddresses(new List<String>{ notification.Email });
}
messages.add(message);
}
sendEmail(messages);
}

private static List<String> getErrorMessages(List<Database.SaveResult> saveResults) {
Expand All @@ -120,24 +132,27 @@ public without sharing class LoggerEmailSender {
return errorMessages;
}

private static void sendEmail(Messaging.SingleEmailMessage message) {
SENT_EMAILS.add(message);
private static void sendEmail(List<Messaging.SingleEmailMessage> messages) {
SENT_EMAILS.addAll(messages);
if (IS_EMAIL_DELIVERABILITY_AVAILABLE) {
List<Messaging.SingleEmailMessage> messages = new List<Messaging.SingleEmailMessage>{ message };
List<Messaging.SendEmailResult> emailResults = Messaging.sendEmail(messages);
List<Messaging.SendEmailResult> emailResults = System.Messaging.sendEmail(messages);

if (LoggerParameter.ENABLE_SYSTEM_MESSAGES == false) {
return;
} else if (emailResults.get(0).success) {
Logger.info('Logger - The email was sent successfully');
} else if (emailResults.get(0).success == true) {
// One of a few limited places in the codebase (except tests) that should use System.debug()
// The rest of the codebase should use a method in Logger.cls
System.debug(System.LoggingLevel.INFO, 'Nebula Logger - The email was sent successfully'); // NOPMD
} else {
Logger.warn('Logger - The email failed to send: ' + emailResults.get(0).errors.get(0).message);
// One of a few limited places in the codebase (except tests) that should use System.debug()
// The rest of the codebase should use a method in Logger.cls
System.debug(System.LoggingLevel.WARN, 'Nebula Logger - The email failed to send: ' + emailResults.get(0).errors.get(0).message); // NOPMD
}
}
}

private static String buildSubject(List<String> errorMessages) {
String emailSubjectTemplate = 'Logger - Error Notification - {0} ({1})';
String emailSubjectTemplate = 'Nebula Logger - Error Notification - {0} ({1})';
List<Object> emailSubjectInputs = new List<Object>{
LoggerEngineDataSelector.getInstance().getCachedOrganization().Name,
LoggerEngineDataSelector.getInstance().getCachedOrganization().Id
Expand All @@ -158,21 +173,13 @@ public without sharing class LoggerEmailSender {
return String.format(emailBodyTemplate, emailBodyInputs);
}

private static List<String> queryApexErrrorRecipients() {
List<String> apexErrrorRecipients = new List<String>();
private static List<ApexEmailNotification> queryApexErrrorRecipients() {
List<ApexEmailNotification> notifications = LogManagementDataSelector.getInstance().getCachedApexEmailNotifications();
if (System.Test.isRunningTest()) {
notifications.clear();
notifications.addAll(MOCK_NOTIFICATIONS);
}

for (ApexEmailNotification notification : notifications) {
if (notification.UserId != null) {
apexErrrorRecipients.add(notification.UserId);
} else if (String.isNotBlank(notification.Email)) {
apexErrrorRecipients.addAll(notification.Email.split(';'));
}
}
return apexErrrorRecipients;
return notifications;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ global with sharing class LogEntryEventBuilder {
this.debugMessage = message;
}

// One of few limited places in the codebase (except tests) that should use System.debug()
// One of a few limited places in the codebase (except tests) that should use System.debug()
// The rest of the codebase should use a method in Logger.cls
System.debug(this.entryLoggingLevel, this.debugMessage);
}
Expand Down
8 changes: 4 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,7 +15,7 @@
global with sharing class Logger {
// There's no reliable way to get the version number dynamically in Apex
@TestVisible
private static final String CURRENT_VERSION_NUMBER = 'v4.11.10';
private static final String CURRENT_VERSION_NUMBER = 'v4.11.11';
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>();
Expand Down Expand Up @@ -97,7 +97,7 @@ global with sharing class Logger {
}

static {
// One of few limited places in the codebase (except tests) that should use System.debug()
// One of a few limited places in the codebase (except tests) that should use System.debug()
// The rest of the codebase should use a method in Logger.cls
System.debug(System.LoggingLevel.INFO, 'Nebula Logger - Version Number: ' + getVersionNumber());
System.debug(System.LoggingLevel.INFO, 'Nebula Logger - Transaction ID: ' + getTransactionId());
Expand Down Expand Up @@ -3041,7 +3041,7 @@ global with sharing class Logger {
global static void setScenario(String scenario) {
if (LoggerParameter.USE_FIRST_SCENARIO_FOR_TRANSACTION == false || String.isBlank(transactionScenario)) {
transactionScenario = scenario;
// One of few limited places in the codebase (except tests) that should use System.debug()
// One of a few limited places in the codebase (except tests) that should use System.debug()
// The rest of the codebase should use a method in Logger.cls
if (String.isNotBlank(transactionScenario)) {
System.debug(System.LoggingLevel.INFO, 'Nebula Logger - Transaction Scenario: ' + transactionScenario);
Expand All @@ -3054,7 +3054,7 @@ global with sharing class Logger {

currentEntryScenario = scenario;
orderedScenarios.add(scenario);
// One of few limited places in the codebase (except tests) that should use System.debug()
// One of a few limited places in the codebase (except tests) that should use System.debug()
// The rest of the codebase should use a method in Logger.cls
if (String.isNotBlank(transactionScenario)) {
System.debug(System.LoggingLevel.INFO, 'Nebula Logger - Entry Scenario: ' + currentEntryScenario);
Expand Down
2 changes: 1 addition & 1 deletion nebula-logger/core/main/logger-engine/lwc/logger/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { LightningElement, api } from 'lwc';
import { createLoggerService } from './loggerService';

const CURRENT_VERSION_NUMBER = 'v4.11.10';
const CURRENT_VERSION_NUMBER = 'v4.11.11';

export default class Logger extends LightningElement {
#loggerService = createLoggerService();
Expand Down
Loading

0 comments on commit 77fe275

Please sign in to comment.