diff --git a/docs/logger-engine/ComponentLogger.md b/docs/logger-engine/ComponentLogger.md index eaa5a4315..318a24d4a 100644 --- a/docs/logger-engine/ComponentLogger.md +++ b/docs/logger-engine/ComponentLogger.md @@ -30,15 +30,16 @@ ComponentLoggerSettings return The instance of `ComponentLoggerSettings` for the current user -#### `saveComponentLogEntries(List componentLogEntries)` → `String` +#### `saveComponentLogEntries(List componentLogEntries, String saveMethodName)` → `String` saveComponentLogEntries Saves log entries created via lwc or aura components ##### Parameters -| Param | Description | -| --------------------- | ------------------------------------------------------------ | -| `componentLogEntries` | The list of `ComponentLogEntry` objects to save via `Logger` | +| Param | Description | +| --------------------- | -------------------------------------------------------------------- | +| `componentLogEntries` | The list of `ComponentLogEntry` objects to save via `Logger` | +| `saveMethodName` | String name of the instance of Logger.SaveMethod to use when saving. | ##### Return @@ -130,6 +131,10 @@ A DTO object used for passing `LoggerSettings__c` details to lightning component ##### Properties +###### `defaultSaveMethodName` → `String` + +Indicates the save method that will be used by default if no other save method is specified, based on `LoggerSettings__c.DefaultSaveMethod__c` + ###### `isConsoleLoggingEnabled` → `Boolean` Indicates if logging via the browser's `console.log()` is enabled for the current user, based on `Logger.IsComponentConsoleLoggingEnabled__c` diff --git a/docs/logger-engine/FlowCollectionLogEntry.md b/docs/logger-engine/FlowCollectionLogEntry.md index 9ee9bf296..cb5cb4a07 100644 --- a/docs/logger-engine/FlowCollectionLogEntry.md +++ b/docs/logger-engine/FlowCollectionLogEntry.md @@ -28,7 +28,7 @@ Optionally log a Flow fault error message #### `flowName` → `String` -The name of the Flow creating the log entry. Due to Salesforce limitations, this cannot be automatically determined +The API name of the Flow creating the log entry. Due to Salesforce limitations, this cannot be automatically determined #### `loggingLevelName` → `String` diff --git a/docs/logger-engine/FlowLogEntry.md b/docs/logger-engine/FlowLogEntry.md index 7f028f9ff..9e88e9ec6 100644 --- a/docs/logger-engine/FlowLogEntry.md +++ b/docs/logger-engine/FlowLogEntry.md @@ -28,7 +28,7 @@ Optionally log a Flow fault error message #### `flowName` → `String` -The name of the Flow creating the log entry. Due to Salesforce limitations, this cannot be automatically determined. +The API name of the Flow creating the log entry. Due to Salesforce limitations, this cannot be automatically determined. #### `loggingLevelName` → `String` @@ -36,7 +36,7 @@ Optionally specify a logging level - the default is 'DEBUG' #### `message` → `String` -The message to log. +The message to log #### `recordId` → `Id` @@ -44,7 +44,7 @@ Optionally relate the log entry to a particular record ID #### `saveLog` → `Boolean` -Optionally choose to save any pending log entries. +Optionally choose to save any pending log entries #### `saveMethodName` → `String` diff --git a/docs/logger-engine/FlowLogger.md b/docs/logger-engine/FlowLogger.md index d22c737ea..28b42e009 100644 --- a/docs/logger-engine/FlowLogger.md +++ b/docs/logger-engine/FlowLogger.md @@ -60,31 +60,31 @@ String containing fault message, if applicable ###### `flowName` → `String` -name of the flow. +API name of the flow ###### `loggingLevelName` → `String` -String containing the logging level. +String name of the entry's logging level ###### `message` → `String` -General message to log. +General message to log ###### `saveLog` → `Boolean` -Boolean used to determine if logs are saved to Salesforce. +Boolean used to determine if logs are saved to Salesforce ###### `saveMethodName` → `String` -String name of the instance of Logger.SaveMethod to use saveLog == true +String name of the instance of Logger.SaveMethod to use when 'Save Log' == true ###### `scenario` → `String` -Optionally specify the name to use for the current transaction's scenario +Optionally specify the scenario to use for the current transaction ###### `tagsString` → `String` -String of tags / topics. +Comma-separated string of tags ###### `timestamp` → `DateTime` @@ -92,7 +92,7 @@ timestamp of the log ###### `topics` → `List` -List of tags / topics. +List of tags / topics --- @@ -100,7 +100,7 @@ List of tags / topics. ###### `addToLoggerBuffer()` → `LogEntryEventBuilder` -Adds the logger to the buffer. +Adds the logger to the buffer ####### Return @@ -110,6 +110,6 @@ LogEntryEventBuilder **Description** -An instance of LogEntryEventBuilder. +An instance of LogEntryEventBuilder --- diff --git a/docs/logger-engine/FlowRecordLogEntry.md b/docs/logger-engine/FlowRecordLogEntry.md index 15a652f86..d94db2d7f 100644 --- a/docs/logger-engine/FlowRecordLogEntry.md +++ b/docs/logger-engine/FlowRecordLogEntry.md @@ -28,7 +28,7 @@ Optionally log a Flow fault error message #### `flowName` → `String` -The name of the Flow creating the log entry. Due to Salesforce limitations, this cannot be automatically determined +The API name of the Flow creating the log entry. Due to Salesforce limitations, this cannot be automatically determined #### `loggingLevelName` → `String` diff --git a/nebula-logger/main/logger-engine/classes/ComponentLogger.cls b/nebula-logger/main/logger-engine/classes/ComponentLogger.cls index a531abc18..ed1076e09 100644 --- a/nebula-logger/main/logger-engine/classes/ComponentLogger.cls +++ b/nebula-logger/main/logger-engine/classes/ComponentLogger.cls @@ -26,11 +26,14 @@ public inherited sharing class ComponentLogger { /** * @description saveComponentLogEntries Saves log entries created via lwc or aura components * @param componentLogEntries The list of `ComponentLogEntry` objects to save via `Logger` + * @param saveMethodName String name of the instance of Logger.SaveMethod to use when saving. + * When null, the value of `Logger.getSaveMethod()` will be used. * @return return The transaction ID (based on `Logger.getTransactionId())` */ @AuraEnabled - public static String saveComponentLogEntries(List componentLogEntries) { + public static String saveComponentLogEntries(List componentLogEntries, String saveMethodName) { try { + Logger.SaveMethod saveMethod = Logger.getSaveMethod(); for (ComponentLogEntry componentLogEntry : componentLogEntries) { Logger.setScenario(componentLogEntry.scenario); LoggingLevel entryLoggingLevel = Logger.getLoggingLevel(componentLogEntry.loggingLevel); @@ -43,7 +46,10 @@ public inherited sharing class ComponentLogger { setComponentErrorDetails(logEntryEventBuilder, componentLogEntry.error); setStackTraceDetails(logEntryEventBuilder, componentLogEntry.stack); } - Logger.saveLog(); + if (String.isNotBlank(saveMethodName) == true) { + saveMethod = Logger.SaveMethod.valueOf(saveMethodName); + } + Logger.saveLog(saveMethod); return Logger.getTransactionId(); } catch (Exception apexException) { throw new AuraHandledException(apexException.getMessage()); @@ -124,6 +130,12 @@ public inherited sharing class ComponentLogger { * @description A DTO object used for passing `LoggerSettings__c` details to lightning components */ public class ComponentLoggerSettings { + /** + * @description Indicates the save method that will be used by default if no other save method is specified, based on `LoggerSettings__c.DefaultSaveMethod__c` + */ + @AuraEnabled + public String defaultSaveMethodName { get; set; } + /** * @description Indicates if logging is enabled for the current user, based on `LoggerSettings__c.IsEnabled__c` */ @@ -149,6 +161,7 @@ public inherited sharing class ComponentLogger { public ComponentLoggingLevel userLoggingLevel { get; set; } private ComponentLoggerSettings() { + this.defaultSaveMethodName = Logger.getSaveMethod().name(); this.isEnabled = Logger.getUserSettings().IsEnabled__c; this.isConsoleLoggingEnabled = Logger.getUserSettings().IsComponentConsoleLoggingEnabled__c; this.supportedLoggingLevels = getSupportedLoggingLevels(); diff --git a/nebula-logger/main/logger-engine/classes/FlowCollectionLogEntry.cls b/nebula-logger/main/logger-engine/classes/FlowCollectionLogEntry.cls index 1f6faef1d..f0219cbba 100644 --- a/nebula-logger/main/logger-engine/classes/FlowCollectionLogEntry.cls +++ b/nebula-logger/main/logger-engine/classes/FlowCollectionLogEntry.cls @@ -15,7 +15,7 @@ @SuppressWarnings('PMD.AvoidGlobalModifier') global inherited sharing class FlowCollectionLogEntry { /** - * @description The name of the Flow creating the log entry. + * @description The API name of the Flow creating the log entry. * Due to Salesforce limitations, this cannot be automatically determined */ @InvocableVariable(required=true label='Flow API Name') diff --git a/nebula-logger/main/logger-engine/classes/FlowLogEntry.cls b/nebula-logger/main/logger-engine/classes/FlowLogEntry.cls index 9bec314da..da1708fa3 100644 --- a/nebula-logger/main/logger-engine/classes/FlowLogEntry.cls +++ b/nebula-logger/main/logger-engine/classes/FlowLogEntry.cls @@ -15,14 +15,14 @@ @SuppressWarnings('PMD.AvoidGlobalModifier') global inherited sharing class FlowLogEntry { /** - * @description The name of the Flow creating the log entry. + * @description The API name of the Flow creating the log entry. * Due to Salesforce limitations, this cannot be automatically determined. */ @InvocableVariable(required=true label='Flow API Name') global String flowName; /** - * @description The message to log. + * @description The message to log */ @InvocableVariable(required=true label='Log Entry Message') global String message; @@ -34,7 +34,7 @@ global inherited sharing class FlowLogEntry { global String faultMessage; /** - * @description Optionally choose to save any pending log entries. + * @description Optionally choose to save any pending log entries */ @InvocableVariable(required=false label='(Optional) Save Log') global Boolean saveLog; diff --git a/nebula-logger/main/logger-engine/classes/FlowLogger.cls b/nebula-logger/main/logger-engine/classes/FlowLogger.cls index 7607ff014..5decacc91 100644 --- a/nebula-logger/main/logger-engine/classes/FlowLogger.cls +++ b/nebula-logger/main/logger-engine/classes/FlowLogger.cls @@ -26,12 +26,12 @@ public inherited sharing class FlowLogger { // Public member variables - all other Flow classes should duplicate these public variables /** - * @description name of the flow. + * @description API name of the flow */ public String flowName; /** - * @description General message to log. + * @description General message to log */ public String message; @@ -41,33 +41,33 @@ public inherited sharing class FlowLogger { public String faultMessage; /** - * @description String containing the logging level. + * @description String name of the entry's logging level */ public String loggingLevelName; /** - * @description Optionally specify the name to use for the current transaction's scenario + * @description Optionally specify the scenario to use for the current transaction */ @InvocableVariable(required=false label='(Optional) Scenario') public String scenario; /** - * @description String of tags / topics. + * @description Comma-separated string of tags */ public String tagsString; /** - * @description List of tags / topics. + * @description List of tags / topics */ public List topics; // TODO: deprecated, remove in a future release /** - * @description Boolean used to determine if logs are saved to Salesforce. + * @description Boolean used to determine if logs are saved to Salesforce */ public Boolean saveLog = false; /** - * @description String name of the instance of Logger.SaveMethod to use saveLog == true + * @description String name of the instance of Logger.SaveMethod to use when 'Save Log' == true */ public String saveMethodName; @@ -82,8 +82,8 @@ public inherited sharing class FlowLogger { private LogEntryEvent__e logEntryEvent; /** - * @description Adds the logger to the buffer. - * @return An instance of LogEntryEventBuilder. + * @description Adds the logger to the buffer + * @return An instance of LogEntryEventBuilder */ public LogEntryEventBuilder addToLoggerBuffer() { if (this.logEntryEventBuilder != null) { diff --git a/nebula-logger/main/logger-engine/classes/FlowRecordLogEntry.cls b/nebula-logger/main/logger-engine/classes/FlowRecordLogEntry.cls index 36e1f47ae..b667745ea 100644 --- a/nebula-logger/main/logger-engine/classes/FlowRecordLogEntry.cls +++ b/nebula-logger/main/logger-engine/classes/FlowRecordLogEntry.cls @@ -15,7 +15,7 @@ @SuppressWarnings('PMD.AvoidGlobalModifier') global inherited sharing class FlowRecordLogEntry { /** - * @description The name of the Flow creating the log entry. + * @description The API name of the Flow creating the log entry. * Due to Salesforce limitations, this cannot be automatically determined */ @InvocableVariable(required=true label='Flow API Name') diff --git a/nebula-logger/main/logger-engine/lwc/logger/__tests__/data/getLoggerSettings.json b/nebula-logger/main/logger-engine/lwc/logger/__tests__/data/getLoggerSettings.json index 4ed435303..6eb6a47b3 100644 --- a/nebula-logger/main/logger-engine/lwc/logger/__tests__/data/getLoggerSettings.json +++ b/nebula-logger/main/logger-engine/lwc/logger/__tests__/data/getLoggerSettings.json @@ -1,4 +1,5 @@ { + "defaultSaveMethod": "EVENT_BUS", "isEnabled": true, "isConsoleLoggingEnabled": true, "supportedLoggingLevels": { "FINEST": 2, "FINER": 3, "FINE": 4, "DEBUG": 5, "INFO": 6, "WARN": 7, "ERROR": 8 }, diff --git a/nebula-logger/main/logger-engine/lwc/logger/__tests__/logger.test.js b/nebula-logger/main/logger-engine/lwc/logger/__tests__/logger.test.js index 1886b004a..a8c6a967e 100644 --- a/nebula-logger/main/logger-engine/lwc/logger/__tests__/logger.test.js +++ b/nebula-logger/main/logger-engine/lwc/logger/__tests__/logger.test.js @@ -3,14 +3,14 @@ import Logger from 'c/logger'; import getSettings from '@salesforce/apex/ComponentLogger.getSettings'; import { registerApexTestWireAdapter } from '@salesforce/sfdx-lwc-jest'; -const mockGetSettings = require('./data/getLoggerSettings.json'); +const MOCK_GET_SETTINGS = require('./data/getLoggerSettings.json'); const getSettingsAdapter = registerApexTestWireAdapter(getSettings); jest.mock( '@salesforce/apex/ComponentLogger.getSettings', () => { return { - default: () => mockGetSettings + default: () => MOCK_GET_SETTINGS }; }, { virtual: true } @@ -22,12 +22,49 @@ describe('Logger lwc tests', () => { document.body.removeChild(document.body.firstChild); } jest.clearAllMocks(); + // jest.restoreAllMocks(); + }); + it('returns user settings', async () => { + const logger = createElement('c-logger', { is: Logger }); + document.body.appendChild(logger); + + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); + + // await Promise.resolve(); + const userSettings = logger.getUserSettings(); + expect(userSettings.defaultSaveMethod).toEqual('EVENT_BUS'); + expect(userSettings.isEnabled).toEqual(true); + expect(userSettings.isConsoleLoggingEnabled).toEqual(true); + }); + it('sets a log scenario on all entries', async () => { + const logger = createElement('c-logger', { is: Logger }); + document.body.appendChild(logger); + + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); + logger.getUserSettings().isEnabled = true; + + return Promise.resolve().then(() => { + const scenario = 'some scenario'; + const message = 'some message'; + const firstLogEntry = logger.finest(message); + expect(firstLogEntry.scenario).toBeUndefined(); + expect(logger.getBufferSize()).toEqual(1); + + const secondLogEntry = logger.info(message); + expect(secondLogEntry.scenario).toBeUndefined(); + expect(logger.getBufferSize()).toEqual(2); + + logger.setScenario(scenario); + + expect(firstLogEntry.scenario).toEqual(scenario); + expect(secondLogEntry.scenario).toEqual(scenario); + }); }); it('logs an ERROR entry', async () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); return Promise.resolve().then(() => { const message = 'component log entry with loggingLevel ERROR'; @@ -42,7 +79,7 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); return Promise.resolve().then(() => { const message = 'component log entry with loggingLevel WARN'; @@ -58,7 +95,7 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); return Promise.resolve().then(() => { const message = 'component log entry with loggingLevel INFO'; @@ -73,7 +110,7 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); return Promise.resolve().then(() => { const message = 'component log entry with loggingLevel DEBUG'; @@ -88,7 +125,7 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); return Promise.resolve().then(() => { const message = 'component log entry with loggingLevel FINE'; @@ -103,7 +140,7 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); return Promise.resolve().then(() => { const message = 'component log entry with loggingLevel FINER'; @@ -118,7 +155,7 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); return Promise.resolve().then(() => { const message = 'component log entry with loggingLevel FINEST'; @@ -129,51 +166,11 @@ describe('Logger lwc tests', () => { expect(logEntry.message).toEqual(message); }); }); - it('sets a log scenario on all entries', async () => { - const logger = createElement('c-logger', { is: Logger }); - document.body.appendChild(logger); - - getSettingsAdapter.emit(mockGetSettings); - - return Promise.resolve().then(() => { - const scenario = 'some scenario'; - const message = 'some message'; - const firstLogEntry = logger.finest(message); - expect(firstLogEntry.scenario).toBeUndefined(); - expect(logger.getBufferSize()).toEqual(1); - - const secondLogEntry = logger.info(message); - expect(secondLogEntry.scenario).toBeUndefined(); - expect(logger.getBufferSize()).toEqual(2); - - logger.setScenario(scenario); - - expect(firstLogEntry.scenario).toEqual(scenario); - expect(secondLogEntry.scenario).toEqual(scenario); - }); - }); - it('flushes buffer', async () => { - const logger = createElement('c-logger', { is: Logger }); - document.body.appendChild(logger); - - getSettingsAdapter.emit(mockGetSettings); - - return Promise.resolve().then(() => { - const numberOfLogEntries = 3; - for (let i = 0; i < numberOfLogEntries; i++) { - logger.info('entry number: ' + i); - } - - expect(logger.getBufferSize()).toEqual(numberOfLogEntries); - logger.flushBuffer(); - expect(logger.getBufferSize()).toEqual(0); - }); - }); it('sets recordId', async () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); return Promise.resolve().then(() => { const logEntry = logger.info('example log entry'); @@ -188,7 +185,7 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); return Promise.resolve().then(() => { const logEntry = logger.info('example log entry'); @@ -204,7 +201,7 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); return Promise.resolve().then(() => { const logEntry = logger.info('example log entry'); @@ -225,7 +222,7 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); return Promise.resolve().then(() => { const logEntry = logger.info('example log entry'); @@ -240,7 +237,7 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); return Promise.resolve().then(() => { const logEntry = logger.info('example log entry'); @@ -255,30 +252,12 @@ describe('Logger lwc tests', () => { expect(logEntry.tags.length).toEqual(1); }); }); - it('saves log entries and flushes buffer', async () => { - const logger = createElement('c-logger', { is: Logger }); - document.body.appendChild(logger); - - getSettingsAdapter.emit(mockGetSettings); - - return Promise.resolve() - .then(() => { - logger.info('example INFO log entry'); - logger.debug('example DEBUG log entry'); - expect(logger.getBufferSize()).toBe(2); - - logger.saveLog(); - }) - .then(() => { - expect(logger.getBufferSize()).toBe(0); - }); - }); it('still works for ERROR when disabled', async () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - mockGetSettings.isEnabled = false; - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); + logger.getUserSettings().isEnabled = false; return Promise.resolve().then(() => { const logEntry = logger @@ -304,8 +283,8 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - mockGetSettings.isEnabled = false; - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); + logger.getUserSettings().isEnabled = false; return Promise.resolve().then(() => { const logEntry = logger @@ -332,8 +311,8 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - mockGetSettings.isEnabled = false; - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); + logger.getUserSettings().isEnabled = false; return Promise.resolve().then(() => { const logEntry = logger @@ -360,8 +339,8 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - mockGetSettings.isEnabled = false; - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); + logger.getUserSettings().isEnabled = false; return Promise.resolve().then(() => { const logEntry = logger @@ -388,8 +367,8 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - mockGetSettings.isEnabled = false; - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); + logger.getUserSettings().isEnabled = false; return Promise.resolve().then(() => { const logEntry = logger @@ -416,8 +395,8 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - mockGetSettings.isEnabled = false; - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); + logger.getUserSettings().isEnabled = false; return Promise.resolve().then(() => { const logEntry = logger @@ -444,8 +423,8 @@ describe('Logger lwc tests', () => { const logger = createElement('c-logger', { is: Logger }); document.body.appendChild(logger); - mockGetSettings.isEnabled = false; - getSettingsAdapter.emit(mockGetSettings); + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); + logger.getUserSettings().isEnabled = false; return Promise.resolve().then(() => { const logEntry = logger @@ -468,4 +447,39 @@ describe('Logger lwc tests', () => { expect(logEntry.tags).toEqual(undefined); }); }); + it('flushes buffer', async () => { + const logger = createElement('c-logger', { is: Logger }); + document.body.appendChild(logger); + + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); + + return Promise.resolve().then(() => { + const numberOfLogEntries = 3; + for (let i = 0; i < numberOfLogEntries; i++) { + logger.info('entry number: ' + i); + } + + expect(logger.getBufferSize()).toEqual(numberOfLogEntries); + logger.flushBuffer(); + expect(logger.getBufferSize()).toEqual(0); + }); + }); + it('saves log entries and flushes buffer', async () => { + const logger = createElement('c-logger', { is: Logger }); + document.body.appendChild(logger); + + getSettingsAdapter.emit({ ...MOCK_GET_SETTINGS }); + + return Promise.resolve() + .then(() => { + logger.info('example INFO log entry'); + logger.debug('example DEBUG log entry'); + expect(logger.getBufferSize()).toBe(2); + + logger.saveLog(); + }) + .then(() => { + expect(logger.getBufferSize()).toBe(0); + }); + }); }); diff --git a/nebula-logger/main/logger-engine/lwc/logger/logger.js b/nebula-logger/main/logger-engine/lwc/logger/logger.js index 05f9b651c..c7f3064ea 100644 --- a/nebula-logger/main/logger-engine/lwc/logger/logger.js +++ b/nebula-logger/main/logger-engine/lwc/logger/logger.js @@ -24,6 +24,19 @@ export default class Logger extends LightningElement { } } + @api + getUserSettings() { + return this.settings; + } + + @api + setScenario(scenario) { + this._scenario = scenario; + this.componentLogEntries.forEach(logEntry => { + logEntry.scenario = this._scenario; + }); + } + @api error(message) { return this._newEntry('ERROR', message); @@ -59,14 +72,6 @@ export default class Logger extends LightningElement { return this._newEntry('FINEST', message); } - @api - setScenario(scenario) { - this._scenario = scenario; - this.componentLogEntries.forEach(logEntry => { - logEntry.scenario = this._scenario; - }); - } - @api getBufferSize() { return this.componentLogEntries.length; @@ -78,9 +83,13 @@ export default class Logger extends LightningElement { } @api - saveLog() { + saveLog(saveMethodName) { if (this.getBufferSize() > 0) { - saveComponentLogEntries({ componentLogEntries: this.componentLogEntries }) + if (!saveMethodName && this.settings && this.settings.defaultSaveMethodName) { + saveMethodName = this.settings.defaultSaveMethodName; + } + + saveComponentLogEntries({ componentLogEntries: this.componentLogEntries, saveMethodName: saveMethodName }) .then(this.flushBuffer()) .catch(error => { if (this.settings.isConsoleLoggingEnabled === true) { diff --git a/nebula-logger/tests/logger-engine/classes/ComponentLogger_Tests.cls b/nebula-logger/tests/logger-engine/classes/ComponentLogger_Tests.cls index f58c8237a..223d7aba5 100644 --- a/nebula-logger/tests/logger-engine/classes/ComponentLogger_Tests.cls +++ b/nebula-logger/tests/logger-engine/classes/ComponentLogger_Tests.cls @@ -44,7 +44,7 @@ private class ComponentLogger_Tests { static void it_should_return_aura_exception_when_it_breaks() { Test.startTest(); try { - ComponentLogger.saveComponentLogEntries(null); + ComponentLogger.saveComponentLogEntries(null, null); System.assert(false, 'This assert shouldn\'t run since this is a negative test'); } catch (Exception apexException) { System.assertEquals(AuraHandledException.class.getName(), apexException.getTypeName()); @@ -70,7 +70,48 @@ private class ComponentLogger_Tests { componentLogEntries.add(componentLogEntry); Test.startTest(); - ComponentLogger.saveComponentLogEntries(componentLogEntries); + ComponentLogger.saveComponentLogEntries(componentLogEntries, null); + Test.stopTest(); + + List logEntries = [ + SELECT Id, LoggingLevel__c, Message__c, RecordId__c, RecordJson__c, RecordSObjectType__c, Timestamp__c + FROM LogEntry__c + ]; + System.assertEquals(1, logEntries.size()); + + LogEntry__c logEntry = logEntries.get(0); + + System.assertEquals(componentLogEntry.loggingLevel, logEntry.LoggingLevel__c); + System.assertEquals(componentLogEntry.message, logEntry.Message__c); + System.assertEquals(componentLogEntry.recordId, logEntry.RecordId__c); + System.assertEquals(JSON.serializePretty(currentUser), logEntry.RecordJson__c); + System.assertEquals(Schema.SObjectType.User.getName(), logEntry.RecordSObjectType__c); + System.assertEquals(componentLogEntry.timestamp, logEntry.Timestamp__c); + } + + @IsTest + static void it_should_save_component_log_entry_with_queueable_job() { + upsert LoggerSettings__c.getInstance(); + System.assertEquals(0, [SELECT COUNT() FROM Log__c]); + + User currentUser = new User(FirstName = UserInfo.getFirstName(), Id = UserInfo.getUserId(), ProfileId = UserInfo.getProfileId()); + + List componentLogEntries = new List(); + ComponentLogger.ComponentLogEntry componentLogEntry = new ComponentLogger.ComponentLogEntry(); + componentLogEntry.loggingLevel = LoggingLevel.INFO.name(); + componentLogEntry.message = 'hello, world'; + componentLogEntry.recordId = currentUser.Id; + componentLogEntry.record = currentUser; + componentLogEntry.timestamp = System.now().addDays(-1 / 24); + componentLogEntry.tags = new List{ 'some tag', 'one more tag' }; + componentLogEntries.add(componentLogEntry); + + Test.startTest(); + System.assertEquals(0, Limits.getQueueableJobs(), 'Test should start with 0 queueable jobs used'); + + ComponentLogger.saveComponentLogEntries(componentLogEntries, Logger.SaveMethod.QUEUEABLE.name()); + + System.assertEquals(1, Limits.getQueueableJobs(), 'Log entries should have been saved using the QUEUEABLE save method'); Test.stopTest(); List logEntries = [ @@ -113,7 +154,7 @@ private class ComponentLogger_Tests { componentLogEntries.add(componentLogEntry); Test.startTest(); - ComponentLogger.saveComponentLogEntries(componentLogEntries); + ComponentLogger.saveComponentLogEntries(componentLogEntries, null); Test.stopTest(); List logEntries = [ @@ -146,7 +187,7 @@ private class ComponentLogger_Tests { componentLogEntries.add(componentLogEntry); Test.startTest(); - ComponentLogger.saveComponentLogEntries(componentLogEntries); + ComponentLogger.saveComponentLogEntries(componentLogEntries, null); Test.stopTest(); Log__c log = [SELECT Id, Scenario__c FROM Log__c]; @@ -168,7 +209,7 @@ private class ComponentLogger_Tests { componentLogEntries.add(componentLogEntry); Test.startTest(); - ComponentLogger.saveComponentLogEntries(componentLogEntries); + ComponentLogger.saveComponentLogEntries(componentLogEntries, null); Test.stopTest(); List logEntries = [ @@ -213,7 +254,7 @@ private class ComponentLogger_Tests { componentLogEntries.add(componentLogEntry); Test.startTest(); - ComponentLogger.saveComponentLogEntries(componentLogEntries); + ComponentLogger.saveComponentLogEntries(componentLogEntries, null); Test.stopTest(); List logEntries = [ diff --git a/package.json b/package.json index 83497f3f6..8e969a242 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "devhub:details": "pwsh ./scripts/build/get-devhub-org-details.ps1", "devhub:limits": "pwsh ./scripts/build/get-devhub-org-limits.ps1", "devhub:open": "pwsh ./scripts/build/open-devhub-org.ps1", - "docs:fix": "pwsh ./scripts/build/generate-docs.ps1", + "docs:fix": "pwsh ./scripts/build/generate-docs.ps1 && git add ./docs && git commit --amend --no-edit", "docs:verify": "pwsh ./scripts/build/verify-docs-up-to-date.ps1", "experience:create": "sfdx force:community:create --name \"Logger Test Site\" --templatename \"Customer Service\" --urlpathprefix logger --description \"Logger Test Site\"", "husky:pre-commit": "lint-staged",