Skip to content

Commit

Permalink
[skip ci][WIP] Added JS support for setting fields once per component…
Browse files Browse the repository at this point in the history
…, using logger.setField()
  • Loading branch information
jongpie committed Sep 28, 2024
1 parent 8356672 commit 8bdcb3b
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 17 deletions.
58 changes: 42 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -645,29 +645,55 @@ The first step is to add a field to the platform event `LogEntryEvent__e`

![Custom Field on LogEntryEvent__e](./images/custom-field-log-entry-event.png)

- In Apex, populate your field(s) by calling the instance method overloads `LogEntryEventBuilder.setField(Schema.SObjectField field, Object fieldValue)` or `LogEntryEventBuilder.setField(Map<Schema.SObjectField, Object> fieldToValue)`

```apex Logger.info('hello, world')
// Set a single field
.setField(LogEntryEvent__e.SomeCustomTextField__c, 'some text value')
// Set multiple fields
.setField(new Map<Schema.SObjectField, Object>{
LogEntryEvent__e.AnotherCustomTextField__c => 'another text value',
LogEntryEvent__e.SomeCustomDatetimeField__c => System.now()
});
- In Apex, you have 2 ways to populate your custom fields

1. Set the field once per transaction - every `LogEntryEvent__e` logged in the transaction will then automatically have the specified field populated with the same value.
- This is typically used for fields that are mapped to an equivalent `Log__c` or `LoggerScenario__c` field.

- How: call the static method overloads `Logger.setField(Schema.SObjectField field, Object fieldValue)` or `Logger.setField(Map<Schema.SObjectField, Object> fieldToValue)`

2. Set the field on a specific `LogEntryEvent__e` record - other records will not have the field automatically set.
- This is typically used for fields that are mapped to an equivalent `LogEntry__c` field.
- How: call the instance method overloads `LogEntryEventBuilder.setField(Schema.SObjectField field, Object fieldValue)` or `LogEntryEventBuilder.setField(Map<Schema.SObjectField, Object> fieldToValue)`

```apex
// Set My_Field__c on every log entry event created in this transaction with the same value
Logger.setField(LogEntryEvent__e.My_Field__c, 'some value that applies to the whole Apex transaction');
// Set fields on specific entries
Logger.warn('hello, world - "a value" set for Some_Other_Field__c').setField(LogEntryEvent__e.Some_Other_Field__c, 'a value')
Logger.warn('hello, world - "different value" set for Some_Other_Field__c').setField(LogEntryEvent__e.Some_Other_Field__c, 'different value')
Logger.info('hello, world - no value set for Some_Other_Field__c');
Logger.saveLog();
```

- In JavaScript, populate your field(s) by calling the instance function `LogEntryEventBuilder.setField(Object fieldToValue)`
- In JavaScript, you have 2 ways to populate your custom fields. These are very similar to the 2 ways available in Apex (above).

1. Set the field once per component - every `LogEntryEvent__e` logged in your component will then automatically have the specified field populated with the same value.
- This is typically used for fields that are mapped to an equivalent `Log__c` or `LoggerScenario__c` field.

- How: call the `logger` LWC function `logger.setField(Object fieldToValue)`

2. Set the field on a specific `LogEntryEvent__e` record - other records will not have the field automatically set.
- This is typically used for fields that are mapped to an equivalent `LogEntry__c` field.
- How: call the instance function `LogEntryEventBuilder.setField(Object fieldToValue)`

```javascript
import { createLogger } from 'c/logger';
import { getLogger } from 'c/logger';

export default class LoggerLWCImportDemo extends LightningElement {
logger;
logger = getLogger();

connectedCallback() {
// Set My_Field__c on every log entry event created in this component with the same value
this.logger.setField(LogEntryEvent__e.My_Field__c, 'some value that applies to the whole Apex transaction');

// Set fields on specific entries
this.logger.warn('hello, world - "a value" set for Some_Other_Field__c').setField({ Some_Other_Field__c: 'a value' });
this.logger.warn('hello, world - "different value" set for Some_Other_Field__c').setField({ Some_Other_Field__c: 'different value' });
this.logger.info('hello, world - no value set for Some_Other_Field__c');

async connectedCallback() {
this.logger = await createLogger();
this.logger.info('Hello, world').setField({ SomeCustomTextField__c: 'some text value', SomeCustomNumbertimeField__c: 123 });
this.logger.saveLog();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,31 @@ describe('logger lwc import tests', () => {
expect(logEntry.browser.windowResolution).toEqual(window.innerWidth + ' x ' + window.innerHeight);
});

it('sets multiple custom fields when using recommended import approach', async () => {
it('sets multiple custom component fields on all entries when using recommended import approach', async () => {
getSettings.mockResolvedValue({ ...MOCK_GET_SETTINGS });
const logger = await createLogger();
await logger.getUserSettings();
const logEntryBuilder = logger.info('example log entry');
const logEntry = logEntryBuilder.getComponentLogEntry();
const firstFakeFieldName = 'SomeField__c';
const firstFieldMockValue = 'something';
const secondFakeFieldName = 'AnotherField__c';
const secondFieldMockValue = 'another value';
expect(logEntry.fieldToValue[firstFakeFieldName]).toBeFalsy();
expect(logEntry.fieldToValue[secondFakeFieldName]).toBeFalsy();

logger.setField({
[firstFakeFieldName]: firstFieldMockValue,
[secondFakeFieldName]: secondFieldMockValue
});
logger.saveLog();
await Promise.resolve('save logs');

expect(logEntry.fieldToValue[firstFakeFieldName]).toEqual(firstFieldMockValue);
expect(logEntry.fieldToValue[secondFakeFieldName]).toEqual(secondFieldMockValue);
});

it('sets multiple custom entry fields on a single entry when using recommended import approach', async () => {
getSettings.mockResolvedValue({ ...MOCK_GET_SETTINGS });
const logger = await createLogger();
await logger.getUserSettings();
Expand Down
9 changes: 9 additions & 0 deletions nebula-logger/core/main/logger-engine/lwc/logger/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ export default class Logger extends LightningElement {
return this.#loggerService.getUserSettings();
}

/**
* @description Sets multiple field values on the builder's `LogEntryEvent__e` record
* @param {Object} fieldToValue An object containing the custom field name as a key, with the corresponding value to store.
* Example: `{"SomeField__c": "some value", "AnotherField__c": "another value"}`
*/
setField(fieldToValue) {
this.#loggerService.setField(fieldToValue);
}

/**
* @description Sets the scenario name for the current transaction - this is stored in `LogEntryEvent__e.Scenario__c`
* and `Log__c.Scenario__c`, and can be used to filter & group logs
Expand Down
15 changes: 15 additions & 0 deletions nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,23 @@ const LoggerService = class {
#componentLogEntries = [];
#settings;
#scenario;
#componentFieldToValue = {};

getUserSettings() {
return this.#settings;
}

/**
* @description Sets multiple field values on every generated `LogEntryEvent__e` record
* @param {Object} fieldToValue An object containing the custom field name as a key, with the corresponding value to store.
* Example: `{"SomeField__c": "some value", "AnotherField__c": "another value"}`
*/
setField(fieldToValue) {
if (!!fieldToValue && typeof fieldToValue === 'object' && !Array.isArray(fieldToValue)) {
Object.assign(this.#componentFieldToValue, fieldToValue);
}
}

setScenario(scenario) {
this.#scenario = scenario;
this.#componentLogEntries.forEach(logEntry => {
Expand Down Expand Up @@ -76,6 +88,9 @@ const LoggerService = class {

try {
const logEntriesToSave = [...this.#componentLogEntries];
logEntriesToSave.forEach(logEntry => {
Object.assign(logEntry.fieldToValue, this.#componentFieldToValue);
});
// this is an attempt to only flush the buffer for log entries that we are sending to Apex
// rather than any that could be added if the saveLog call isn't awaited properly
this.flushBuffer();
Expand Down

0 comments on commit 8bdcb3b

Please sign in to comment.