Skip to content

Commit

Permalink
More controls for scenario-based logging (#357)
Browse files Browse the repository at this point in the history
* Closed #347 & #356 by deprecating LogScenarioRule__mdt object & replacing it with a new object LoggerScenarioRule__mdt that provides optional overrides for all fields on LoggerSettings__c

* Added new Apex class LogScenarioRule to manage accessing LoggerScenarioRule__mdt CMDT records

* Incorporated the stellar idea from @jamessimone to tie LogEntry__c records to the new LoggerScenario__c object via a new lookup field LogEntry__c.EntryScenario__c

* Added new method Logger.endScenario(String) so that Apex developers can explicitly end a scenario, which then automatically rolls back to the previous scenario (and re-applies the previous scenario rule, if one exists) - another fantastic suggestion from @jamessimone

* Renamed LoggerSettings__c.DefaultLogScenario__c to LoggerSettings__c.DefaultScenario__c for consistency

* Fixed #360 by changing Logger.logDatabaseErrors() overloads to always return a non-null instance of LogEntryEventBuilder

* Updated some formatting in SlackLoggerPlugin to better format stack traces & create new plugin package version v1.5.0

* Fixed #363 by correcting some references in the migration script ./scripts/data/migrate-log-scenario-field-to-logger-scenario-object.apex

* Added content in README that links to the wiki's architecture overview

* Removed build numbers for package versions in sfdx-project.json, upgraded some packages in package.json to resolve some GitHub security alerts
  • Loading branch information
jongpie authored Sep 22, 2022
1 parent 5f59b7a commit bade266
Show file tree
Hide file tree
Showing 85 changed files with 1,854 additions and 444 deletions.
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
[![Build](https://github.com/jongpie/NebulaLogger/actions/workflows/build.yml/badge.svg)](https://github.com/jongpie/NebulaLogger/actions/workflows/build.yml)
[![codecov](https://codecov.io/gh/jongpie/NebulaLogger/branch/main/graph/badge.svg?token=1DJPDRM3N4)](https://codecov.io/gh/jongpie/NebulaLogger)

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

## Unlocked Package - v4.8.1
## Unlocked Package - v4.8.2

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

## Managed Package - v4.8.0
Expand All @@ -34,7 +34,14 @@ Designed for Salesforce admins, developers & architects. A robust logger for Ape

Learn more about the design and history of the project on [Joys Of Apex blog post](https://www.joysofapex.com/advanced-logging-using-nebula-logger/)

---
## Architecture Overview

Nebula Logger is built natively on Salesforce, using Apex, lightning components and various types of objects. There are no required external dependencies. To learn more about the architecture, check out the
[architecture overview in the wiki](https://raw.githubusercontent.com/wiki/jongpie/NebulaLogger/images/nebula-logger-architecture-overview.png).

<a href="https://github.com/jongpie/NebulaLogger/wiki/Architecture" target="_blank">
<img src="https://raw.githubusercontent.com/wiki/jongpie/NebulaLogger/images/nebula-logger-architecture-overview.png" width="300">
</a>

## Installing

Expand Down
47 changes: 47 additions & 0 deletions docs/apex/Configuration/LoggerScenarioRule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
layout: default
---

## LoggerScenarioRule class

Provides a centralized way to load scenario rules that override behavior within Nebula Logger

---

### Methods

#### `getAll()``Map<String, LoggerScenarioRule_t>`

Returns a map containing any enabled `LoggerScenarioRule_t` records with valid `StartTime__c` and `EndTime__c` values (null is considered valid)

##### Return

**Type**

Map&lt;String, LoggerScenarioRule_t&gt;

**Description**

The current transaction&apos;s cached `Map&lt;String, LoggerScenarioRule_t&gt;`, where the key

#### `getInstance(String scenario)``LoggerScenarioRule_t`

Returns the `LoggerScenarioRule_t` with the matching scenario, based on the field `LoggerScenarioRule_t.Scenario__c`

##### Parameters

| Param | Description |
| ---------- | ------------------------ |
| `scenario` | The name of the scenario |

##### Return

**Type**

LoggerScenarioRule_t

**Description**

The matching `LoggerScenarioRule_t` if one is found, or `null`

---
4 changes: 0 additions & 4 deletions docs/apex/Log-Management/RelatedLogEntriesController.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,6 @@ Contains the plural label of the log entry sObject, fetched using a describe cal

contains the log entry results from the query.

###### `tabIcon``String`

contains the tab icon of the log entry, fetched using describe a call on the log entry sObject.

###### `totalLogEntriesCount``Integer`

Contains the number of records returned via the log entries query.
Expand Down
12 changes: 11 additions & 1 deletion docs/apex/Logger-Engine/Logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,16 @@ LogEntryEventBuilder

The new entry&apos;s instance of `LogEntryEventBuilder`, useful for chaining methods

#### `endScenario(String scenario)``void`

End the specified scenario, if it&apos;s the currently active scenario, and rolls back to the previous scenario (if a previous scenario was specified in the current transaction)

##### Parameters

| Param | Description |
| ---------- | ------------------------------- |
| `scenario` | The name of the scenario to end |

#### `error(LogMessage logMessage, Database.DeleteResult deleteResult)``LogEntryEventBuilder`

Creates a new log entry with logging level == `LoggingLevel.ERROR`
Expand Down Expand Up @@ -4470,7 +4480,7 @@ Sets the default save method used when calling saveLog() - any subsequent calls

#### `setScenario(String scenario)``void`

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 &amp; group logs
Sets the current scenario, which can be used to identify modules or groupings of for the current transaction

##### Parameters

Expand Down
10 changes: 5 additions & 5 deletions docs/apex/Test-Utilities/LoggerTestConfigurator.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,15 @@ Loads the mock `LoggerSObjectHandler_t` during test execution
| ------ | ----------------------------------------------------- |
| `mock` | The mock instance of `LoggerSObjectHandler_t` to load |

#### `setMock(LogScenarioRule_t mock)``void`
#### `setMock(LoggerScenarioRule_t mock)``void`

Loads the mock `LogScenarioRule_t` during test execution
Loads the mock `LoggerScenarioRule_t` during test execution

##### Parameters

| Param | Description |
| ------ | ------------------------------------------------ |
| `mock` | The mock instance of `LogScenarioRule_t` to load |
| Param | Description |
| ------ | --------------------------------------------------- |
| `mock` | The mock instance of `LoggerScenarioRule_t` to load |

#### `setMock(LogStatus_t mock)``void`

Expand Down
4 changes: 4 additions & 0 deletions docs/apex/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,7 @@ Provides a centralized way to load parameters for SObject handlers &amp; plugins
### [LoggerPlugin](Configuration/LoggerPlugin)

The core of the plugin framework, used to create custom Apex &amp; Flow plugins for `LoggerSObjectHandler` and `LogBatchPurger` based on configurations stored in the custom metadata type `LoggerPlugin_t`

### [LoggerScenarioRule](Configuration/LoggerScenarioRule)

Provides a centralized way to load scenario rules that override behavior within Nebula Logger
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------------------------//
// This file is part of the Nebula Logger project, released under the MIT License. //
// See LICENSE file or go to https://github.com/jongpie/NebulaLogger for full license details. //
//------------------------------------------------------------------------------------------------//

/**
* @group Configuration
* @description Provides a centralized way to load scenario rules that override behavior
* within Nebula Logger
*/
public without sharing class LoggerScenarioRule {
private static final Map<String, LoggerScenarioRule__mdt> SCENARIO_NAME_TO_SCENARIO_RULE = loadLogScenarioRules();

/**
* @description Returns a map containing any enabled `LoggerScenarioRule__mdt` records with
* valid `StartTime__c` and `EndTime__c` values (null is considered valid)
* @return The current transaction's cached `Map<String, LoggerScenarioRule__mdt>`, where the key
* is the log scenario (configured in `LoggerScenarioRule__mdt.Scenario__c`)
*/
public static Map<String, LoggerScenarioRule__mdt> getAll() {
return SCENARIO_NAME_TO_SCENARIO_RULE;
}

/**
* @description Returns the `LoggerScenarioRule__mdt` with the matching scenario,
* based on the field `LoggerScenarioRule__mdt.Scenario__c`
* @param scenario The name of the scenario
* @return The matching `LoggerScenarioRule__mdt` if one is found, or `null`
*/
public static LoggerScenarioRule__mdt getInstance(String scenario) {
return SCENARIO_NAME_TO_SCENARIO_RULE.get(scenario);
}

@TestVisible
private static void setMock(LoggerScenarioRule__mdt scenarioRule) {
if (String.isBlank(scenarioRule.Scenario__c) == true) {
throw new IllegalArgumentException('Scenario__c is required on `LoggerScenarioRule__mdt: \n' + JSON.serializePretty(scenarioRule));
}

if (isValid(scenarioRule) == true) {
SCENARIO_NAME_TO_SCENARIO_RULE.put(scenarioRule.Scenario__c, scenarioRule);
}
}

private static Map<String, LoggerScenarioRule__mdt> loadLogScenarioRules() {
Map<String, LoggerScenarioRule__mdt> scenarioRules = new Map<String, LoggerScenarioRule__mdt>();
for (LoggerScenarioRule__mdt scenarioRule : LoggerScenarioRule__mdt.getAll().values()) {
if (isValid(scenarioRule) == true) {
scenarioRules.put(scenarioRule.Scenario__c, scenarioRule);
}
}

if (System.Test.isRunningTest() == true) {
scenarioRules.clear();
}

return scenarioRules;
}

private static Boolean isValid(LoggerScenarioRule__mdt scenarioRule) {
Boolean isValid = false;
if (scenarioRule.IsEnabled__c == true) {
Datetime currentTime = System.now();
Boolean startTimeIsValid = scenarioRule.StartTime__c == null || scenarioRule.StartTime__c <= currentTime;
Boolean endTimeIsValid = scenarioRule.EndTime__c == null || scenarioRule.EndTime__c >= currentTime;

isValid = startTimeIsValid == true && endTimeIsValid == true;
}
return isValid;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>55.0</apiVersion>
<status>Active</status>
</ApexClass>
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Layout xmlns="http://soap.sforce.com/2006/04/metadata">
<layoutSections>
<customLabel>false</customLabel>
<detailHeading>true</detailHeading>
<editHeading>true</editHeading>
<label>Information</label>
<layoutColumns>
<layoutItems>
<behavior>Required</behavior>
<field>MasterLabel</field>
</layoutItems>
<layoutItems>
<behavior>Required</behavior>
<field>DeveloperName</field>
</layoutItems>
<layoutItems>
<behavior>Required</behavior>
<field>Scenario__c</field>
</layoutItems>
</layoutColumns>
<layoutColumns>
<layoutItems>
<behavior>Edit</behavior>
<field>IsEnabled__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>StartTime__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>EndTime__c</field>
</layoutItems>
</layoutColumns>
<style>TwoColumnsTopToBottom</style>
</layoutSections>
<layoutSections>
<customLabel>true</customLabel>
<detailHeading>true</detailHeading>
<editHeading>true</editHeading>
<label>Logger Engine Overrides</label>
<layoutColumns>
<layoutItems>
<behavior>Edit</behavior>
<field>IsLoggerEnabled__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>UserLoggingLevel__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>IsSavingEnabled__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>SaveMethod__c</field>
</layoutItems>
</layoutColumns>
<layoutColumns>
<layoutItems>
<behavior>Edit</behavior>
<field>IsAnonymousModeEnabled__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>IsApexSystemDebugLoggingEnabled__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>IsJavaScriptConsoleLoggingEnabled__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>IsDataMaskingEnabled__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>IsRecordFieldStrippingEnabled__c</field>
</layoutItems>
</layoutColumns>
<style>TwoColumnsTopToBottom</style>
</layoutSections>
<layoutSections>
<customLabel>true</customLabel>
<detailHeading>true</detailHeading>
<editHeading>true</editHeading>
<label>Log Management Overrides</label>
<layoutColumns>
<layoutItems>
<behavior>Edit</behavior>
<field>IsPlatformEventStorageLocationEnabled__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>PlatformEventStorageLocation__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>IsLogAssignmentEnabled__c</field>
</layoutItems>
</layoutColumns>
<layoutColumns>
<layoutItems>
<behavior>Edit</behavior>
<field>IsLogRetentionOverrideEnabled__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>NumberOfDaysToRetainLogs__c</field>
</layoutItems>
</layoutColumns>
<style>TwoColumnsTopToBottom</style>
</layoutSections>
<layoutSections>
<customLabel>false</customLabel>
<detailHeading>true</detailHeading>
<editHeading>true</editHeading>
<label>System Information</label>
<layoutColumns>
<layoutItems>
<behavior>Required</behavior>
<field>NamespacePrefix</field>
</layoutItems>
<layoutItems>
<behavior>Readonly</behavior>
<field>CreatedById</field>
</layoutItems>
</layoutColumns>
<layoutColumns>
<layoutItems>
<behavior>Edit</behavior>
<field>IsProtected</field>
</layoutItems>
<layoutItems>
<behavior>Readonly</behavior>
<field>LastModifiedById</field>
</layoutItems>
</layoutColumns>
<style>TwoColumnsTopToBottom</style>
</layoutSections>
<layoutSections>
<customLabel>true</customLabel>
<detailHeading>true</detailHeading>
<editHeading>false</editHeading>
<label>Custom Links</label>
<layoutColumns />
<layoutColumns />
<layoutColumns />
<style>CustomLinks</style>
</layoutSections>
<showEmailCheckbox>false</showEmailCheckbox>
<showHighlightsPanel>false</showHighlightsPanel>
<showInteractionLogPanel>false</showInteractionLogPanel>
<showRunAssignmentRulesCheckbox>false</showRunAssignmentRulesCheckbox>
<showSubmitAndAttachButton>false</showSubmitAndAttachButton>
<summaryLayout>
<masterLabel>00h63000007CAvC</masterLabel>
<sizeX>4</sizeX>
<sizeY>0</sizeY>
<summaryLayoutStyle>Default</summaryLayoutStyle>
</summaryLayout>
</Layout>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
<label>Log Scenario Rule</label>
<pluralLabel>Log Scenario Rules</pluralLabel>
<label>Logger Scenario Rule</label>
<pluralLabel>Logger Scenario Rules</pluralLabel>
<visibility>Public</visibility>
</CustomObject>
Loading

0 comments on commit bade266

Please sign in to comment.