Skip to content

Commit

Permalink
Created new LoggerScenario__c custom object (#356)
Browse files Browse the repository at this point in the history
* Created new object LoggerScenario__c as a more robust replacement for the old text field, Log__c.Scenario__c

* Added new object & fields to permission sets

* Rearranged tab order in LoggerConsole to have logger settings, log entry event stream & logger scenarios at the top of the list

* Small scope creep to update picklist values for various 'API Version' fields

* Fixed a test failure in LoggerEngineDataSelector_Tests mentioned in #358

* Fixed a small issue with how the pipeline generates package version aliases, cleaned up sfdx-project.json & README files
  • Loading branch information
jongpie authored Sep 8, 2022
1 parent 3f20f6f commit 5f59b7a
Show file tree
Hide file tree
Showing 57 changed files with 1,116 additions and 81 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@

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

## Unlocked Package - v4.8.0
## Unlocked Package - v4.8.1

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

## Managed Package - v4.8.0

[![Install Managed Package in a Sandbox](./images/btn-install-managed-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?mgd=true&p0=04t5Y0000015lsgQAA)
[![Install Managed Package in Production](./images/btn-install-managed-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?mgd=true&p0=04t5Y0000015lsgQAA)
[![View Milestone](./images/btn-view-managed-package-milestone.png)](https://github.com/jongpie/NebulaLogger/milestone/8)
[![View Milestone](./images/btn-view-managed-package-milestone.png)](https://github.com/jongpie/NebulaLogger/milestone/8?closed=1)

---

Expand Down
22 changes: 21 additions & 1 deletion docs/apex/Log-Management/LogManagementDataSelector.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,26 @@ Log\_\_c

The matching `Log__c` record

#### `getLoggerScenariosById(List<Id> logScenarioIds)``List<LoggerScenario__c>`

Returns a `List&lt;LoggerScenario__c&gt;` of records with the specified log scenario IDs

##### Parameters

| Param | Description |
| ---------------- | ------------------------------------------------- |
| `logScenarioIds` | The list of `ID` of the `Log__c` records to query |

##### Return

**Type**

List&lt;LoggerScenario\_\_c&gt;

**Description**

The list of matching `LoggerScenario__c` records

#### `getLogsById(List<Id> logIds)``List<Log__c>`

Returns a `Log__c` record and its related `LogEntry__c` records
Expand All @@ -243,7 +263,7 @@ List&lt;Log\_\_c&gt;

The list of matching `Log__c` records

#### `getLogsByTransactionId(Set<String> transactionIds)``List<Log__c>`
#### `getLogsByTransactionId(List<String> transactionIds)``List<Log__c>`

Returns a `List&lt;Log__c&gt;` of records with the specified transaction IDs

Expand Down
27 changes: 27 additions & 0 deletions docs/apex/Log-Management/LoggerScenarioHandler.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
layout: default
---

## LoggerScenarioHandler class

Handles trigger events for the `LoggerScenario__c` object

---

### Methods

#### `getSObjectType()``Schema.SObjectType`

Returns SObject Type that the handler is responsible for processing

##### Return

**Type**

Schema.SObjectType

**Description**

The instance of `SObjectType`

---
4 changes: 4 additions & 0 deletions docs/apex/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ Builds and sends email notifications when internal exceptions occur within the l

Provides details to LWCs about Logger&apos;s `SObjects`, using `@AuraEnabled` properties

### [LoggerScenarioHandler](Log-Management/LoggerScenarioHandler)

Handles trigger events for the `LoggerScenario__c` object

### [LoggerSettingsController](Log-Management/LoggerSettingsController)

Controller class for lwc `loggerSettings`, used to manage records in `LoggerSettings__c`
Expand Down
2 changes: 1 addition & 1 deletion docs/lightning-components/Logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</dd>
<dt><a href="#setScenario">setScenario(scenario)</a></dt>
<dd><p>Sets the scenario name for the current transaction - this is stored in <code>LogEntryEvent__e.Scenario__c</code>
and <code>Log__c.Scenario__c</code>, and can be used to filter &amp; group logs</p>
and <code>Log__c.TransactionScenario__c</code>, and can be used to filter &amp; group logs</p>
</dd>
<dt><a href="#error">error(message)</a> <code>LogEntryBuilder</code></dt>
<dd><p>Creates a new log entry with logging level == <code>LoggingLevel.ERROR</code></p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<field>Description__c</field>
<value
xsi:type="xsd:string"
>When enabled (default), the first value provided when calling Logger.setScenario(String) is used to set the field Log__c.Scenario__c, and any subsequent calls to Logger.setScenario(String) are ignored in the current transaction. When disabled, the last value provided when calling Logger.setScenario(String) is instead used.</value>
>When enabled (default), the first value provided when calling Logger.setScenario(String) is used to set the field Log__c.TransactionScenario__c, and any subsequent calls to Logger.setScenario(String) are ignored in the current transaction. When disabled, the last value provided when calling Logger.setScenario(String) is instead used.</value>
</values>
<values>
<field>Value__c</field>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<CustomMetadata
xmlns="http://soap.sforce.com/2006/04/metadata"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
>
<label>LoggerScenarioHandler config</label>
<protected>false</protected>
<values>
<field>IsEnabled__c</field>
<value xsi:type="xsd:boolean">true</value>
</values>
<values>
<field>SObjectHandlerApexClass__c</field>
<value xsi:type="xsd:string">LoggerScenarioHandler</value>
</values>
<values>
<field>SObjectTypeOverride__c</field>
<value xsi:nil="true" />
</values>
<values>
<field>SObjectType__c</field>
<value xsi:type="xsd:string">LoggerScenario__c</value>
</values>
</CustomMetadata>
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
<isNavTabPersistenceDisabled>false</isNavTabPersistenceDisabled>
<label>Logger Console</label>
<navType>Console</navType>
<tabs>LoggerSettings</tabs>
<tabs>LogEntryEventStream</tabs>
<tabs>LoggerScenario__c</tabs>
<tabs>Log__c</tabs>
<tabs>LogEntry__c</tabs>
<tabs>LogEntryTag__c</tabs>
<tabs>LoggerTag__c</tabs>
<tabs>LogEntryEventStream</tabs>
<tabs>LoggerSettings</tabs>
<tabs>LogBatchPurge</tabs>
<tabs>standard-report</tabs>
<tabs>standard-Dashboard</tabs>
Expand All @@ -38,6 +39,9 @@
<fieldName>Log__c</fieldName>
<tab>LogEntry__c</tab>
</mappings>
<mappings>
<tab>LoggerScenario__c</tab>
</mappings>
<mappings>
<tab>Log__c</tab>
</mappings>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public without sharing class LogEntryEventHandler extends LoggerSObjectHandler {
private static final String DEFAULT_STORAGE_LOCATION_NAME = 'CUSTOM_OBJECTS';
private static final Database.DmlOptions DML_OPTIONS = createDmlOptions();
private static final String GUEST_USER_TYPE = 'Guest';
private static final Map<String, LoggerScenario__c> SCENARIO_UNIQUE_ID_TO_SCENARIO = new Map<String, LoggerScenario__c>();
private static final Map<String, Log__c> TRANSACTION_ID_TO_LOG = new Map<String, Log__c>();

@TestVisible
Expand Down Expand Up @@ -53,6 +54,7 @@ public without sharing class LogEntryEventHandler extends LoggerSObjectHandler {
this.logEntryEvents = this.filterLogEntryEventsToSave((List<LogEntryEvent__e>) triggerNew);

if (this.logEntryEvents.isEmpty() == false) {
this.upsertLoggerScenarios();
this.upsertLogs();
this.upsertLogEntries();
this.appendRuleBasedTags();
Expand All @@ -72,6 +74,22 @@ public without sharing class LogEntryEventHandler extends LoggerSObjectHandler {
return logEntryEventsToSave;
}

private void upsertLoggerScenarios() {
for (LogEntryEvent__e logEntryEvent : this.logEntryEvents) {
if (String.isBlank(logEntryEvent.Scenario__c) == true || SCENARIO_UNIQUE_ID_TO_SCENARIO.containsKey(logEntryEvent.Scenario__c)) {
continue;
}

LoggerScenario__c loggerScenario = new LoggerScenario__c(Name = logEntryEvent.Scenario__c, UniqueId__c = logEntryEvent.Scenario__c);
loggerScenario.setOptions(DML_OPTIONS);
SCENARIO_UNIQUE_ID_TO_SCENARIO.put(loggerScenario.UniqueId__c, loggerScenario);
}

List<Database.UpsertResult> upsertResults = LoggerDataStore.getDatabase()
.upsertRecords(SCENARIO_UNIQUE_ID_TO_SCENARIO.values(), Schema.LoggerScenario__c.UniqueId__c, System.Test.isRunningTest());
LoggerEmailSender.sendErrorEmail(Schema.LoggerScenario__c.SObjectType, upsertResults);
}

private void upsertLogs() {
// To avoid making a callout for every log for details retrieved from api.status.salesforce.com,
// try to query recent logs first to see if there is a recent log with the details already populated
Expand Down Expand Up @@ -143,6 +161,10 @@ public without sharing class LogEntryEventHandler extends LoggerSObjectHandler {
UserType__c = logEntryEvent.UserType__c
);

if (String.isNotBlank(logEntryEvent.Scenario__c) == true && SCENARIO_UNIQUE_ID_TO_SCENARIO.containsKey(logEntryEvent.Scenario__c) == true) {
log.TransactionScenario__c = SCENARIO_UNIQUE_ID_TO_SCENARIO.get(logEntryEvent.Scenario__c).Id;
}

TRANSACTION_ID_TO_LOG.put(log.TransactionId__c, log);
}

Expand Down
39 changes: 33 additions & 6 deletions nebula-logger/core/main/log-management/classes/LogHandler.cls
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public without sharing class LogHandler extends LoggerSObjectHandler {
private List<Log__c> logs;
@TestVisible
private Map<Id, Log__c> oldLogsById;
private Map<Id, LoggerScenario__c> loggerScenariosById;

/**
* @description Returns SObject Type that the handler is responsible for processing
Expand All @@ -27,6 +28,7 @@ public without sharing class LogHandler extends LoggerSObjectHandler {

protected override void executeBeforeInsert(List<SObject> triggerNew) {
this.logs = (List<Log__c>) triggerNew;
this.loggerScenariosById = queryLoggerScenarios(this.logs);

this.setClosedStatusFields();
// The log OwnerId field should support being manually changed, so only auto-set it on insert
Expand Down Expand Up @@ -107,7 +109,7 @@ public without sharing class LogHandler extends LoggerSObjectHandler {
}

private void setParentLog() {
Set<String> parentLogTransactionIds = new Set<String>();
List<String> parentLogTransactionIds = new List<String>();
for (Log__c log : this.logs) {
if (String.isNotBlank(log.ParentLogTransactionId__c) == true) {
parentLogTransactionIds.add(log.ParentLogTransactionId__c);
Expand All @@ -131,7 +133,7 @@ public without sharing class LogHandler extends LoggerSObjectHandler {
}

private void setLogRetentionDetails() {
Map<String, LogScenarioRule__mdt> scenarioToScenarioRule = queryScenarioRules(this.logs);
Map<String, LogScenarioRule__mdt> scenarioToScenarioRule = queryLogScenarioRules(this.logs, this.loggerScenariosById);
for (Log__c log : this.logs) {
// If the retention date has already been populated, leave it as-is
if (log.LogRetentionDate__c != null) {
Expand All @@ -142,7 +144,11 @@ public without sharing class LogHandler extends LoggerSObjectHandler {
LoggerSettings__c loggingUserSettings = getLoggingUserSettings(log);

// Load the configured scenario rule (if one exists)
LogScenarioRule__mdt matchingScenarioRule = scenarioToScenarioRule.get(log.Scenario__c);
LogScenarioRule__mdt matchingScenarioRule;
if (log.TransactionScenario__c != null) {
LoggerScenario__c loggerScenario = this.loggerScenariosById.get(log.TransactionScenario__c);
matchingScenarioRule = scenarioToScenarioRule.get(loggerScenario.UniqueId__c);
}

Integer daysToRetainLog = Integer.valueOf(
matchingScenarioRule != null ? matchingScenarioRule.NumberOfDaysToRetainLogs__c : loggingUserSettings.DefaultNumberOfDaysToRetainLogs__c
Expand Down Expand Up @@ -226,6 +232,27 @@ public without sharing class LogHandler extends LoggerSObjectHandler {
return logStatusNameToStatus;
}

private static Map<Id, LoggerScenario__c> queryLoggerScenarios(List<Log__c> logs) {
List<Id> loggerScenarioIds = new List<Id>();
for (Log__c log : logs) {
if (log.TransactionScenario__c != null) {
loggerScenarioIds.add(log.TransactionScenario__c);
}
}

Map<Id, LoggerScenario__c> loggerScenariosById = new Map<Id, LoggerScenario__c>();

if (loggerScenarioIds.isEmpty() == true) {
return loggerScenariosById;
}

List<LoggerScenario__c> matchingLoggerScenarios = LogManagementDataSelector.getInstance().getLoggerScenariosById(loggerScenarioIds);
if (matchingLoggerScenarios != null && matchingLoggerScenarios.isEmpty() == false) {
loggerScenariosById = new Map<Id, LoggerScenario__c>(matchingLoggerScenarios);
}
return loggerScenariosById;
}

private static Map<String, Id> queryQueues(List<String> possibleQueueNames) {
Map<String, Id> queuesByDeveloperName = new Map<String, Id>();
for (Group queue : LogManagementDataSelector.getInstance().getQueuesByDeveloperName(possibleQueueNames)) {
Expand All @@ -242,11 +269,11 @@ public without sharing class LogHandler extends LoggerSObjectHandler {
return usersByUsername;
}

private static Map<String, LogScenarioRule__mdt> queryScenarioRules(List<Log__c> logs) {
private static Map<String, LogScenarioRule__mdt> queryLogScenarioRules(List<Log__c> logs, Map<Id, LoggerScenario__c> loggerScenariosById) {
Set<String> scenarios = new Set<String>();
for (Log__c log : logs) {
if (log.Scenario__c != null) {
scenarios.add(log.Scenario__c);
if (log.TransactionScenario__c != null && loggerScenariosById.containsKey(log.TransactionScenario__c) == true) {
scenarios.add(loggerScenariosById.get(log.TransactionScenario__c).UniqueId__c);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,19 @@ public without sharing class LogManagementDataSelector {
* @param transactionIds The list of `String` transaction IDs of the `Log__c` records to query
* @return The list of matching `Log__c` records
*/
public List<Log__c> getLogsByTransactionId(Set<String> transactionIds) {
public List<Log__c> getLogsByTransactionId(List<String> transactionIds) {
return [SELECT Id, TransactionId__c FROM Log__c WHERE TransactionId__c IN :transactionIds];
}

/**
* @description Returns a `List<LoggerScenario__c>` of records with the specified log scenario IDs
* @param logScenarioIds The list of `ID` of the `Log__c` records to query
* @return The list of matching `LoggerScenario__c` records
*/
public List<LoggerScenario__c> getLoggerScenariosById(List<Id> logScenarioIds) {
return [SELECT Id, OwnerId, UniqueId__c FROM LoggerScenario__c WHERE Id IN :logScenarioIds];
}

/**
* @description Returns a `List<Profile>` of records with the specified profile IDs
* @param profileIds The list of `ID` of the `Profile` records to query
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//------------------------------------------------------------------------------------------------//
// 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 Log Management
* @description Handles trigger events for the `LoggerScenario__c` object
*/
public without sharing class LoggerScenarioHandler extends LoggerSObjectHandler {
/**
* @description Returns SObject Type that the handler is responsible for processing
* @return The instance of `SObjectType`
*/
public override Schema.SObjectType getSObjectType() {
return Schema.LoggerScenario__c.SObjectType;
}
}
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
Expand Up @@ -246,8 +246,8 @@
<name>uiBehavior</name>
<value>readonly</value>
</fieldInstanceProperties>
<fieldItem>Record.Scenario__c</fieldItem>
<identifier>RecordScenario__cField</identifier>
<fieldItem>Record.TransactionScenario__c</fieldItem>
<identifier>RecordTransactionScenario__cField</identifier>
</fieldInstance>
</itemInstances>
<itemInstances>
Expand Down
Loading

0 comments on commit 5f59b7a

Please sign in to comment.