Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Properly handle logs created and saved through createLogger in pre-mounted instances #577

Merged
merged 6 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.11
## Unlocked Package - v4.11.12

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

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

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

---

Expand Down
2 changes: 1 addition & 1 deletion 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.11';
private static final String CURRENT_VERSION_NUMBER = 'v4.11.12';
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
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const ComponentLogEntry = class {
}
};

/* eslint-disable @lwc/lwc/no-dupe-class-members */
const LogEntryBuilder = class {
#componentLogEntry;
#settingsPromise;
Expand Down Expand Up @@ -138,7 +139,7 @@ const LogEntryBuilder = class {
/* eslint-disable no-console */
_logToConsole() {
this.#settingsPromise().then(setting => {
this.isConsoleLoggingEnabled = setting.isConsoleLoggingEnabled;
this.isConsoleLoggingEnabled = !!setting?.isConsoleLoggingEnabled;

if (!this.isConsoleLoggingEnabled) {
return;
Expand Down
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.11';
const CURRENT_VERSION_NUMBER = 'v4.11.12';

export default class Logger extends LightningElement {
#loggerService = createLoggerService();
Expand Down
62 changes: 47 additions & 15 deletions nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,17 @@ import { newLogEntry } from './logEntryBuilder';
import getSettings from '@salesforce/apex/ComponentLogger.getSettings';
import saveComponentLogEntries from '@salesforce/apex/ComponentLogger.saveComponentLogEntries';

const LOADING_ENUM = {
loading: 'loading',
enabled: 'enabled',
disabled: 'disabled'
};

/* eslint-disable @lwc/lwc/no-dupe-class-members */
const LoggerService = class {
static settings = undefined;

#isSavingLog = false;
#componentLogEntries = [];
#scenario;
#loggingPromises = [];
Expand Down Expand Up @@ -113,17 +120,18 @@ const LoggerService = class {
* @return {Integer} The buffer's current size
*/
getBufferSize() {
return this.#componentLogEntries.length;
return this.#componentLogEntries.length + this.#loggingPromises.length;
}

/**
* @description Discards any entries that have been generated but not yet saved
* @return {Promise<void>} A promise to clear the entries
*/
flushBuffer() {
async flushBuffer() {
return Promise.all(this.#loggingPromises).then(() => {
this.#componentLogEntries = [];
this.#loggingPromises = [];
this.#isSavingLog = false;
});
}

Expand All @@ -132,17 +140,31 @@ const LoggerService = class {
* All subsequent calls to saveLog() will use the transaction save method
* @param {String} saveMethod The enum value of LoggerService.SaveMethod to use for this specific save action
*/
saveLog(saveMethodName) {
if (this.getBufferSize() > 0) {
async saveLog(saveMethodName) {
this.#isSavingLog = true;

const filteredLogEntries = this.#componentLogEntries.filter(
possibleLogEntry =>
(possibleLogEntry.loadingEnum === LOADING_ENUM.loading &&
this._meetsUserLoggingLevel(possibleLogEntry.loggingLevel) === LOADING_ENUM.enabled) ||
possibleLogEntry.loadingEnum === LOADING_ENUM.enabled
);

if (filteredLogEntries.length > 0) {
let resolvedSaveMethodName;
if (!saveMethodName && LoggerService.settings && LoggerService.settings.defaultSaveMethodName) {
resolvedSaveMethodName = LoggerService.settings.defaultSaveMethodName;
} else {
resolvedSaveMethodName = saveMethodName;
}

Promise.all(this.#loggingPromises)
.then(saveComponentLogEntries({ componentLogEntries: this.#componentLogEntries, saveMethodName: resolvedSaveMethodName }))
return Promise.all(this.#loggingPromises)
.then(
saveComponentLogEntries({
componentLogEntries: filteredLogEntries,
saveMethodName: resolvedSaveMethodName
})
)
.then(this.flushBuffer())
.catch(error => {
if (LoggerService.settings.isConsoleLoggingEnabled === true) {
Expand All @@ -153,6 +175,7 @@ const LoggerService = class {
}
});
}
return Promise.resolve();
}

_loadSettingsFromServer(forceReload) {
Expand All @@ -173,27 +196,36 @@ const LoggerService = class {
}

_meetsUserLoggingLevel(logEntryLoggingLevel) {
let logEntryLoggingLevelOrdinal = LoggerService.settings.supportedLoggingLevels[logEntryLoggingLevel];
return (
LoggerService.settings &&
LoggerService.settings.isEnabled === true &&
LoggerService.settings.userLoggingLevel.ordinal <= logEntryLoggingLevelOrdinal
);
if (LoggerService.settings && LoggerService.settings.supportedLoggingLevels && LoggerService.settings.userLoggingLevel) {
const currentIsEnabled =
LoggerService.settings.isEnabled === true &&
LoggerService.settings.userLoggingLevel.ordinal <= LoggerService.settings?.supportedLoggingLevels[logEntryLoggingLevel];
return currentIsEnabled ? LOADING_ENUM.enabled : LOADING_ENUM.disabled;
}
return LOADING_ENUM.loading;
}

_newEntry(loggingLevel, message) {
// Builder is returned immediately but console log will be determined after loadding settings from server
// Builder is returned immediately but console log will be determined after loading settings from server
const logEntryBuilder = newLogEntry(loggingLevel, this._loadSettingsFromServer);
logEntryBuilder.setMessage(message);
if (this.#scenario) {
logEntryBuilder.scenario = this.#scenario;
}
const loggingPromise = this._loadSettingsFromServer().then(() => {
if (this._meetsUserLoggingLevel(loggingLevel) === true) {
this.#componentLogEntries.push(logEntryBuilder.getComponentLogEntry());
const isEnabledEnum = this._meetsUserLoggingLevel(loggingLevel);
if (isEnabledEnum === LOADING_ENUM.enabled || isEnabledEnum === LOADING_ENUM.loading) {
const componentLogEntry = logEntryBuilder.getComponentLogEntry();
componentLogEntry.loadingEnum = isEnabledEnum;
this.#componentLogEntries.push(componentLogEntry);
}
if (this.#isSavingLog) {
this.#isSavingLog = false;
this.saveLog();
}
});
this.#loggingPromises.push(loggingPromise);

return logEntryBuilder;
}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { createElement } from 'lwc';
import LoggerLWCDemo from 'c/loggerLWCDemo';

import getSettings from '@salesforce/apex/ComponentLogger.getSettings';

const flushPromises = async () => {
await new Promise(process.nextTick);
};

const MOCK_GET_SETTINGS = {
defaultSaveMethod: 'EVENT_BUS',
isEnabled: true,
isConsoleLoggingEnabled: true,
supportedLoggingLevels: { FINEST: 2, FINER: 3, FINE: 4, DEBUG: 5, INFO: 6, WARN: 7, ERROR: 8 },
userLoggingLevel: { ordinal: 2, name: 'FINEST' }
};

jest.mock(
'@salesforce/apex/ComponentLogger.getSettings',
() => {
return {
default: jest.fn()
};
},
{ virtual: true }
);

describe('logger demo tests', () => {
afterEach(() => {
while (document.body.firstChild) {
document.body.removeChild(document.body.firstChild);
}
jest.clearAllMocks();
});

it('mounts and saves log correctly in one go', async () => {
getSettings.mockResolvedValue({ ...MOCK_GET_SETTINGS });
const demo = createElement('c-logger-demo', { is: LoggerLWCDemo });
document.body.appendChild(demo);

await flushPromises();

expect(demo.logger?.getBufferSize()).toBe(0);
});
});
19 changes: 15 additions & 4 deletions nebula-logger/recipes/lwc/loggerLWCDemo/loggerLWCDemo.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,21 @@ export default class LoggerLWCDemo extends LightningElement {

connectedCallback() {
console.log('>>> start of connectedCallback()');
this.logger.info('>>> running connectedCallback(), using createLogger()');
this.logger.info('>>> adding an extra log entry');
this.logger.saveLog();
console.log('>>> done with connectedCallback()');
try {
this.logger.error('test error entry');
this.logger.warn('test warn entry');
this.logger.info('test info entry');
this.logger.debug('test debug entry');
this.logger.fine('test fine entry');
this.logger.finer('test finer entry');
this.logger.finest('test finest entry');
throw new Error('A bad thing happened here');
} catch (error) {
this.logger.error('>>> connectedCallback error: ' + JSON.stringify(error));
this.logger.saveLog().then(() => {
console.log('done with async save');
});
}
}

disconnectedCallback() {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nebula-logger",
"version": "4.11.11",
"version": "4.11.12",
"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",
Expand Down
7 changes: 4 additions & 3 deletions sfdx-project.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
"package": "Nebula Logger - Core",
"path": "./nebula-logger/core",
"definitionFile": "./config/scratch-orgs/base-scratch-def.json",
"versionNumber": "4.11.11.NEXT",
"versionName": "Reduced Usage of Email Limits Consumption in LoggerEmailSender",
"versionDescription": "Updated LoggerEmailSender to use the instance method Messaging.SingleEmailMessage.setTargetObjectId() when sending failure emails to internal users, which does not count towards the transactional email limits",
"versionNumber": "4.11.12.NEXT",
"versionName": "Bugfix for Lightning Component Entries Not Always Saving",
"versionDescription": "Fixed an issue in the logger LWC where log entries in lightning components would be lost while trying to load LoggerSettings__c for the current user",
"releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases",
"unpackagedMetadata": {
"path": "./nebula-logger/extra-tests"
Expand Down Expand Up @@ -159,6 +159,7 @@
"Nebula Logger - [email protected]__c.loggedbyusernametext__c-and-logentry__c.loggedbyusernametext__c": "04t5Y000001OigJQAS",
"Nebula Logger - [email protected]": "04t5Y000001OigxQAC",
"Nebula Logger - Core@4.11.11-reduced-usage-of-email-limits-consumption-in-loggeremailsender": "04t5Y000001Oih7QAC",
"Nebula Logger - Core@4.11.12-bugfix-for-lightning-component-entries-not-always-saving": "04t5Y000001Mjx5QAC",
"Nebula Logger - Core Plugin - Async Failure Additions": "0Ho5Y000000blO4SAI",
"Nebula Logger - Core Plugin - Async Failure [email protected]": "04t5Y0000015lhiQAA",
"Nebula Logger - Core Plugin - Async Failure [email protected]": "04t5Y0000015lhsQAA",
Expand Down