diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..019e4ba35 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [jongpie] diff --git a/README.md b/README.md index 7174d9c04..91a0dcf51 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ The most robust logger for Salesforce. Works with Apex, Lightning Components, Fl ## Features -1. Easily add log entries via Apex, Lightning Components (lwc & aura), Flow & Process Builder to generate 1 consolidated, unified log +1. Easily add log entries via Apex, Lightning Components (lightning web components (LWCs) & aura components), Flow & Process Builder to generate 1 consolidated, unified log 2. Manage & report on logging data using the `Log__c` and `LogEntry__c` objects 3. Leverage `LogEntryEvent__e` platform events for real-time monitoring & integrations 4. Enable logging and set the logging level for different users & profiles using `LoggerSettings__c` custom hierarchy setting @@ -86,11 +86,6 @@ Nebula Logger is available as both an unlocked package and a managed package. Th System.debug() is automatically called - the output can be configured with LoggerSettings__c.SystemLogMessageFormat__c to use any field on LogEntryEvent__e Requires adding your own calls for System.debug() due to Salesforce limitations with managed packages - - Apex Stack Traces - Automatically stored in LogEntry__c.StackTrace__c when calling methods like Logger.debug('my message'); - Requires calling parseStackTrace() due to Salesforce limitations with managed packages. For example:
Logger.debug('my message').parseStackTrace(new DmlException().getStackTrace()); - Logger Plugin Framework Leverage Apex or Flow to build your own "plugins" for Logger - easily add your own automation to the any of the included objects: LogEntryEvent__e, Log__c, LogEntry__c, LogEntryTag__c and LoggerTag__c. The logger system will then automatically run your plugins for each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on). @@ -142,20 +137,21 @@ This results in 1 `Log__c` record with several related `LogEntry__c` records. ### Logger for Lightning Components: Quick Start -For lightning component developers, the `logger` lwc provides very similar functionality that is offered in Apex. Simply embed the `logger` lwc in your component, and call the desired logging methods within your code. +For lightning component developers, the `logger` LWC provides very similar functionality that is offered in Apex. Simply incorporate the `logger` LWC into your component, and call the desired logging methods within your code. ```javascript -// For lwc, retrieve logger from your component's template -const logger = this.template.querySelector('c-logger'); +// For LWC, import logger's createLogger() function into your component +import { createLogger } from 'c/logger'; -logger.error('Hello, world!').addTag('some important tag'); -logger.warn('Hello, world!'); -logger.info('Hello, world!'); -logger.debug('Hello, world!'); -logger.fine('Hello, world!'); -logger.finer('Hello, world!'); -logger.finest('Hello, world!'); -logger.saveLog(); +export default class LoggerLWCDemo extends LightningElement { + logger; + + async connectedCallback() { + this.logger = await createLogger(); + this.logger.info('Hello, world'); + this.logger.saveLog(); + } +} ``` ```javascript @@ -388,7 +384,7 @@ For more details, check out the `LogMessage` class [documentation](https://jongp ## Features for Lightning Component Developers -For lightning component developers, the included `logger` lwc can be used in other lwc & aura components for frontend logging. Similar to `Logger` and `LogEntryBuilder` Apex classes, the lwc has both `logger` and `logEntryBuilder` classes. This provides a fluent API for javascript developers so they can chain the method calls. +For lightning component developers, the included `logger` LWC can be used in other LWCs & aura components for frontend logging. Similar to `Logger` and `LogEntryBuilder` Apex classes, the LWC has both `logger` and `logEntryBuilder` classes. This provides a fluent API for JavaScript developers so they can chain the method calls. Once you've incorporated `logger` into your lightning components, you can see your `LogEntry__c` records using the included list view "All Component Log Entries'. @@ -400,34 +396,48 @@ Each `LogEntry__c` record automatically stores the component's type ('Aura' or ' #### Example LWC Usage -To use the logger component, it has to be added to your lwc's markup: +For lightning component developers, the `logger` LWC provides very similar functionality that is offered in Apex. Simply import the `logger` LWC in your component, and call the desired logging methods within your code. -```html - -``` +export default class LoggerLWCDemo extends LightningElement { + logger; -Once you've added logger to your markup, you can call it in your lwc's controller: + async connectedCallback() { + // Call createLogger() once per component + this.logger = await createLogger(); -```javascript -import { LightningElement } from 'lwc'; + this.logger.setScenario('some scenario'); + this.logger.finer('initialized demo LWC'); + } -export default class LoggerDemo extends LightningElement { logSomeStuff() { - const logger = this.template.querySelector('c-logger'); - - logger.error('Hello, world!').addTag('some important tag'); - logger.warn('Hello, world!'); - logger.info('Hello, world!'); - logger.debug('Hello, world!'); - logger.fine('Hello, world!'); - logger.finer('Hello, world!'); - logger.finest('Hello, world!'); + this.logger.error('Add log entry using Nebula Logger with logging level == ERROR').addTag('some important tag'); + this.logger.warn('Add log entry using Nebula Logger with logging level == WARN'); + this.logger.info('Add log entry using Nebula Logger with logging level == INFO'); + this.logger.debug('Add log entry using Nebula Logger with logging level == DEBUG'); + this.logger.fine('Add log entry using Nebula Logger with logging level == FINE'); + this.logger.finer('Add log entry using Nebula Logger with logging level == FINER'); + this.logger.finest('Add log entry using Nebula Logger with logging level == FINEST'); + + this.logger.saveLog(); + } - logger.saveLog(); + doSomething(event) { + this.logger.finest('Starting doSomething() with event: ' + JSON.stringify(event)); + try { + this.logger.debug('TODO - finishing implementation of doSomething()').addTag('another tag'); + // TODO add the function's implementation below + } catch (thrownError) { + this.logger + .error('An unexpected error log entry using Nebula Logger with logging level == ERROR') + .setError(thrownError) + .addTag('some important tag'); + } finally { + this.logger.saveLog(); + } } } ``` @@ -584,6 +594,53 @@ Once you've implementing log entry tagging within Apex or Flow, you can choose h --- +## Adding Custom Fields to Nebula Logger's Data Model + +As of `v4.13.14`, Nebula Logger supports defining, setting, and mapping custom fields within Nebula Logger's data model. This is helpful in orgs that want to extend Nebula Logger's included data model by creating their own org/project-specific fields. + +This feature requires that you populate your custom fields yourself, and is only available in Apex currently. The plan is to add in a future release the ability to also set custom fields via JavaScript & Flow. + +### Adding Custom Fields to the Platform Event `LogEntryEvent__e` + +The first step is to add a field to the platform event `LogEntryEvent__e` + +- Create a custom field on `LogEntryEvent__e`. Any data type supported by platform events can be used. + + - In this example, a custom text field called `SomeCustomField__c` has been added: + + ![Custom Field on LogEntryEvent__e](./images/custom-field-log-entry-event.png) + +- Populate your field(s) in Apex by calling the instance method overloads `LogEntryEventBuilder.setField(Schema.SObjectField field, Object fieldValue)` or `LogEntryEventBuilder.setField(Map fieldToValue)` + + ```apex + Logger.info('hello, world') + // Set a single field + .setField(LogEntryEvent__e.SomeCustomTextField__c, 'some text value') + // Set multiple fields + .setFields(new Map{ + LogEntryEvent__e.AnotherCustomTextField__c => 'another text value', + LogEntryEvent__e.SomeCustomDatetimeField__c => System.now() + }); + ``` + +### Adding Custom Fields to the Custom Objects `Log__c`, `LogEntry__c`, and `LoggerScenario__c` + +If you want to store the data in one of Nebula Logger's custom objects, you can follow the above steps, and also... + +- Create an equivalent custom field on one of Nebula Logger's custom objects - right now, only `Log__c`, `LogEntry__c`, and `LoggerScenario__c` are supported. + + - In this example, a custom text field _also_ called `SomeCustomField__c` has been added to `Log__c` object - this will be used to store the value of the field `LogEntryEvent__e.SomeCustomField__c`: + + ![Custom Field on LogEntryEvent__e](./images/custom-field-log.png) + +- Create a record in the new CMDT `LoggerFieldMapping__mdt` to map the `LogEntryEvent__e` custom field to the custom object's custom field, shown below. Nebula Logger will automatically populate the custom object's target field with the value of the source `LogEntryEvent__e` field. + + - In this example, a custom text field called `SomeCustomField__c` has been added to both `LogEntryEvent__e` and `Log__c`. + + ![Custom Field on LogEntryEvent__e](./images/custom-field-mapping.png) + +--- + ## Log Management ### Logger Console App diff --git a/docs/apex/Log-Management/LoggerFieldMapper.md b/docs/apex/Log-Management/LoggerFieldMapper.md deleted file mode 100644 index 2c5672f7b..000000000 --- a/docs/apex/Log-Management/LoggerFieldMapper.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -layout: default ---- - -## LoggerFieldMapper class - -Maps fields values from custom fields on `LogEntryEvent__e` to equivalent fields on `Log__c`, `LogEntry__c`, and `LoggerScenario__c` - ---- - -### Methods - -#### `mapFieldValues(SObject sourceRecord, SObject targetRecord)` → `void` - -Copies field values from the `sourceRecord` to the `targetRecord`, based on rules configured in `LoggerFieldMapping_t` - -##### Parameters - -| Param | Description | -| -------------- | ------------------------------------------------------------------------------- | -| `sourceRecord` | The source `SObject` record containing the data to copy | -| `targetRecord` | The target `SObject` record that should have fields & field values appended | - ---- diff --git a/images/custom-field-log-entry-event.png b/images/custom-field-log-entry-event.png new file mode 100644 index 000000000..40e0ad2fe Binary files /dev/null and b/images/custom-field-log-entry-event.png differ diff --git a/images/custom-field-log.png b/images/custom-field-log.png new file mode 100644 index 000000000..724cde990 Binary files /dev/null and b/images/custom-field-log.png differ diff --git a/images/custom-field-mapping.png b/images/custom-field-mapping.png new file mode 100644 index 000000000..db2e64045 Binary files /dev/null and b/images/custom-field-mapping.png differ diff --git a/sfdx-project.json b/sfdx-project.json index 7c6c66848..8fe340abf 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -11,7 +11,7 @@ "scopeProfiles": true, "versionNumber": "4.13.14.NEXT", "versionName": "Custom Field Mappings Support", - "versionDescription": "Added the ability to set & map custom fields, using new instance methods LogEntryEventBuilder.setField() & setFields(), and a new CMDT LoggerFieldMapping__mdt", + "versionDescription": "Added the ability to set & map custom fields, using new instance method overloads LogEntryEventBuilder.setField(), and a new CMDT LoggerFieldMapping__mdt", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases", "unpackagedMetadata": { "path": "./nebula-logger/extra-tests"