From d8f2bac739267f58c52ad4102bf1d31db123919b Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Thu, 3 Jun 2021 23:28:06 -0700 Subject: [PATCH 01/82] Added basic functionality for handler post-processors in LogHandler and LogEntryHandler --- README.md | 26 +++++++ .../classes/LogEntryHandler.cls | 7 ++ .../log-management/classes/LogHandler.cls | 3 + .../log-management/classes/LoggerHandler.cls | 45 +++++++++++ .../classes/LoggerHandler.cls-meta.xml | 5 ++ ...ndler Configuration Layout.layout-meta.xml | 78 +++++++++++++++++++ ...rHandlerConfiguration__mdt.object-meta.xml | 7 ++ .../fields/ApexClassName__c.field-meta.xml | 13 ++++ .../fields/FlowName__c.field-meta.xml | 11 +++ .../fields/LoggerSObject__c.field-meta.xml | 15 ++++ .../listViews/All.listView-meta.xml | 11 +++ 11 files changed, 221 insertions(+) create mode 100644 nebula-logger/main/log-management/classes/LoggerHandler.cls create mode 100644 nebula-logger/main/log-management/classes/LoggerHandler.cls-meta.xml create mode 100644 nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/LoggerHandlerConfiguration__mdt.object-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/ApexClassName__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/FlowName__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml diff --git a/README.md b/README.md index 736178f7d..25d94efa3 100644 --- a/README.md +++ b/README.md @@ -338,6 +338,32 @@ The class `LogMessage` provides the ability to generate string messages on deman For more details, check out the `LogMessage` class [documentation](https://jongpie.github.io/NebulaLogger/logger-engine/LogMessage). +### Adding Custom Post-Processors for Log__c and LogEntry__c + +If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you leverage Apex or Flow. + +- Flow post-processors: your Flow should be built with 2 input parameters + 1. `records` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) + 1. `oldRecords` - The list of logger records as they exist in the datatabase - this is only populated when running in the context of `Trigger.isUpdate` +- Apex post-processors: your Apex class should implement `LoggerHandler.PostProcessor` and the method `executePostProcessors(List loggerRecords, Map oldLoggerRecordsById)`. For example: + + ```java + public with sharing class ExamplePostProcessor implements LoggerHandler.PostProcessor { + public void execute(List logs, Map oldLoggerRecordsById) { + switch on Trigger.operationType { + when BEFORE_INSERT { + for (Log__c log : logs) { + log.Status__c = 'On Hold'; + } + } + } + } + } + + ``` + +Once you've created your Apex or Flow post-processor(s), you will also need to configure the custom metadata type `LoggerHandlerConfiguration__mdt` to specify the name(s) of Apex class and Flow to run. + ## Managing Logs To help development and support teams better manage logs (and any underlying code or config issues), some fields on `Log__c` are provided to track the owner, priority and status of a log. These fields are optional, but are helpful in critical environments (production, QA sandboxes, UAT sandboxes, etc.) for monitoring ongoing user activities. diff --git a/nebula-logger/main/log-management/classes/LogEntryHandler.cls b/nebula-logger/main/log-management/classes/LogEntryHandler.cls index 9d8d31786..a620ffa6d 100644 --- a/nebula-logger/main/log-management/classes/LogEntryHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryHandler.cls @@ -8,14 +8,18 @@ * @description Manages setting fields on `LogEntry__c` before insert & before update */ public without sharing class LogEntryHandler { + // Trigger-based variables - tests can override these with mock objects @testVisible private List logEntries; @testVisible + private Map oldLogEntriesById; + @testVisible private TriggerOperation triggerOperationType; public LogEntryHandler() { this.logEntries = (List) Trigger.new; + this.oldLogEntriesById = (Map) Trigger.oldMap; this.triggerOperationType = Trigger.operationType; } @@ -39,6 +43,9 @@ public without sharing class LogEntryHandler { this.setCheckboxFields(); } } + + // Run any post-processors + LoggerHandler.executePostProcessors(this.logEntries, this.oldLogEntriesById); } private void setCheckboxFields() { diff --git a/nebula-logger/main/log-management/classes/LogHandler.cls b/nebula-logger/main/log-management/classes/LogHandler.cls index 82f2624ae..1a7ce72d4 100644 --- a/nebula-logger/main/log-management/classes/LogHandler.cls +++ b/nebula-logger/main/log-management/classes/LogHandler.cls @@ -58,6 +58,9 @@ public without sharing class LogHandler { this.shareLogsWithLoggingUsers(); } } + + // Run any post-processors + LoggerHandler.executePostProcessors(this.logs, this.oldLogsById); } private void setOrgReleaseCycle() { diff --git a/nebula-logger/main/log-management/classes/LoggerHandler.cls b/nebula-logger/main/log-management/classes/LoggerHandler.cls new file mode 100644 index 000000000..9fd29d417 --- /dev/null +++ b/nebula-logger/main/log-management/classes/LoggerHandler.cls @@ -0,0 +1,45 @@ +global class LoggerHandler { + private LoggerHandler() {} + + global interface PostProcessor { + void execute(List loggerRecords, Map oldLoggerRecordsById); + } + + public static void executePostProcessors(List loggerRecords, Map oldLoggerRecordsById) { + String sobjectTypeCmdtName = loggerRecords.getSObjectType().getDescribe().getName().replace('__c', ''); + + List loggerHandlerConfigurations = [ + SELECT ApexClassName__c, FlowName__c + FROM LoggerHandlerConfiguration__mdt + WHERE LoggerSObject__r.DeveloperName = :sobjectTypeCmdtName + ]; + LoggerHandlerConfiguration__mdt loggerHandlerConfiguration = loggerHandlerConfigurations.isEmpty() ? null : loggerHandlerConfigurations.get(0); + + executeApexClass(loggerHandlerConfiguration?.ApexClassName__c, loggerRecords, oldLoggerRecordsById); + executeFlow(loggerHandlerConfiguration?.FlowName__c, loggerRecords, oldLoggerRecordsById); + } + + private static void executeApexClass(String apexClassName, List loggerRecords, Map oldLoggerRecordsById) { + if (String.isBlank(apexClassName)) { + return; + } + + Type postProcessorType = Type.forName(apexClassName); + PostProcessor recordPostProcessor = (PostProcessor) postProcessorType.newInstance(); + recordPostProcessor.execute(loggerRecords, oldLoggerRecordsById); + } + + private static void executeFlow(String flowName, List loggerRecords, Map oldLoggerRecordsById) { + if (String.isBlank(flowName)) { + return; + } + + Map flowInputs = new Map(); + flowInputs.put('records', loggerRecords); + flowInputs.put('oldRecords', oldLoggerRecordsById.values()); + + Flow.Interview recordFlow = Flow.Interview.createInterview(flowName, flowInputs); + recordFlow.start(); + } +} + diff --git a/nebula-logger/main/log-management/classes/LoggerHandler.cls-meta.xml b/nebula-logger/main/log-management/classes/LoggerHandler.cls-meta.xml new file mode 100644 index 000000000..d75b0582f --- /dev/null +++ b/nebula-logger/main/log-management/classes/LoggerHandler.cls-meta.xml @@ -0,0 +1,5 @@ + + + 51.0 + Active + diff --git a/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml new file mode 100644 index 000000000..41d092054 --- /dev/null +++ b/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml @@ -0,0 +1,78 @@ + + + + false + false + true + + + + Required + MasterLabel + + + Required + DeveloperName + + + Required + LoggerSObject__c + + + Required + ApexClassName__c + + + + + Edit + IsProtected + + + Required + NamespacePrefix + + + + + + false + false + true + + + + Readonly + CreatedById + + + + + Readonly + LastModifiedById + + + + + + true + false + false + + + + + + + false + false + false + false + false + + 00h3F0000048LpM + 4 + 0 + Default + + diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/LoggerHandlerConfiguration__mdt.object-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/LoggerHandlerConfiguration__mdt.object-meta.xml new file mode 100644 index 000000000..2e5eaf852 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/LoggerHandlerConfiguration__mdt.object-meta.xml @@ -0,0 +1,7 @@ + + + Used to configure additional Apex classes that should be executed by Logger after creating or updating records in Log__c or LogEntry__c + + Logger Handler Configs + Public + diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/ApexClassName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/ApexClassName__c.field-meta.xml new file mode 100644 index 000000000..7df9b3a7b --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/ApexClassName__c.field-meta.xml @@ -0,0 +1,13 @@ + + + ApexClassName__c + The name of an Apex class that implements LoggerPostProcessor.Handler + false + DeveloperControlled + The name of an Apex class that implements LoggerPostProcessor.Handler + + 255 + true + Text + false + diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/FlowName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/FlowName__c.field-meta.xml new file mode 100644 index 000000000..ec7d16545 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/FlowName__c.field-meta.xml @@ -0,0 +1,11 @@ + + + FlowName__c + false + DeveloperControlled + + 255 + false + Text + false + diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml new file mode 100644 index 000000000..1df03fd8c --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml @@ -0,0 +1,15 @@ + + + LoggerSObject__c + The Logger object to process - Log__c or LogEntry__c + false + DeveloperControlled + The Logger object to process - Log__c or LogEntry__c + + EntityDefinition + Logger Post Processors + LoggerPostProcessors + true + MetadataRelationship + true + diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml new file mode 100644 index 000000000..5326b3366 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml @@ -0,0 +1,11 @@ + + + All + MasterLabel + DeveloperName + LoggerSObject__c + ApexClassName__c + FlowName__c + Everything + + From 1de4a6568232145ae23b2494d44aa9b186dff92e Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Thu, 3 Jun 2021 23:51:14 -0700 Subject: [PATCH 02/82] Added all trigger operations + updates in README --- README.md | 11 ++++++---- content/logger-handler-configuration.png | Bin 0 -> 101240 bytes .../classes/LogEntryHandler.cls | 1 - .../log-management/classes/LoggerHandler.cls | 5 +++-- ...ndler Configuration Layout.layout-meta.xml | 20 +++++++++++------- .../fields/ApexClassName__c.field-meta.xml | 2 +- .../main/log-management/triggers/Log.trigger | 2 +- .../log-management/triggers/LogEntry.trigger | 2 +- 8 files changed, 25 insertions(+), 18 deletions(-) create mode 100644 content/logger-handler-configuration.png diff --git a/README.md b/README.md index 25d94efa3..0679a4d25 100644 --- a/README.md +++ b/README.md @@ -338,17 +338,18 @@ The class `LogMessage` provides the ability to generate string messages on deman For more details, check out the `LogMessage` class [documentation](https://jongpie.github.io/NebulaLogger/logger-engine/LogMessage). -### Adding Custom Post-Processors for Log__c and LogEntry__c +### Adding Custom Post-Processors for Log\_\_c and LogEntry\_\_c -If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you leverage Apex or Flow. +If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you can leverage Apex or Flow to define "post-processors" - the logger system will then automatically run the post-processors after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on) - Flow post-processors: your Flow should be built with 2 input parameters 1. `records` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) - 1. `oldRecords` - The list of logger records as they exist in the datatabase - this is only populated when running in the context of `Trigger.isUpdate` + 2. `oldRecords` - The list of logger records as they exist in the datatabase - this is only populated when running in the context of `Trigger.isUpdate` + 3. `triggerOperation` - The name of the current trigger operation (such as BEFORE_INSERT, BEFORE_UPDATE, etc.) - Apex post-processors: your Apex class should implement `LoggerHandler.PostProcessor` and the method `executePostProcessors(List loggerRecords, Map oldLoggerRecordsById)`. For example: ```java - public with sharing class ExamplePostProcessor implements LoggerHandler.PostProcessor { + public class ExamplePostProcessor implements LoggerHandler.PostProcessor { public void execute(List logs, Map oldLoggerRecordsById) { switch on Trigger.operationType { when BEFORE_INSERT { @@ -364,6 +365,8 @@ If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, Once you've created your Apex or Flow post-processor(s), you will also need to configure the custom metadata type `LoggerHandlerConfiguration__mdt` to specify the name(s) of Apex class and Flow to run. +![Logger Handler Configuration](./content/logger-handler-configuration.png) + ## Managing Logs To help development and support teams better manage logs (and any underlying code or config issues), some fields on `Log__c` are provided to track the owner, priority and status of a log. These fields are optional, but are helpful in critical environments (production, QA sandboxes, UAT sandboxes, etc.) for monitoring ongoing user activities. diff --git a/content/logger-handler-configuration.png b/content/logger-handler-configuration.png new file mode 100644 index 0000000000000000000000000000000000000000..8ed0aa27d74b9f4b794976d6deb16f5cd5827de0 GIT binary patch literal 101240 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

Tj+ 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 z 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 RC-@$fijv0V^oxkc{|8zl8wmga literal 0 HcmV?d00001 diff --git a/nebula-logger/main/log-management/classes/LogEntryHandler.cls b/nebula-logger/main/log-management/classes/LogEntryHandler.cls index a620ffa6d..cb2f2b2b8 100644 --- a/nebula-logger/main/log-management/classes/LogEntryHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryHandler.cls @@ -8,7 +8,6 @@ * @description Manages setting fields on `LogEntry__c` before insert & before update */ public without sharing class LogEntryHandler { - // Trigger-based variables - tests can override these with mock objects @testVisible private List logEntries; diff --git a/nebula-logger/main/log-management/classes/LoggerHandler.cls b/nebula-logger/main/log-management/classes/LoggerHandler.cls index 9fd29d417..0c5c60f40 100644 --- a/nebula-logger/main/log-management/classes/LoggerHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerHandler.cls @@ -1,5 +1,6 @@ global class LoggerHandler { - private LoggerHandler() {} + private LoggerHandler() { + } global interface PostProcessor { void execute(List loggerRecords, Map oldLoggerRecordsById); @@ -37,9 +38,9 @@ global class LoggerHandler { Map flowInputs = new Map(); flowInputs.put('records', loggerRecords); flowInputs.put('oldRecords', oldLoggerRecordsById.values()); + flowInputs.put('triggerOperation', Trigger.operationType); Flow.Interview recordFlow = Flow.Interview.createInterview(flowName, flowInputs); recordFlow.start(); } } - diff --git a/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml index 41d092054..f16a5a78c 100644 --- a/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml @@ -14,23 +14,19 @@ Required DeveloperName + + Required LoggerSObject__c - Required + Edit ApexClassName__c - - Edit - IsProtected - - - Required - NamespacePrefix + FlowName__c @@ -41,12 +37,20 @@ true + + Required + NamespacePrefix + Readonly CreatedById + + Edit + IsProtected + Readonly LastModifiedById diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/ApexClassName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/ApexClassName__c.field-meta.xml index 7df9b3a7b..814ec8680 100644 --- a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/ApexClassName__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/ApexClassName__c.field-meta.xml @@ -7,7 +7,7 @@ The name of an Apex class that implements LoggerPostProcessor.Handler 255 - true + false Text false diff --git a/nebula-logger/main/log-management/triggers/Log.trigger b/nebula-logger/main/log-management/triggers/Log.trigger index 754ef74a0..e7bfb5ad4 100644 --- a/nebula-logger/main/log-management/triggers/Log.trigger +++ b/nebula-logger/main/log-management/triggers/Log.trigger @@ -2,6 +2,6 @@ // 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. // //------------------------------------------------------------------------------------------------// -trigger Log on Log__c(before insert, before update, after insert) { +trigger Log on Log__c(before insert, before update, before delete, after insert, after update, after delete, after undelete) { new LogHandler().execute(); } diff --git a/nebula-logger/main/log-management/triggers/LogEntry.trigger b/nebula-logger/main/log-management/triggers/LogEntry.trigger index 842830472..07009e45a 100644 --- a/nebula-logger/main/log-management/triggers/LogEntry.trigger +++ b/nebula-logger/main/log-management/triggers/LogEntry.trigger @@ -2,6 +2,6 @@ // 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. // //------------------------------------------------------------------------------------------------// -trigger LogEntry on LogEntry__c(before insert, before update) { +trigger LogEntry on LogEntry__c(before insert, before update, before delete, after insert, after update, after delete, after undelete) { new LogEntryHandler().execute(); } From 5ffe394e6ac9525397fb946bc71df46712f3a1d3 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Thu, 3 Jun 2021 23:57:20 -0700 Subject: [PATCH 03/82] Added triggerOperation parameter --- README.md | 6 +++--- nebula-logger/main/log-management/classes/LoggerHandler.cls | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0679a4d25..4b394519f 100644 --- a/README.md +++ b/README.md @@ -346,12 +346,12 @@ If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, 1. `records` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) 2. `oldRecords` - The list of logger records as they exist in the datatabase - this is only populated when running in the context of `Trigger.isUpdate` 3. `triggerOperation` - The name of the current trigger operation (such as BEFORE_INSERT, BEFORE_UPDATE, etc.) -- Apex post-processors: your Apex class should implement `LoggerHandler.PostProcessor` and the method `executePostProcessors(List loggerRecords, Map oldLoggerRecordsById)`. For example: +- Apex post-processors: your Apex class should implement `LoggerHandler.PostProcessor`. For example: ```java public class ExamplePostProcessor implements LoggerHandler.PostProcessor { - public void execute(List logs, Map oldLoggerRecordsById) { - switch on Trigger.operationType { + public void execute(Trigger.operationType triggerOperation, List logs, Map oldLoggerRecordsById) { + switch on triggerOperation { when BEFORE_INSERT { for (Log__c log : logs) { log.Status__c = 'On Hold'; diff --git a/nebula-logger/main/log-management/classes/LoggerHandler.cls b/nebula-logger/main/log-management/classes/LoggerHandler.cls index 0c5c60f40..843df3085 100644 --- a/nebula-logger/main/log-management/classes/LoggerHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerHandler.cls @@ -3,7 +3,7 @@ global class LoggerHandler { } global interface PostProcessor { - void execute(List loggerRecords, Map oldLoggerRecordsById); + void execute(TriggerOperation triggerOperation, List loggerRecords, Map oldLoggerRecordsById); } public static void executePostProcessors(List loggerRecords, Map oldLoggerRecordsById) { @@ -27,7 +27,7 @@ global class LoggerHandler { Type postProcessorType = Type.forName(apexClassName); PostProcessor recordPostProcessor = (PostProcessor) postProcessorType.newInstance(); - recordPostProcessor.execute(loggerRecords, oldLoggerRecordsById); + recordPostProcessor.execute(Trigger.operationType, loggerRecords, oldLoggerRecordsById); } private static void executeFlow(String flowName, List loggerRecords, Map oldLoggerRecordsById) { From a9224c2843ad209fa3b32b225e6ebc4912a1ea4e Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Thu, 3 Jun 2021 23:58:47 -0700 Subject: [PATCH 04/82] Fixed Flow input details --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b394519f..18bd1b2a6 100644 --- a/README.md +++ b/README.md @@ -342,7 +342,7 @@ For more details, check out the `LogMessage` class [documentation](https://jongp If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you can leverage Apex or Flow to define "post-processors" - the logger system will then automatically run the post-processors after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on) -- Flow post-processors: your Flow should be built with 2 input parameters +- Flow post-processors: your Flow should be built with these input parameters: 1. `records` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) 2. `oldRecords` - The list of logger records as they exist in the datatabase - this is only populated when running in the context of `Trigger.isUpdate` 3. `triggerOperation` - The name of the current trigger operation (such as BEFORE_INSERT, BEFORE_UPDATE, etc.) From 778af21ccd180aeb446522ae1fad92e7c55d8b03 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Fri, 4 Jun 2021 00:27:49 -0700 Subject: [PATCH 05/82] Added IsActive__c flag on config CMDT --- .../main/log-management/classes/LoggerHandler.cls | 8 ++++++-- ...t-Logger Handler Configuration Layout.layout-meta.xml | 4 ++++ .../fields/IsActive__c.field-meta.xml | 9 +++++++++ .../listViews/All.listView-meta.xml | 1 + 4 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/IsActive__c.field-meta.xml diff --git a/nebula-logger/main/log-management/classes/LoggerHandler.cls b/nebula-logger/main/log-management/classes/LoggerHandler.cls index 843df3085..78e376bfd 100644 --- a/nebula-logger/main/log-management/classes/LoggerHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerHandler.cls @@ -7,12 +7,16 @@ global class LoggerHandler { } public static void executePostProcessors(List loggerRecords, Map oldLoggerRecordsById) { + if (loggerRecords == null) { + return; + } + String sobjectTypeCmdtName = loggerRecords.getSObjectType().getDescribe().getName().replace('__c', ''); List loggerHandlerConfigurations = [ SELECT ApexClassName__c, FlowName__c FROM LoggerHandlerConfiguration__mdt - WHERE LoggerSObject__r.DeveloperName = :sobjectTypeCmdtName + WHERE LoggerSObject__r.DeveloperName = :sobjectTypeCmdtName AND IsActive__c = TRUE ]; LoggerHandlerConfiguration__mdt loggerHandlerConfiguration = loggerHandlerConfigurations.isEmpty() ? null : loggerHandlerConfigurations.get(0); @@ -37,7 +41,7 @@ global class LoggerHandler { Map flowInputs = new Map(); flowInputs.put('records', loggerRecords); - flowInputs.put('oldRecords', oldLoggerRecordsById.values()); + flowInputs.put('oldRecords', oldLoggerRecordsById?.values()); flowInputs.put('triggerOperation', Trigger.operationType); Flow.Interview recordFlow = Flow.Interview.createInterview(flowName, flowInputs); diff --git a/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml index f16a5a78c..d08ca4a12 100644 --- a/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml @@ -14,6 +14,10 @@ Required DeveloperName + + Edit + IsActive__c + diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/IsActive__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/IsActive__c.field-meta.xml new file mode 100644 index 000000000..570cc14bd --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/IsActive__c.field-meta.xml @@ -0,0 +1,9 @@ + + + IsActive__c + true + false + SubscriberControlled + + Checkbox + diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml index 5326b3366..acacae25b 100644 --- a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml @@ -3,6 +3,7 @@ All MasterLabel DeveloperName + IsActive__c LoggerSObject__c ApexClassName__c FlowName__c From 9ff08baa46fa51a5cec7b145c5307f43da3dd126 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Fri, 4 Jun 2021 08:09:23 -0700 Subject: [PATCH 06/82] Moved post-processor interface outside of LoggerHandler, LoggerHandler is now abstract & used by all 3 handlers (mini trigger framework style) --- README.md | 4 +-- .../classes/LogEntryEventHandler.cls | 2 +- .../classes/LogEntryHandler.cls | 4 +-- .../log-management/classes/LogHandler.cls | 4 +-- .../log-management/classes/LoggerHandler.cls | 27 ++++++++++--------- .../classes/LoggerPostProcessor.cls | 13 +++++++++ .../classes/LoggerPostProcessor.cls-meta.xml | 5 ++++ 7 files changed, 40 insertions(+), 19 deletions(-) create mode 100644 nebula-logger/main/log-management/classes/LoggerPostProcessor.cls create mode 100644 nebula-logger/main/log-management/classes/LoggerPostProcessor.cls-meta.xml diff --git a/README.md b/README.md index 18bd1b2a6..72d4374d6 100644 --- a/README.md +++ b/README.md @@ -346,10 +346,10 @@ If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, 1. `records` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) 2. `oldRecords` - The list of logger records as they exist in the datatabase - this is only populated when running in the context of `Trigger.isUpdate` 3. `triggerOperation` - The name of the current trigger operation (such as BEFORE_INSERT, BEFORE_UPDATE, etc.) -- Apex post-processors: your Apex class should implement `LoggerHandler.PostProcessor`. For example: +- Apex post-processors: your Apex class should implement `LoggerPostProcessor`. For example: ```java - public class ExamplePostProcessor implements LoggerHandler.PostProcessor { + public class ExamplePostProcessor implements LoggerPostProcessor { public void execute(Trigger.operationType triggerOperation, List logs, Map oldLoggerRecordsById) { switch on triggerOperation { when BEFORE_INSERT { diff --git a/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls b/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls index 708cd6072..c19b09ea9 100644 --- a/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls @@ -7,7 +7,7 @@ * @group Log Management * @description Subscribes to `LogEntryEvent__e` platform events and normalizes the data into `Log__c` and `LogEntry__c` records */ -public without sharing class LogEntryEventHandler { +public without sharing class LogEntryEventHandler extends LoggerHandler { private static final Map TRANSACTION_ID_TO_LOG = new Map(); @testVisible diff --git a/nebula-logger/main/log-management/classes/LogEntryHandler.cls b/nebula-logger/main/log-management/classes/LogEntryHandler.cls index cb2f2b2b8..296213a3f 100644 --- a/nebula-logger/main/log-management/classes/LogEntryHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryHandler.cls @@ -7,7 +7,7 @@ * @group Log Management * @description Manages setting fields on `LogEntry__c` before insert & before update */ -public without sharing class LogEntryHandler { +public without sharing class LogEntryHandler extends LoggerHandler { // Trigger-based variables - tests can override these with mock objects @testVisible private List logEntries; @@ -44,7 +44,7 @@ public without sharing class LogEntryHandler { } // Run any post-processors - LoggerHandler.executePostProcessors(this.logEntries, this.oldLogEntriesById); + super.executePostProcessors(this.logEntries, this.oldLogEntriesById); } private void setCheckboxFields() { diff --git a/nebula-logger/main/log-management/classes/LogHandler.cls b/nebula-logger/main/log-management/classes/LogHandler.cls index 1a7ce72d4..85cd0e6fe 100644 --- a/nebula-logger/main/log-management/classes/LogHandler.cls +++ b/nebula-logger/main/log-management/classes/LogHandler.cls @@ -7,7 +7,7 @@ * @group Log Management * @description Manages setting fields on `Log__c` before insert & before update */ -public without sharing class LogHandler { +public without sharing class LogHandler extends LoggerHandler { private static final Organization ORGANIZATION = [SELECT Id, InstanceName, IsSandbox FROM Organization]; @testVisible @@ -60,7 +60,7 @@ public without sharing class LogHandler { } // Run any post-processors - LoggerHandler.executePostProcessors(this.logs, this.oldLogsById); + super.executePostProcessors(this.logs, this.oldLogsById); } private void setOrgReleaseCycle() { diff --git a/nebula-logger/main/log-management/classes/LoggerHandler.cls b/nebula-logger/main/log-management/classes/LoggerHandler.cls index 78e376bfd..537d4cd01 100644 --- a/nebula-logger/main/log-management/classes/LoggerHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerHandler.cls @@ -1,12 +1,15 @@ -global class LoggerHandler { - private LoggerHandler() { - } - - global interface PostProcessor { - void execute(TriggerOperation triggerOperation, List loggerRecords, Map oldLoggerRecordsById); - } - - public static void executePostProcessors(List loggerRecords, Map oldLoggerRecordsById) { +//------------------------------------------------------------------------------------------------// +// 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 Abstract class used by trigger handlers for shared logic + */ + public abstract class LoggerHandler { + + protected void executePostProcessors(List loggerRecords, Map oldLoggerRecordsById) { if (loggerRecords == null) { return; } @@ -24,17 +27,17 @@ global class LoggerHandler { executeFlow(loggerHandlerConfiguration?.FlowName__c, loggerRecords, oldLoggerRecordsById); } - private static void executeApexClass(String apexClassName, List loggerRecords, Map oldLoggerRecordsById) { + private void executeApexClass(String apexClassName, List loggerRecords, Map oldLoggerRecordsById) { if (String.isBlank(apexClassName)) { return; } Type postProcessorType = Type.forName(apexClassName); - PostProcessor recordPostProcessor = (PostProcessor) postProcessorType.newInstance(); + LoggerPostProcessor recordPostProcessor = (LoggerPostProcessor) postProcessorType.newInstance(); recordPostProcessor.execute(Trigger.operationType, loggerRecords, oldLoggerRecordsById); } - private static void executeFlow(String flowName, List loggerRecords, Map oldLoggerRecordsById) { + private void executeFlow(String flowName, List loggerRecords, Map oldLoggerRecordsById) { if (String.isBlank(flowName)) { return; } diff --git a/nebula-logger/main/log-management/classes/LoggerPostProcessor.cls b/nebula-logger/main/log-management/classes/LoggerPostProcessor.cls new file mode 100644 index 000000000..839586e6d --- /dev/null +++ b/nebula-logger/main/log-management/classes/LoggerPostProcessor.cls @@ -0,0 +1,13 @@ +//------------------------------------------------------------------------------------------------// +// 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 Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` + */ + global interface LoggerPostProcessor { + void execute(TriggerOperation triggerOperation, List loggerRecords, Map oldLoggerRecordsById); +} \ No newline at end of file diff --git a/nebula-logger/main/log-management/classes/LoggerPostProcessor.cls-meta.xml b/nebula-logger/main/log-management/classes/LoggerPostProcessor.cls-meta.xml new file mode 100644 index 000000000..d75b0582f --- /dev/null +++ b/nebula-logger/main/log-management/classes/LoggerPostProcessor.cls-meta.xml @@ -0,0 +1,5 @@ + + + 51.0 + Active + From e93a5cf77f6c246615d3ddc0a5ab488e49ec44c2 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Fri, 4 Jun 2021 18:13:26 -0700 Subject: [PATCH 07/82] Swapped `super` for `this` ...and all I got was this t-shirt? --- nebula-logger/main/log-management/classes/LogEntryHandler.cls | 2 +- nebula-logger/main/log-management/classes/LogHandler.cls | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nebula-logger/main/log-management/classes/LogEntryHandler.cls b/nebula-logger/main/log-management/classes/LogEntryHandler.cls index 296213a3f..d868077bb 100644 --- a/nebula-logger/main/log-management/classes/LogEntryHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryHandler.cls @@ -44,7 +44,7 @@ public without sharing class LogEntryHandler extends LoggerHandler { } // Run any post-processors - super.executePostProcessors(this.logEntries, this.oldLogEntriesById); + this.executePostProcessors(this.logEntries, this.oldLogEntriesById); } private void setCheckboxFields() { diff --git a/nebula-logger/main/log-management/classes/LogHandler.cls b/nebula-logger/main/log-management/classes/LogHandler.cls index 85cd0e6fe..a2fc6672d 100644 --- a/nebula-logger/main/log-management/classes/LogHandler.cls +++ b/nebula-logger/main/log-management/classes/LogHandler.cls @@ -60,7 +60,7 @@ public without sharing class LogHandler extends LoggerHandler { } // Run any post-processors - super.executePostProcessors(this.logs, this.oldLogsById); + this.executePostProcessors(this.logs, this.oldLogsById); } private void setOrgReleaseCycle() { From e9b7454b02817fe1cb79d5a16610601860b55ce1 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 5 Jun 2021 00:34:52 -0700 Subject: [PATCH 08/82] Added handler tests for Apex post-processors + cleaned up field names --- README.md | 10 ++-- .../log-management/classes/LoggerHandler.cls | 39 +++++++------- .../classes/LoggerPostProcessor.cls | 3 +- ...LoggerHandlerConfiguration.Log.md-meta.xml | 13 +++++ ...rHandlerConfiguration.LogEntry.md-meta.xml | 13 +++++ ...ndler Configuration Layout.layout-meta.xml | 25 +++++---- ...rHandlerConfiguration__mdt.object-meta.xml | 4 +- .../fields/FlowName__c.field-meta.xml | 11 ---- .../fields/IsActive__c.field-meta.xml | 9 ---- .../fields/LoggerSObject__c.field-meta.xml | 2 +- ...tProcessorApexClassName__c.field-meta.xml} | 4 +- ...PostProcessorFlowApiName__c.field-meta.xml | 15 ++++++ .../listViews/All.listView-meta.xml | 7 ++- .../classes/LogEntryHandler_Tests.cls | 51 +++++++++++++++++++ .../classes/LogHandler_Tests.cls | 48 +++++++++++++++++ 15 files changed, 192 insertions(+), 62 deletions(-) create mode 100644 nebula-logger/main/log-management/customMetadata/LoggerHandlerConfiguration.Log.md-meta.xml create mode 100644 nebula-logger/main/log-management/customMetadata/LoggerHandlerConfiguration.LogEntry.md-meta.xml delete mode 100644 nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/FlowName__c.field-meta.xml delete mode 100644 nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/IsActive__c.field-meta.xml rename nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/{ApexClassName__c.field-meta.xml => PostProcessorApexClassName__c.field-meta.xml} (80%) create mode 100644 nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml diff --git a/README.md b/README.md index 49c469773..19a63211c 100644 --- a/README.md +++ b/README.md @@ -344,15 +344,15 @@ For more details, check out the `LogMessage` class [documentation](https://jongp If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you can leverage Apex or Flow to define "post-processors" - the logger system will then automatically run the post-processors after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on) - Flow post-processors: your Flow should be built with these input parameters: - 1. `records` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) - 2. `oldRecords` - The list of logger records as they exist in the datatabase - this is only populated when running in the context of `Trigger.isUpdate` - 3. `triggerOperation` - The name of the current trigger operation (such as BEFORE_INSERT, BEFORE_UPDATE, etc.) + 1. `triggerOperationType` - The name of the current trigger operation (such as BEFORE_INSERT, BEFORE_UPDATE, etc.) + 2. `records` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) + 3. `oldRecords` - The list of logger records as they exist in the datatabase - this is only populated when running in the context of `Trigger.isUpdate` - Apex post-processors: your Apex class should implement `LoggerPostProcessor`. For example: ```java public class ExamplePostProcessor implements LoggerPostProcessor { - public void execute(Trigger.operationType triggerOperation, List logs, Map oldLoggerRecordsById) { - switch on triggerOperation { + public void execute(Trigger.operationType triggerOperationType, List logs, Map oldLoggerRecordsById) { + switch on triggerOperationType { when BEFORE_INSERT { for (Log__c log : logs) { log.Status__c = 'On Hold'; diff --git a/nebula-logger/main/log-management/classes/LoggerHandler.cls b/nebula-logger/main/log-management/classes/LoggerHandler.cls index 537d4cd01..3cc757ecf 100644 --- a/nebula-logger/main/log-management/classes/LoggerHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerHandler.cls @@ -8,46 +8,51 @@ * @description Abstract class used by trigger handlers for shared logic */ public abstract class LoggerHandler { + @testVisible + private static Map configurationsbySObjectType = loadConfigurations(); + + private static Map loadConfigurations() { + Map configsbySObjectType = new Map(); + for (LoggerHandlerConfiguration__mdt config : LoggerHandlerConfiguration__mdt.getAll().values()) { + // Schema.getGlobalDescribe() is the worst, so don't use it + SObjectType sobjectType = ((SObject) Type.forName(config.LoggerSObject__r.DeveloperName + '__c').newInstance()).getSObjectType(); + + configsbySObjectType.put(sobjectType, config); + } + return configsbySObjectType; + } protected void executePostProcessors(List loggerRecords, Map oldLoggerRecordsById) { if (loggerRecords == null) { return; } - String sobjectTypeCmdtName = loggerRecords.getSObjectType().getDescribe().getName().replace('__c', ''); - - List loggerHandlerConfigurations = [ - SELECT ApexClassName__c, FlowName__c - FROM LoggerHandlerConfiguration__mdt - WHERE LoggerSObject__r.DeveloperName = :sobjectTypeCmdtName AND IsActive__c = TRUE - ]; - LoggerHandlerConfiguration__mdt loggerHandlerConfiguration = loggerHandlerConfigurations.isEmpty() ? null : loggerHandlerConfigurations.get(0); + LoggerHandlerConfiguration__mdt loggerHandlerConfiguration = configurationsbySObjectType.get(loggerRecords.getSObjectType()); - executeApexClass(loggerHandlerConfiguration?.ApexClassName__c, loggerRecords, oldLoggerRecordsById); - executeFlow(loggerHandlerConfiguration?.FlowName__c, loggerRecords, oldLoggerRecordsById); + this.executeApexClass(loggerHandlerConfiguration?.PostProcessorApexClassName__c, loggerRecords, oldLoggerRecordsById); + this.executeFlow(loggerHandlerConfiguration?.PostProcessorFlowApiName__c, loggerRecords, oldLoggerRecordsById); } private void executeApexClass(String apexClassName, List loggerRecords, Map oldLoggerRecordsById) { - if (String.isBlank(apexClassName)) { + if (String.isBlank(apexClassName) || Type.forName(apexClassName) == null) { return; } - Type postProcessorType = Type.forName(apexClassName); - LoggerPostProcessor recordPostProcessor = (LoggerPostProcessor) postProcessorType.newInstance(); + LoggerPostProcessor recordPostProcessor = (LoggerPostProcessor) Type.forName(apexClassName).newInstance(); recordPostProcessor.execute(Trigger.operationType, loggerRecords, oldLoggerRecordsById); } - private void executeFlow(String flowName, List loggerRecords, Map oldLoggerRecordsById) { - if (String.isBlank(flowName)) { + private void executeFlow(String flowApiName, List loggerRecords, Map oldLoggerRecordsById) { + if (String.isBlank(flowApiName)) { return; } Map flowInputs = new Map(); + flowInputs.put('triggerOperationType', Trigger.operationType); flowInputs.put('records', loggerRecords); flowInputs.put('oldRecords', oldLoggerRecordsById?.values()); - flowInputs.put('triggerOperation', Trigger.operationType); - Flow.Interview recordFlow = Flow.Interview.createInterview(flowName, flowInputs); + Flow.Interview recordFlow = Flow.Interview.createInterview(flowApiName, flowInputs); recordFlow.start(); } } diff --git a/nebula-logger/main/log-management/classes/LoggerPostProcessor.cls b/nebula-logger/main/log-management/classes/LoggerPostProcessor.cls index 839586e6d..12f9fa912 100644 --- a/nebula-logger/main/log-management/classes/LoggerPostProcessor.cls +++ b/nebula-logger/main/log-management/classes/LoggerPostProcessor.cls @@ -3,11 +3,10 @@ // See LICENSE file or go to https://github.com/jongpie/NebulaLogger for full license details. // //------------------------------------------------------------------------------------------------// - /** * @group Log Management * @description Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` */ global interface LoggerPostProcessor { - void execute(TriggerOperation triggerOperation, List loggerRecords, Map oldLoggerRecordsById); + void execute(TriggerOperation triggerOperationType, List loggerRecords, Map oldLoggerRecordsById); } \ No newline at end of file diff --git a/nebula-logger/main/log-management/customMetadata/LoggerHandlerConfiguration.Log.md-meta.xml b/nebula-logger/main/log-management/customMetadata/LoggerHandlerConfiguration.Log.md-meta.xml new file mode 100644 index 000000000..fbad45c23 --- /dev/null +++ b/nebula-logger/main/log-management/customMetadata/LoggerHandlerConfiguration.Log.md-meta.xml @@ -0,0 +1,13 @@ + + + + false + + LoggerSObject__c + Log__c + + diff --git a/nebula-logger/main/log-management/customMetadata/LoggerHandlerConfiguration.LogEntry.md-meta.xml b/nebula-logger/main/log-management/customMetadata/LoggerHandlerConfiguration.LogEntry.md-meta.xml new file mode 100644 index 000000000..c80e3d49f --- /dev/null +++ b/nebula-logger/main/log-management/customMetadata/LoggerHandlerConfiguration.LogEntry.md-meta.xml @@ -0,0 +1,13 @@ + + + + false + + LoggerSObject__c + LogEntry__c + + diff --git a/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml index d08ca4a12..1b220462a 100644 --- a/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml @@ -2,7 +2,7 @@ false - false + true true @@ -14,30 +14,37 @@ Required DeveloperName - - Edit - IsActive__c - Required LoggerSObject__c + + + + + true + true + true + + Edit - ApexClassName__c + PostProcessorApexClassName__c + + Edit - FlowName__c + PostProcessorFlowApiName__c false - false + true true @@ -78,7 +85,7 @@ false false - 00h3F0000048LpM + 00h3F0000048Uxu 4 0 Default diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/LoggerHandlerConfiguration__mdt.object-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/LoggerHandlerConfiguration__mdt.object-meta.xml index 2e5eaf852..3570a901e 100644 --- a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/LoggerHandlerConfiguration__mdt.object-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/LoggerHandlerConfiguration__mdt.object-meta.xml @@ -1,7 +1,7 @@ Used to configure additional Apex classes that should be executed by Logger after creating or updating records in Log__c or LogEntry__c - - Logger Handler Configs + + Logger Handler Configurations Public diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/FlowName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/FlowName__c.field-meta.xml deleted file mode 100644 index ec7d16545..000000000 --- a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/FlowName__c.field-meta.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - FlowName__c - false - DeveloperControlled - - 255 - false - Text - false - diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/IsActive__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/IsActive__c.field-meta.xml deleted file mode 100644 index 570cc14bd..000000000 --- a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/IsActive__c.field-meta.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - IsActive__c - true - false - SubscriberControlled - - Checkbox - diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml index 1df03fd8c..41d004629 100644 --- a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml @@ -3,7 +3,7 @@ LoggerSObject__c The Logger object to process - Log__c or LogEntry__c false - DeveloperControlled + SubscriberControlled The Logger object to process - Log__c or LogEntry__c EntityDefinition diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/ApexClassName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml similarity index 80% rename from nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/ApexClassName__c.field-meta.xml rename to nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml index 814ec8680..bb9beafb3 100644 --- a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/ApexClassName__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml @@ -1,9 +1,9 @@ - ApexClassName__c + PostProcessorApexClassName__c The name of an Apex class that implements LoggerPostProcessor.Handler false - DeveloperControlled + SubscriberControlled The name of an Apex class that implements LoggerPostProcessor.Handler 255 diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml new file mode 100644 index 000000000..9c2185c06 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml @@ -0,0 +1,15 @@ + + + PostProcessorFlowApiName__c + The API name of a Flow that suppports these inputs: + - triggerOperationType: text variable + - records: record collection variable + - oldRecords: record collection variable + false + SubscriberControlled + + 255 + false + Text + false + diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml index acacae25b..b593e3a58 100644 --- a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml @@ -1,12 +1,11 @@ - + All MasterLabel DeveloperName - IsActive__c LoggerSObject__c - ApexClassName__c - FlowName__c + PostProcessorApexClassName__c + PostProcessorFlowApiName__c Everything diff --git a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls index c96e4c2a0..828904c0d 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls @@ -4,6 +4,30 @@ //------------------------------------------------------------------------------------------------// @isTest private class LogEntryHandler_Tests { + + public class LogEntryPostProcessorTest implements LoggerPostProcessor { + public void execute(TriggerOperation triggerOperationType, List logs, Map oldLogsById) { + if (triggerOperationType == TriggerOperation.BEFORE_INSERT) { + for (LogEntry__c logEntry : (List) logs) { + // The specific field changed doesn't really matter - we just want to ensure that whatever... + // ...logic implement in the instance of LoggerPostProcessor is executed + logEntry.Message__c = 'Some String'; + } + } + } + } + + private static LoggerHandlerConfiguration__mdt getMockConfiguration() { + // Mocking entity deefinition fields on CMDT is not properly supported, so here's some goofy workarounds for mocking an instance + EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :LogEntry__c.getSObjectType().getDescribe().getName()]; + LoggerHandlerConfiguration__mdt configuration = new LoggerHandlerConfiguration__mdt(); + + Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); + configurationUntyped.put('LoggerSObject__r', logEntityDefinition); + + return (LoggerHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerHandlerConfiguration__mdt.class); + } + @testSetup static void setupData() { Log__c log = new Log__c(TransactionId__c = '1234'); @@ -200,4 +224,31 @@ private class LogEntryHandler_Tests { System.assert(logEntry.HasStackTrace__c); System.assertEquals(stackTrace, logEntry.StackTrace__c); } + + @isTest + static void it_should_run_apex_post_processor_when_configured() { + String expectedMessage = 'Some String'; + + LoggerHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); + logHandlerConfiguration.PostProcessorApexClassName__c = LogEntryPostProcessorTest.class.getName(); + + Map configurationsBySObjectType = new Map{ + Schema.LogEntry__c.SObjectType => logHandlerConfiguration + }; + + Log__c log = [SELECT Id FROM Log__c LIMIT 1]; + + Test.startTest(); + + // Use the mock configurations + LoggerHandler.configurationsBySObjectType = configurationsBySObjectType; + + LogEntry__c logEntry = new LogEntry__c(Log__c = log.Id, Message__c = 'qwerty'); + insert logEntry; + + logEntry = [SELECT Id, Message__c FROM LogEntry__c WHERE Id = :logEntry.Id]; + System.assertEquals(expectedMessage, logEntry.Message__c); + + Test.stopTest(); + } } diff --git a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls index cf8fc1d00..a2cd9bd4a 100644 --- a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls @@ -11,6 +11,29 @@ private class LogHandler_Tests { private static final String FIRST_STATUS = Schema.Log__c.Status__c.getDescribe().getPicklistValues().get(0).getValue(); private static final String SECOND_STATUS = Schema.Log__c.Status__c.getDescribe().getPicklistValues().get(1).getValue(); + public class LogPostProcessorTest implements LoggerPostProcessor { + public void execute(TriggerOperation triggerOperationType, List logs, Map oldLogsById) { + if (triggerOperationType == TriggerOperation.BEFORE_INSERT) { + for (Log__c log : (List) logs) { + // The specific field changed doesn't really matter - we just want to ensure that whatever... + // ...logic implement in the instance of LoggerPostProcessor is executed + log.ProfileName__c = 'Some String'; + } + } + } + } + + private static LoggerHandlerConfiguration__mdt getMockConfiguration() { + // Mocking entity deefinition fields on CMDT is not properly supported, so here's some goofy workarounds for mocking an instance + EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :Log__c.getSObjectType().getDescribe().getName()]; + LoggerHandlerConfiguration__mdt configuration = new LoggerHandlerConfiguration__mdt(); + + Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); + configurationUntyped.put('LoggerSObject__r', logEntityDefinition); + + return (LoggerHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerHandlerConfiguration__mdt.class); + } + @testSetup static void setupData() { Map logStatusByName = new Map(); @@ -401,4 +424,29 @@ private class LogHandler_Tests { System.assertEquals(0, logShares.size(), logShares); } + + @isTest + static void it_should_run_apex_post_processor_when_configured() { + String expectedProfileName = 'Some String'; + + LoggerHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); + logHandlerConfiguration.PostProcessorApexClassName__c = LogPostProcessorTest.class.getName(); + + Map configurationsBySObjectType = new Map{ + Schema.Log__c.SObjectType => logHandlerConfiguration + }; + + Test.startTest(); + + // Use the mock configurations + LoggerHandler.configurationsBySObjectType = configurationsBySObjectType; + + Log__c log = new Log__c(LoggedBy__c = UserInfo.getUserId(), TransactionId__c = '1234'); + insert log; + + log = [SELECT Id, ProfileName__c FROM Log__c WHERE Id = :log.Id]; + System.assertEquals(expectedProfileName, log.ProfileName__c); + + Test.stopTest(); + } } From 30fe68c1c5b8c4db71c74c79995bd61224c745aa Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 5 Jun 2021 23:34:04 -0700 Subject: [PATCH 09/82] More renames - Renamed LoggerHandler to LoggerSObjectHandler - Renamed LoggerPostProcessor to LoggerSObjectPostProcessor - Renamed LoggerHandlerConfiguration__mdt to LoggerSObjectHandlerConfiguration__mdt --- README.md | 6 ++--- .../classes/LogEntryEventHandler.cls | 2 +- .../classes/LogEntryHandler.cls | 2 +- .../log-management/classes/LogHandler.cls | 2 +- ...erHandler.cls => LoggerSObjectHandler.cls} | 26 +++++++++---------- ....xml => LoggerSObjectHandler.cls-meta.xml} | 0 ...sor.cls => LoggerSObjectPostProcessor.cls} | 2 +- ...> LoggerSObjectPostProcessor.cls-meta.xml} | 0 ...bjectHandlerConfiguration.Log.md-meta.xml} | 0 ...HandlerConfiguration.LogEntry.md-meta.xml} | 0 ...dler Configuration Layout.layout-meta.xml} | 0 ...rHandlerConfiguration__mdt.object-meta.xml | 7 ----- ...tHandlerConfiguration__mdt.object-meta.xml | 8 ++++++ .../fields/LoggerSObject__c.field-meta.xml | 4 +-- ...stProcessorApexClassName__c.field-meta.xml | 6 ++--- ...PostProcessorFlowApiName__c.field-meta.xml | 0 .../listViews/All.listView-meta.xml | 0 .../classes/LogEntryHandler_Tests.cls | 16 ++++++------ .../classes/LogHandler_Tests.cls | 16 ++++++------ 19 files changed, 49 insertions(+), 48 deletions(-) rename nebula-logger/main/log-management/classes/{LoggerHandler.cls => LoggerSObjectHandler.cls} (51%) rename nebula-logger/main/log-management/classes/{LoggerHandler.cls-meta.xml => LoggerSObjectHandler.cls-meta.xml} (100%) rename nebula-logger/main/log-management/classes/{LoggerPostProcessor.cls => LoggerSObjectPostProcessor.cls} (93%) rename nebula-logger/main/log-management/classes/{LoggerPostProcessor.cls-meta.xml => LoggerSObjectPostProcessor.cls-meta.xml} (100%) rename nebula-logger/main/log-management/customMetadata/{LoggerHandlerConfiguration.Log.md-meta.xml => LoggerSObjectHandlerConfiguration.Log.md-meta.xml} (100%) rename nebula-logger/main/log-management/customMetadata/{LoggerHandlerConfiguration.LogEntry.md-meta.xml => LoggerSObjectHandlerConfiguration.LogEntry.md-meta.xml} (100%) rename nebula-logger/main/log-management/layouts/{LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml => LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml} (100%) delete mode 100644 nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/LoggerHandlerConfiguration__mdt.object-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/LoggerSObjectHandlerConfiguration__mdt.object-meta.xml rename nebula-logger/main/log-management/objects/{LoggerHandlerConfiguration__mdt => LoggerSObjectHandlerConfiguration__mdt}/fields/LoggerSObject__c.field-meta.xml (85%) rename nebula-logger/main/log-management/objects/{LoggerHandlerConfiguration__mdt => LoggerSObjectHandlerConfiguration__mdt}/fields/PostProcessorApexClassName__c.field-meta.xml (78%) rename nebula-logger/main/log-management/objects/{LoggerHandlerConfiguration__mdt => LoggerSObjectHandlerConfiguration__mdt}/fields/PostProcessorFlowApiName__c.field-meta.xml (100%) rename nebula-logger/main/log-management/objects/{LoggerHandlerConfiguration__mdt => LoggerSObjectHandlerConfiguration__mdt}/listViews/All.listView-meta.xml (100%) diff --git a/README.md b/README.md index 19a63211c..8d212db28 100644 --- a/README.md +++ b/README.md @@ -347,10 +347,10 @@ If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, 1. `triggerOperationType` - The name of the current trigger operation (such as BEFORE_INSERT, BEFORE_UPDATE, etc.) 2. `records` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) 3. `oldRecords` - The list of logger records as they exist in the datatabase - this is only populated when running in the context of `Trigger.isUpdate` -- Apex post-processors: your Apex class should implement `LoggerPostProcessor`. For example: +- Apex post-processors: your Apex class should implement `LoggerSObjectPostProcessor`. For example: ```java - public class ExamplePostProcessor implements LoggerPostProcessor { + public class ExamplePostProcessor implements LoggerSObjectPostProcessor { public void execute(Trigger.operationType triggerOperationType, List logs, Map oldLoggerRecordsById) { switch on triggerOperationType { when BEFORE_INSERT { @@ -364,7 +364,7 @@ If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, ``` -Once you've created your Apex or Flow post-processor(s), you will also need to configure the custom metadata type `LoggerHandlerConfiguration__mdt` to specify the name(s) of Apex class and Flow to run. +Once you've created your Apex or Flow post-processor(s), you will also need to configure the custom metadata type `LoggerSObjectHandlerConfiguration__mdt` to specify the name(s) of Apex class and Flow to run. ![Logger Handler Configuration](./content/logger-handler-configuration.png) diff --git a/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls b/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls index 9e0a58e41..26766bd8c 100644 --- a/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls @@ -7,7 +7,7 @@ * @group Log Management * @description Processes `LogEntryEvent__e` platform events and normalizes the data into `Log__c` and `LogEntry__c` records */ -public without sharing class LogEntryEventHandler extends LoggerHandler { +public without sharing class LogEntryEventHandler extends LoggerSObjectHandler { private static final Map TRANSACTION_ID_TO_LOG = new Map(); @testVisible diff --git a/nebula-logger/main/log-management/classes/LogEntryHandler.cls b/nebula-logger/main/log-management/classes/LogEntryHandler.cls index d868077bb..a974aa5cf 100644 --- a/nebula-logger/main/log-management/classes/LogEntryHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryHandler.cls @@ -7,7 +7,7 @@ * @group Log Management * @description Manages setting fields on `LogEntry__c` before insert & before update */ -public without sharing class LogEntryHandler extends LoggerHandler { +public without sharing class LogEntryHandler extends LoggerSObjectHandler { // Trigger-based variables - tests can override these with mock objects @testVisible private List logEntries; diff --git a/nebula-logger/main/log-management/classes/LogHandler.cls b/nebula-logger/main/log-management/classes/LogHandler.cls index a2fc6672d..f6ac02b02 100644 --- a/nebula-logger/main/log-management/classes/LogHandler.cls +++ b/nebula-logger/main/log-management/classes/LogHandler.cls @@ -7,7 +7,7 @@ * @group Log Management * @description Manages setting fields on `Log__c` before insert & before update */ -public without sharing class LogHandler extends LoggerHandler { +public without sharing class LogHandler extends LoggerSObjectHandler { private static final Organization ORGANIZATION = [SELECT Id, InstanceName, IsSandbox FROM Organization]; @testVisible diff --git a/nebula-logger/main/log-management/classes/LoggerHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls similarity index 51% rename from nebula-logger/main/log-management/classes/LoggerHandler.cls rename to nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index 3cc757ecf..ca1065d32 100644 --- a/nebula-logger/main/log-management/classes/LoggerHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -7,13 +7,13 @@ * @group Log Management * @description Abstract class used by trigger handlers for shared logic */ - public abstract class LoggerHandler { + public abstract class LoggerSObjectHandler { @testVisible - private static Map configurationsbySObjectType = loadConfigurations(); + private static Map configurationsbySObjectType = loadConfigurations(); - private static Map loadConfigurations() { - Map configsbySObjectType = new Map(); - for (LoggerHandlerConfiguration__mdt config : LoggerHandlerConfiguration__mdt.getAll().values()) { + private static Map loadConfigurations() { + Map configsbySObjectType = new Map(); + for (LoggerSObjectHandlerConfiguration__mdt config : LoggerSObjectHandlerConfiguration__mdt.getAll().values()) { // Schema.getGlobalDescribe() is the worst, so don't use it SObjectType sobjectType = ((SObject) Type.forName(config.LoggerSObject__r.DeveloperName + '__c').newInstance()).getSObjectType(); @@ -27,22 +27,22 @@ return; } - LoggerHandlerConfiguration__mdt loggerHandlerConfiguration = configurationsbySObjectType.get(loggerRecords.getSObjectType()); + LoggerSObjectHandlerConfiguration__mdt loggerHandlerConfiguration = configurationsbySObjectType.get(loggerRecords.getSObjectType()); - this.executeApexClass(loggerHandlerConfiguration?.PostProcessorApexClassName__c, loggerRecords, oldLoggerRecordsById); - this.executeFlow(loggerHandlerConfiguration?.PostProcessorFlowApiName__c, loggerRecords, oldLoggerRecordsById); + this.executePostProcessorApexClass(loggerHandlerConfiguration?.PostProcessorApexClassName__c, loggerRecords, oldLoggerRecordsById); + this.executePostProcessorFlow(loggerHandlerConfiguration?.PostProcessorFlowApiName__c, loggerRecords, oldLoggerRecordsById); } - private void executeApexClass(String apexClassName, List loggerRecords, Map oldLoggerRecordsById) { + private void executePostProcessorApexClass(String apexClassName, List loggerRecords, Map oldLoggerRecordsById) { if (String.isBlank(apexClassName) || Type.forName(apexClassName) == null) { return; } - LoggerPostProcessor recordPostProcessor = (LoggerPostProcessor) Type.forName(apexClassName).newInstance(); + LoggerSObjectPostProcessor recordPostProcessor = (LoggerSObjectPostProcessor) Type.forName(apexClassName).newInstance(); recordPostProcessor.execute(Trigger.operationType, loggerRecords, oldLoggerRecordsById); } - private void executeFlow(String flowApiName, List loggerRecords, Map oldLoggerRecordsById) { + private void executePostProcessorFlow(String flowApiName, List loggerRecords, Map oldLoggerRecordsById) { if (String.isBlank(flowApiName)) { return; } @@ -52,7 +52,7 @@ flowInputs.put('records', loggerRecords); flowInputs.put('oldRecords', oldLoggerRecordsById?.values()); - Flow.Interview recordFlow = Flow.Interview.createInterview(flowApiName, flowInputs); - recordFlow.start(); + Flow.Interview postProcessorFlow = Flow.Interview.createInterview(flowApiName, flowInputs); + postProcessorFlow.start(); } } diff --git a/nebula-logger/main/log-management/classes/LoggerHandler.cls-meta.xml b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls-meta.xml similarity index 100% rename from nebula-logger/main/log-management/classes/LoggerHandler.cls-meta.xml rename to nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls-meta.xml diff --git a/nebula-logger/main/log-management/classes/LoggerPostProcessor.cls b/nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls similarity index 93% rename from nebula-logger/main/log-management/classes/LoggerPostProcessor.cls rename to nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls index 12f9fa912..5e4130d85 100644 --- a/nebula-logger/main/log-management/classes/LoggerPostProcessor.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls @@ -7,6 +7,6 @@ * @group Log Management * @description Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` */ - global interface LoggerPostProcessor { + global interface LoggerSObjectPostProcessor { void execute(TriggerOperation triggerOperationType, List loggerRecords, Map oldLoggerRecordsById); } \ No newline at end of file diff --git a/nebula-logger/main/log-management/classes/LoggerPostProcessor.cls-meta.xml b/nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls-meta.xml similarity index 100% rename from nebula-logger/main/log-management/classes/LoggerPostProcessor.cls-meta.xml rename to nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls-meta.xml diff --git a/nebula-logger/main/log-management/customMetadata/LoggerHandlerConfiguration.Log.md-meta.xml b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.Log.md-meta.xml similarity index 100% rename from nebula-logger/main/log-management/customMetadata/LoggerHandlerConfiguration.Log.md-meta.xml rename to nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.Log.md-meta.xml diff --git a/nebula-logger/main/log-management/customMetadata/LoggerHandlerConfiguration.LogEntry.md-meta.xml b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntry.md-meta.xml similarity index 100% rename from nebula-logger/main/log-management/customMetadata/LoggerHandlerConfiguration.LogEntry.md-meta.xml rename to nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntry.md-meta.xml diff --git a/nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml similarity index 100% rename from nebula-logger/main/log-management/layouts/LoggerHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml rename to nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/LoggerHandlerConfiguration__mdt.object-meta.xml b/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/LoggerHandlerConfiguration__mdt.object-meta.xml deleted file mode 100644 index 3570a901e..000000000 --- a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/LoggerHandlerConfiguration__mdt.object-meta.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - Used to configure additional Apex classes that should be executed by Logger after creating or updating records in Log__c or LogEntry__c - - Logger Handler Configurations - Public - diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/LoggerSObjectHandlerConfiguration__mdt.object-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/LoggerSObjectHandlerConfiguration__mdt.object-meta.xml new file mode 100644 index 000000000..7f7199aed --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/LoggerSObjectHandlerConfiguration__mdt.object-meta.xml @@ -0,0 +1,8 @@ + + + Used to configure additional Apex classes that should be executed by Logger after creating or updating records in Log__c or LogEntry__c + + Logger SObject Handler Configurations + Public + diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml similarity index 85% rename from nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml index 41d004629..b56e4a7e8 100644 --- a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml @@ -1,4 +1,4 @@ - + LoggerSObject__c The Logger object to process - Log__c or LogEntry__c @@ -8,7 +8,7 @@ EntityDefinition Logger Post Processors - LoggerPostProcessors + LoggerSObjectPostProcessors true MetadataRelationship true diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml similarity index 78% rename from nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml index bb9beafb3..8300f885b 100644 --- a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml @@ -1,10 +1,10 @@ - + PostProcessorApexClassName__c - The name of an Apex class that implements LoggerPostProcessor.Handler + The name of an Apex class that implements LoggerSObjectPostProcessor.Handler false SubscriberControlled - The name of an Apex class that implements LoggerPostProcessor.Handler + The name of an Apex class that implements LoggerSObjectPostProcessor.Handler 255 false diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerHandlerConfiguration__mdt/listViews/All.listView-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml diff --git a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls index 828904c0d..fad7f0c50 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls @@ -5,27 +5,27 @@ @isTest private class LogEntryHandler_Tests { - public class LogEntryPostProcessorTest implements LoggerPostProcessor { + public class LogEntryPostProcessorTest implements LoggerSObjectPostProcessor { public void execute(TriggerOperation triggerOperationType, List logs, Map oldLogsById) { if (triggerOperationType == TriggerOperation.BEFORE_INSERT) { for (LogEntry__c logEntry : (List) logs) { // The specific field changed doesn't really matter - we just want to ensure that whatever... - // ...logic implement in the instance of LoggerPostProcessor is executed + // ...logic implement in the instance of LoggerSObjectPostProcessor is executed logEntry.Message__c = 'Some String'; } } } } - private static LoggerHandlerConfiguration__mdt getMockConfiguration() { + private static LoggerSObjectHandlerConfiguration__mdt getMockConfiguration() { // Mocking entity deefinition fields on CMDT is not properly supported, so here's some goofy workarounds for mocking an instance EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :LogEntry__c.getSObjectType().getDescribe().getName()]; - LoggerHandlerConfiguration__mdt configuration = new LoggerHandlerConfiguration__mdt(); + LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); configurationUntyped.put('LoggerSObject__r', logEntityDefinition); - return (LoggerHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerHandlerConfiguration__mdt.class); + return (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); } @testSetup @@ -229,10 +229,10 @@ private class LogEntryHandler_Tests { static void it_should_run_apex_post_processor_when_configured() { String expectedMessage = 'Some String'; - LoggerHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); + LoggerSObjectHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); logHandlerConfiguration.PostProcessorApexClassName__c = LogEntryPostProcessorTest.class.getName(); - Map configurationsBySObjectType = new Map{ + Map configurationsBySObjectType = new Map{ Schema.LogEntry__c.SObjectType => logHandlerConfiguration }; @@ -241,7 +241,7 @@ private class LogEntryHandler_Tests { Test.startTest(); // Use the mock configurations - LoggerHandler.configurationsBySObjectType = configurationsBySObjectType; + LoggerSObjectHandler.configurationsBySObjectType = configurationsBySObjectType; LogEntry__c logEntry = new LogEntry__c(Log__c = log.Id, Message__c = 'qwerty'); insert logEntry; diff --git a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls index a2cd9bd4a..9c1565c27 100644 --- a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls @@ -11,27 +11,27 @@ private class LogHandler_Tests { private static final String FIRST_STATUS = Schema.Log__c.Status__c.getDescribe().getPicklistValues().get(0).getValue(); private static final String SECOND_STATUS = Schema.Log__c.Status__c.getDescribe().getPicklistValues().get(1).getValue(); - public class LogPostProcessorTest implements LoggerPostProcessor { + public class LogPostProcessorTest implements LoggerSObjectPostProcessor { public void execute(TriggerOperation triggerOperationType, List logs, Map oldLogsById) { if (triggerOperationType == TriggerOperation.BEFORE_INSERT) { for (Log__c log : (List) logs) { // The specific field changed doesn't really matter - we just want to ensure that whatever... - // ...logic implement in the instance of LoggerPostProcessor is executed + // ...logic implement in the instance of LoggerSObjectPostProcessor is executed log.ProfileName__c = 'Some String'; } } } } - private static LoggerHandlerConfiguration__mdt getMockConfiguration() { + private static LoggerSObjectHandlerConfiguration__mdt getMockConfiguration() { // Mocking entity deefinition fields on CMDT is not properly supported, so here's some goofy workarounds for mocking an instance EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :Log__c.getSObjectType().getDescribe().getName()]; - LoggerHandlerConfiguration__mdt configuration = new LoggerHandlerConfiguration__mdt(); + LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); configurationUntyped.put('LoggerSObject__r', logEntityDefinition); - return (LoggerHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerHandlerConfiguration__mdt.class); + return (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); } @testSetup @@ -429,17 +429,17 @@ private class LogHandler_Tests { static void it_should_run_apex_post_processor_when_configured() { String expectedProfileName = 'Some String'; - LoggerHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); + LoggerSObjectHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); logHandlerConfiguration.PostProcessorApexClassName__c = LogPostProcessorTest.class.getName(); - Map configurationsBySObjectType = new Map{ + Map configurationsBySObjectType = new Map{ Schema.Log__c.SObjectType => logHandlerConfiguration }; Test.startTest(); // Use the mock configurations - LoggerHandler.configurationsBySObjectType = configurationsBySObjectType; + LoggerSObjectHandler.configurationsBySObjectType = configurationsBySObjectType; Log__c log = new Log__c(LoggedBy__c = UserInfo.getUserId(), TransactionId__c = '1234'); insert log; From e295a3aefdd44c3441507feaf7506bad89fce952 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 6 Jun 2021 10:04:48 -0700 Subject: [PATCH 10/82] Updated version to v4.5.0 --- package.json | 2 +- packages/managed-package/sfdx-project.json | 8 ++++---- sfdx-project.json | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index d87f71517..07554d085 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nebula-logger", - "version": "4.4.6", + "version": "4.5.0", "description": "Designed for Salesforce admins, developers & architects. A robust logger for Apex, Flow, Process Builder & Integrations.", "scripts": { "deploy": "npm run deploy:logger && npm run deploy:managedpackage && npm run deploy:extratests", diff --git a/packages/managed-package/sfdx-project.json b/packages/managed-package/sfdx-project.json index a4064b032..6d2670032 100644 --- a/packages/managed-package/sfdx-project.json +++ b/packages/managed-package/sfdx-project.json @@ -9,10 +9,10 @@ "default": true, "definitionFile": "config/project-scratch-def.json", "postInstallScript": "LoggerInstallHandler", - "versionName": "Configurable Default Save Method & New Epoch Timestamp Fields", - "versionNumber": "4.4.0.2", - "ancestorVersion": "4.3.0.3", - "versionDescription": "Includes new Logger Setting for the default save method, added new Epoch Timestamp fields and bugfixes", + "versionName": "Logger SObject Post-Processors", + "versionNumber": "4.5.0.0", + "ancestorVersion": "4.4.0.2", + "versionDescription": "Easily add your own automations for Log__c and LogEntry__c objects using Apex or Flow", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases" } ], diff --git a/sfdx-project.json b/sfdx-project.json index 8b4fbe7b6..00b92159f 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -8,9 +8,9 @@ "path": "nebula-logger", "default": true, "definitionFile": "config/project-scratch-def-with-experience-cloud.json", - "versionName": "New save method SYNCHRONOUS_DML", - "versionNumber": "4.4.6.0", - "versionDescription": "The new save method skips publishing platform events and instead immediately creates Log__c and LogEntry__c records. Use cautiously!", + "versionName": "Logger SObject Post-Processors", + "versionNumber": "4.5.0.0", + "versionDescription": "Easily add your own automations for Log__c and LogEntry__c objects using Apex or Flow", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases" } ], @@ -23,4 +23,4 @@ "Nebula Logger - Unlocked Package@4.4.5-0-log-batch-purger-bugfixes": "04t5Y0000027FIVQA2", "Nebula Logger - Unlocked Package@4.4.6-0-new-save-method-synchronous_dml": "04t5Y0000027FJdQAM" } -} \ No newline at end of file +} From 5ced29b43aac340d6ce8019b5a3bf7b2fc883d08 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 6 Jun 2021 10:04:59 -0700 Subject: [PATCH 11/82] Updated docs --- docs/index.md | 8 ++++++++ docs/log-management/LoggerSObjectHandler.md | 9 +++++++++ docs/log-management/LoggerSObjectPostProcessor.md | 15 +++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 docs/log-management/LoggerSObjectHandler.md create mode 100644 docs/log-management/LoggerSObjectPostProcessor.md diff --git a/docs/index.md b/docs/index.md index c8cad3759..f48c450a3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -56,6 +56,14 @@ Manages setting fields on `Log__c` before insert & before update Manages mass deleting `Log__c` records that have been selected by a user on a `Log__c` list view +### [LoggerSObjectHandler](log-management/LoggerSObjectHandler) + +Abstract class used by trigger handlers for shared logic + +### [LoggerSObjectPostProcessor](log-management/LoggerSObjectPostProcessor) + +Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` + ### [RelatedLogEntriesController](log-management/RelatedLogEntriesController) Controller class for the component RelatedLogEntries diff --git a/docs/log-management/LoggerSObjectHandler.md b/docs/log-management/LoggerSObjectHandler.md new file mode 100644 index 000000000..05e4e5d02 --- /dev/null +++ b/docs/log-management/LoggerSObjectHandler.md @@ -0,0 +1,9 @@ +--- +layout: default +--- + +## LoggerSObjectHandler class + +Abstract class used by trigger handlers for shared logic + +--- diff --git a/docs/log-management/LoggerSObjectPostProcessor.md b/docs/log-management/LoggerSObjectPostProcessor.md new file mode 100644 index 000000000..f55c8292d --- /dev/null +++ b/docs/log-management/LoggerSObjectPostProcessor.md @@ -0,0 +1,15 @@ +--- +layout: default +--- + +## LoggerSObjectPostProcessor interface + +Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` + +--- + +### Methods + +#### `execute(TriggerOperation triggerOperationType, List loggerRecords, Map oldLoggerRecordsById)` → `void` + +--- From 1a4f46f5e062dd06f257e146e7d469939769bec8 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 6 Jun 2021 23:57:49 -0700 Subject: [PATCH 12/82] Added IsEnabled__c flag to handler config CMDT --- content/btn-view-documentation.png | Bin 25094 -> 20568 bytes docs/log-management/LogEntryEventHandler.md | 14 ++++++ docs/log-management/LogEntryHandler.md | 14 ++++++ docs/log-management/LogHandler.md | 14 ++++++ docs/log-management/LoggerSObjectHandler.md | 24 ++++++++++ .../classes/LogEntryEventHandler.cls | 12 +++++ .../classes/LogEntryHandler.cls | 12 +++++ .../log-management/classes/LogHandler.cls | 12 +++++ .../classes/LoggerSObjectHandler.cls | 45 ++++++++++++++---- ...iguration.LogEntryEventHandler.md-meta.xml | 13 +++++ ...Configuration.LogEntryHandler.md-meta.xml} | 2 +- ...ndlerConfiguration.LogHandler.md-meta.xml} | 2 +- ...ndler Configuration Layout.layout-meta.xml | 6 ++- .../fields/IsEnabled__c.field-meta.xml | 11 +++++ ...stProcessorApexClassName__c.field-meta.xml | 6 +-- ...PostProcessorFlowApiName__c.field-meta.xml | 4 +- .../listViews/All.listView-meta.xml | 1 + ...sing_not_supported.validationRule-meta.xml | 15 ++++++ .../classes/LogEntryEventHandler_Tests.cls | 7 +++ .../classes/LogEntryHandler_Tests.cls | 9 +++- .../classes/LogHandler_Tests.cls | 9 +++- 21 files changed, 214 insertions(+), 18 deletions(-) create mode 100644 nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryEventHandler.md-meta.xml rename nebula-logger/main/log-management/customMetadata/{LoggerSObjectHandlerConfiguration.LogEntry.md-meta.xml => LoggerSObjectHandlerConfiguration.LogEntryHandler.md-meta.xml} (89%) rename nebula-logger/main/log-management/customMetadata/{LoggerSObjectHandlerConfiguration.Log.md-meta.xml => LoggerSObjectHandlerConfiguration.LogHandler.md-meta.xml} (90%) create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/IsEnabled__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_Processing_not_supported.validationRule-meta.xml diff --git a/content/btn-view-documentation.png b/content/btn-view-documentation.png index 4a45d26950825aea0b0f141c0bec94c5430287cf..475dd95a2d5e786dad3ae359c7fa7f1f092e6d26 100644 GIT binary patch literal 20568 zcmeHP2~bs47(VZz4~1b-38Y*wO9hdp#ljWkLBJ4*3jf22t-QUPx-i-4ee!C2Ml```Yd9YWs<6 zp`*`F2S@I=OD}iI%*k2zb=Lai>67O4xUuxi-@dh*Po&&e`Rh(k(alyz3_lY*xFW{q zh?i#ig)EOqHgUxlAHJgdJfrfjgUeUfE`Ir|n<=&Dhi`RxOH&_EF=EGau63Havpez@ z{W925SCs3#rB{%{+%@&tw~Nlie;Mj%Kl;^qvr7LsIWuNY*{K9KUD39l6M6-?L~j3h zKxNVK53+RAcIlF~JjmFVzIW}fBQFl=8SUTGGjq+vpstb8nHP3v$2=caxzI_Ud1FF$ z=%A>spY^f-W_-qP^~dz(_vf9fD9g=p`P3%O?dqf6HtEIV3TIxu{=?pDBUKO1AKh@N z?((LizYnfjxyp5fTC*=L>-MTawW^Jyj^0`4&<4@aY_l?tU8ny4w z5#jw)z0b{U(D?dx`95_0p_;my!!-vUew07vNdMPoC#*h|am7>G7EMfOPyo~8XX~N- zb<#}t1;JAnG3GN6mnu2WFG-rTO$-SOw7sdZ)pU3FtV!2NQ|^g@(TUpl`SWAnPh{GJ z*qMp3vpg2ZCC>2(3JHsdN^^8$%!7pljGvOMQaOa*-J_C-WboT~O_Rsp2VZGUC4|}F=3So=uDijbNV2|{Soh-k{7U^!W zv+*yeRLHF9L2hj90DIvc;Q_1l!13$%*pdTPOpP)CnN@)BfHivnF^X7Kqh=LlfHiNG z&SmtYReG0U{!*3nd$Yx5a@!2SOasWk)lmRj_)BSbN9kcnIY#YipPc1V zWHkOQz*A7#?{-&s=E#1i~3 z-l~_!d>=TVK?@oH`ra$AH1Xp3$_S5d;0HVc^hpNhAcxj5&&%ceqyy3LE&58}X=x2| zzz2YJ>MP{}k94RoFkSuQHCf-MPfm21irtt-DQ_vwkm6HS0j3|iEp037Y9fo@W5 zSS9m9<}7%-AE7t3R1VMtN`s|`s#*TDzBJWDhb#y=e4VY-0YruG^pmp-T4Moa5!pwj zkW%hNsm?By{9`PT{lpjk0??S`V$P6Vn5X^VX`r7HkijE!E0ohMj!8E0c)_<*H3wBSn{jd4plV9gkS zjtE5PNctK>Z*E*u?1KIXR^rj#vdG*vw8hWl8kPjeFF=yPXbk}c9$$A69%zuEi54v~ zCXERXEglNg%y2A!@pUxt=tYcz3R$349UgC%F&PFKjWROvriT`C>E#n^(9e+Vn5XPd zw9wxeAlZiax0erefGz;?SzELum-OasZj1Iw*Uge)AsiVD8IR9oN~Q2tjZLP^h@%== zk!TAZA9ol75BN$@mIJho;KmvqPuKu@VW6M_t|1+efl~t;k88BZE~N%!gPuQj!HYJH z=Z!vq*B|_#57`c#pesrsdPw+})kY5OzZO4Sij*) R;hWGgBrrT+xBrave*j}8vEBdx literal 25094 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 } + /** + * @description Returns SObject Type that the handler is responsible for processing + * @return The instance of `SObjectType` + */ + public override SObjectType getSObjectType() { + return Schema.LogEntryEvent__e.SObjectType; + } + /** * @description Runs the trigger handler's logic for the `LogEntryEvent__e` platform event object */ public void execute() { + if (this.configuration.IsEnabled__c == false) { + return; + } + if (this.logEntryEvents.isEmpty() == false) { this.upsertLogs(); this.insertLogEntries(); diff --git a/nebula-logger/main/log-management/classes/LogEntryHandler.cls b/nebula-logger/main/log-management/classes/LogEntryHandler.cls index a974aa5cf..7dce6b3c8 100644 --- a/nebula-logger/main/log-management/classes/LogEntryHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryHandler.cls @@ -22,10 +22,22 @@ public without sharing class LogEntryHandler extends LoggerSObjectHandler { this.triggerOperationType = Trigger.operationType; } + /** + * @description Returns SObject Type that the handler is responsible for processing + * @return The instance of `SObjectType` + */ + public override SObjectType getSObjectType() { + return Schema.LogEntry__c.SObjectType; + } + /** * @description Runs the trigger handler's logic for the `LogEntry__c` custom object */ public void execute() { + if (this.configuration.IsEnabled__c == false) { + return; + } + switch on this.triggerOperationType { when BEFORE_INSERT { this.setCheckboxFields(); diff --git a/nebula-logger/main/log-management/classes/LogHandler.cls b/nebula-logger/main/log-management/classes/LogHandler.cls index f6ac02b02..5b51298a7 100644 --- a/nebula-logger/main/log-management/classes/LogHandler.cls +++ b/nebula-logger/main/log-management/classes/LogHandler.cls @@ -38,10 +38,22 @@ public without sharing class LogHandler extends LoggerSObjectHandler { this.triggerOperationType = Trigger.operationType; } + /** + * @description Returns SObject Type that the handler is responsible for processing + * @return The instance of `SObjectType` + */ + public override SObjectType getSObjectType() { + return Schema.Log__c.SObjectType; + } + /** * @description Runs the trigger handler's logic for the `Log__c` custom object */ public void execute() { + if (this.configuration.IsEnabled__c == false) { + return; + } + switch on this.triggerOperationType { when BEFORE_INSERT { this.setOrgReleaseCycle(); diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index ca1065d32..3ca729dc1 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -9,28 +9,57 @@ */ public abstract class LoggerSObjectHandler { @testVisible - private static Map configurationsbySObjectType = loadConfigurations(); + private static Map configurationsBySObjectType = loadConfigurations(); private static Map loadConfigurations() { - Map configsbySObjectType = new Map(); + Map configsBySObjectType = new Map(); for (LoggerSObjectHandlerConfiguration__mdt config : LoggerSObjectHandlerConfiguration__mdt.getAll().values()) { // Schema.getGlobalDescribe() is the worst, so don't use it - SObjectType sobjectType = ((SObject) Type.forName(config.LoggerSObject__r.DeveloperName + '__c').newInstance()).getSObjectType(); + SObjectType sobjectType = ((SObject) Type.forName(config.LoggerSObject__r.QualifiedApiName + '__c').newInstance()).getSObjectType(); - configsbySObjectType.put(sobjectType, config); + configsBySObjectType.put(sobjectType, config); } - return configsbySObjectType; + return configsBySObjectType; } + protected LoggerSObjectHandlerConfiguration__mdt configuration; + + public LoggerSObjectHandler() { + this.configuration = getConfiguration(this.getSObjectType()); + } + + /** + * @description Returns the SObject Type that the handler is responsible for processing + * @return The instance of `SObjectType` + */ + public abstract SObjectType getSObjectType(); + protected void executePostProcessors(List loggerRecords, Map oldLoggerRecordsById) { if (loggerRecords == null) { return; } - LoggerSObjectHandlerConfiguration__mdt loggerHandlerConfiguration = configurationsbySObjectType.get(loggerRecords.getSObjectType()); + this.executePostProcessorApexClass(this.configuration?.PostProcessorApexClassName__c, loggerRecords, oldLoggerRecordsById); + this.executePostProcessorFlow(this.configuration?.PostProcessorFlowApiName__c, loggerRecords, oldLoggerRecordsById); + } + + private LoggerSObjectHandlerConfiguration__mdt getConfiguration(SObjectType sobjectType) { + LoggerSObjectHandlerConfiguration__mdt configuration = configurationsBySObjectType.get(sobjectType); + + if (configuration == null || Test.isRunningTest()) { + configuration = new LoggerSObjectHandlerConfiguration__mdt(); + + // Setting entity definition fields on CMDT is not properly supported, so here's some goofy workarounds for handling it + // TODO cache entity definition query for Log__c, LogEntry__c and LogEntryEvent__e + EntityDefinition sobjectEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :sobjectType.getDescribe().getName()]; + Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); + configurationUntyped.put('LoggerSObject__r', sobjectEntityDefinition); + + configuration = (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); + configuration.IsEnabled__c = true; + } - this.executePostProcessorApexClass(loggerHandlerConfiguration?.PostProcessorApexClassName__c, loggerRecords, oldLoggerRecordsById); - this.executePostProcessorFlow(loggerHandlerConfiguration?.PostProcessorFlowApiName__c, loggerRecords, oldLoggerRecordsById); + return configuration; } private void executePostProcessorApexClass(String apexClassName, List loggerRecords, Map oldLoggerRecordsById) { diff --git a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryEventHandler.md-meta.xml b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryEventHandler.md-meta.xml new file mode 100644 index 000000000..4e8127dcb --- /dev/null +++ b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryEventHandler.md-meta.xml @@ -0,0 +1,13 @@ + + + + false + + LoggerSObject__c + LogEntryEvent__e + + diff --git a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntry.md-meta.xml b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryHandler.md-meta.xml similarity index 89% rename from nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntry.md-meta.xml rename to nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryHandler.md-meta.xml index c80e3d49f..825fa1236 100644 --- a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntry.md-meta.xml +++ b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryHandler.md-meta.xml @@ -4,7 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" > - + false LoggerSObject__c diff --git a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.Log.md-meta.xml b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogHandler.md-meta.xml similarity index 90% rename from nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.Log.md-meta.xml rename to nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogHandler.md-meta.xml index fbad45c23..b1dc16bff 100644 --- a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.Log.md-meta.xml +++ b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogHandler.md-meta.xml @@ -4,7 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" > - + false LoggerSObject__c diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml index 1b220462a..398798de2 100644 --- a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml @@ -20,6 +20,10 @@ Required LoggerSObject__c + + Edit + IsEnabled__c + @@ -27,7 +31,7 @@ true true true - + Edit diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/IsEnabled__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/IsEnabled__c.field-meta.xml new file mode 100644 index 000000000..2825706a3 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/IsEnabled__c.field-meta.xml @@ -0,0 +1,11 @@ + + + IsEnabled__c + true + Controls if the SObject's trigger handler class should execute. This is useful for temporary disabling the logger's trigger handlers, but should typically be enabled. + false + SubscriberControlled + Controls if the SObject's trigger handler class should execute. This is useful for temporary disabling the logger's trigger handlers, but should typically be enabled. + + Checkbox + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml index 8300f885b..5ae97f50c 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml @@ -1,11 +1,11 @@ PostProcessorApexClassName__c - The name of an Apex class that implements LoggerSObjectPostProcessor.Handler + The name of an Apex class that implements the interface LoggerSObjectPostProcessor false SubscriberControlled - The name of an Apex class that implements LoggerSObjectPostProcessor.Handler - + The name of an Apex class that implements the interface LoggerSObjectPostProcessor + 255 false Text diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml index 9c2185c06..9bf44a13f 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml @@ -1,4 +1,4 @@ - + PostProcessorFlowApiName__c The API name of a Flow that suppports these inputs: @@ -7,7 +7,7 @@ - oldRecords: record collection variable false SubscriberControlled - + 255 false Text diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml index b593e3a58..47c451f92 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml @@ -4,6 +4,7 @@ MasterLabel DeveloperName LoggerSObject__c + IsEnabled__c PostProcessorApexClassName__c PostProcessorFlowApiName__c Everything diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_Processing_not_supported.validationRule-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_Processing_not_supported.validationRule-meta.xml new file mode 100644 index 000000000..917acea15 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_Processing_not_supported.validationRule-meta.xml @@ -0,0 +1,15 @@ + + + Post_Processing_not_supported + true + AND( + LoggerSObject__r.DeveloperName != 'Log', + LoggerSObject__r.DeveloperName != 'LogEntry', + OR( + NOT(ISBLANK(PostProcessorApexClassName__c)), + NOT(ISBLANK(PostProcessorFlowApiName__c)) + ) +) + LoggerSObject__c + Post-processing is not supported for this SObject + diff --git a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls index 58ae3e4c5..3ad3be6b3 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls @@ -262,6 +262,13 @@ private class LogEntryEventHandler_Tests { System.assertEquals(logEntryEvent.TriggerSObjectType__c, logEntry.TriggerSObjectType__c); } + @isTest + static void it_should_return_the_logEntryEvent_sobjectType() { + Test.startTest(); + System.assertEquals(Schema.LogEntryEvent__e.SObjectType, new LogEntryEventHandler().getSObjectType()); + Test.stopTest(); + } + @isTest static void it_should_gracefully_skip_execution_when_logEntryEvents_list_is_empty() { List logEntryEvents = new List(); diff --git a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls index fad7f0c50..66a5e9d55 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls @@ -18,7 +18,7 @@ private class LogEntryHandler_Tests { } private static LoggerSObjectHandlerConfiguration__mdt getMockConfiguration() { - // Mocking entity deefinition fields on CMDT is not properly supported, so here's some goofy workarounds for mocking an instance + // Setting entity definition fields on CMDT is not properly supported, so here's some goofy workarounds for handling it EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :LogEntry__c.getSObjectType().getDescribe().getName()]; LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); @@ -35,6 +35,13 @@ private class LogEntryHandler_Tests { Test.setCreatedDate(log.Id, System.now().addDays(-8)); } + @isTest + static void it_should_return_the_logEntry_sobjectType() { + Test.startTest(); + System.assertEquals(Schema.LogEntry__c.SObjectType, new LogEntryHandler().getSObjectType()); + Test.stopTest(); + } + @isTest static void it_should_save_log_entry_without_related_record_id() { Log__c log = [SELECT Id FROM Log__c LIMIT 1]; diff --git a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls index 9c1565c27..f64a6c04c 100644 --- a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls @@ -24,7 +24,7 @@ private class LogHandler_Tests { } private static LoggerSObjectHandlerConfiguration__mdt getMockConfiguration() { - // Mocking entity deefinition fields on CMDT is not properly supported, so here's some goofy workarounds for mocking an instance + // Setting entity definition fields on CMDT is not properly supported, so here's some goofy workarounds for handling it EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :Log__c.getSObjectType().getDescribe().getName()]; LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); @@ -46,6 +46,13 @@ private class LogHandler_Tests { LogHandler.logStatusByName = logStatusByName; } + @isTest + static void it_should_return_the_log_sobjectType() { + Test.startTest(); + System.assertEquals(Schema.Log__c.SObjectType, new LogHandler().getSObjectType()); + Test.stopTest(); + } + @isTest static void it_should_set_org_release_cycle_on_insert() { Set previewInstances = new Set{ From 6739628a15bf2125537bce0ae13b9f7aa366480c Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 7 Jun 2021 00:03:58 -0700 Subject: [PATCH 13/82] Updated relationship name on CMDT --- .../fields/LoggerSObject__c.field-meta.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml index b56e4a7e8..56cb55bc7 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml @@ -1,14 +1,14 @@ LoggerSObject__c - The Logger object to process - Log__c or LogEntry__c + The Logger object to process - LogEntryEvent__e, Log__c or LogEntry__c false SubscriberControlled - The Logger object to process - Log__c or LogEntry__c + The Logger object to process - LogEntryEvent__e, Log__c or LogEntry__c EntityDefinition - Logger Post Processors - LoggerSObjectPostProcessors + Logger SObject Handler Configurations + LoggerSObjectHandlerConfigurations true MetadataRelationship true From 76c5f8ebe28baf7b41877d3df6217b3cebfb459f Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 7 Jun 2021 11:17:35 -0700 Subject: [PATCH 14/82] Renamed config.LoggerSObject__c field to SObjectType__c --- .../classes/LoggerSObjectHandler.cls | 5 ++-- ...iguration.LogEntryEventHandler.md-meta.xml | 2 +- ...rConfiguration.LogEntryHandler.md-meta.xml | 2 +- ...andlerConfiguration.LogHandler.md-meta.xml | 2 +- ...ndler Configuration Layout.layout-meta.xml | 10 +++---- ...meta.xml => SObjectType__c.field-meta.xml} | 10 +++---- .../listViews/All.listView-meta.xml | 2 +- ...sing_not_supported.validationRule-meta.xml | 8 ++--- .../classes/LogEntryHandler_Tests.cls | 2 +- .../classes/LogHandler_Tests.cls | 29 ++++++++++++++++++- 10 files changed, 49 insertions(+), 23 deletions(-) rename nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/{LoggerSObject__c.field-meta.xml => SObjectType__c.field-meta.xml} (57%) diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index 3ca729dc1..3a06643f2 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -15,7 +15,7 @@ Map configsBySObjectType = new Map(); for (LoggerSObjectHandlerConfiguration__mdt config : LoggerSObjectHandlerConfiguration__mdt.getAll().values()) { // Schema.getGlobalDescribe() is the worst, so don't use it - SObjectType sobjectType = ((SObject) Type.forName(config.LoggerSObject__r.QualifiedApiName + '__c').newInstance()).getSObjectType(); + SObjectType sobjectType = ((SObject) Type.forName(config.SObjectType__r.QualifiedApiName + '__c').newInstance()).getSObjectType(); configsBySObjectType.put(sobjectType, config); } @@ -51,9 +51,10 @@ // Setting entity definition fields on CMDT is not properly supported, so here's some goofy workarounds for handling it // TODO cache entity definition query for Log__c, LogEntry__c and LogEntryEvent__e + String entityDefinitionRelationshipName = Schema.LoggerSObjectHandlerConfiguration__mdt.SObjectType__c.getDescribe().getName().replace('__c', '__r'); EntityDefinition sobjectEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :sobjectType.getDescribe().getName()]; Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); - configurationUntyped.put('LoggerSObject__r', sobjectEntityDefinition); + configurationUntyped.put(entityDefinitionRelationshipName, sobjectEntityDefinition); configuration = (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); configuration.IsEnabled__c = true; diff --git a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryEventHandler.md-meta.xml b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryEventHandler.md-meta.xml index 4e8127dcb..fb1b68276 100644 --- a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryEventHandler.md-meta.xml +++ b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryEventHandler.md-meta.xml @@ -7,7 +7,7 @@ false - LoggerSObject__c + SObjectType__c LogEntryEvent__e diff --git a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryHandler.md-meta.xml b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryHandler.md-meta.xml index 825fa1236..1fa2d72d0 100644 --- a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryHandler.md-meta.xml +++ b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryHandler.md-meta.xml @@ -7,7 +7,7 @@ false - LoggerSObject__c + SObjectType__c LogEntry__c diff --git a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogHandler.md-meta.xml b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogHandler.md-meta.xml index b1dc16bff..77c2ad016 100644 --- a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogHandler.md-meta.xml +++ b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogHandler.md-meta.xml @@ -7,7 +7,7 @@ false - LoggerSObject__c + SObjectType__c Log__c diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml index 398798de2..d9bca69b5 100644 --- a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml @@ -1,4 +1,4 @@ - + false @@ -18,7 +18,7 @@ Required - LoggerSObject__c + SObjectType__c Edit @@ -78,9 +78,9 @@ false false - - - + + + false diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/SObjectType__c.field-meta.xml similarity index 57% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/SObjectType__c.field-meta.xml index 56cb55bc7..66a53f722 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/LoggerSObject__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/SObjectType__c.field-meta.xml @@ -1,15 +1,13 @@ - LoggerSObject__c - The Logger object to process - LogEntryEvent__e, Log__c or LogEntry__c + SObjectType__c false SubscriberControlled - The Logger object to process - LogEntryEvent__e, Log__c or LogEntry__c - + EntityDefinition Logger SObject Handler Configurations LoggerSObjectHandlerConfigurations - true + false MetadataRelationship - true + false diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml index 47c451f92..b74ff52dd 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml @@ -3,7 +3,7 @@ All MasterLabel DeveloperName - LoggerSObject__c + SObjectType__c IsEnabled__c PostProcessorApexClassName__c PostProcessorFlowApiName__c diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_Processing_not_supported.validationRule-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_Processing_not_supported.validationRule-meta.xml index 917acea15..a3992e7bf 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_Processing_not_supported.validationRule-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_Processing_not_supported.validationRule-meta.xml @@ -1,15 +1,15 @@ - + Post_Processing_not_supported true AND( - LoggerSObject__r.DeveloperName != 'Log', - LoggerSObject__r.DeveloperName != 'LogEntry', + SObjectType__r.DeveloperName != 'Log', + SObjectType__r.DeveloperName != 'LogEntry', OR( NOT(ISBLANK(PostProcessorApexClassName__c)), NOT(ISBLANK(PostProcessorFlowApiName__c)) ) ) - LoggerSObject__c + SObjectType__c Post-processing is not supported for this SObject diff --git a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls index 66a5e9d55..5c510c4ac 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls @@ -23,7 +23,7 @@ private class LogEntryHandler_Tests { LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); - configurationUntyped.put('LoggerSObject__r', logEntityDefinition); + configurationUntyped.put('SObjectType__r', logEntityDefinition); return (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); } diff --git a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls index f64a6c04c..11cef7f0e 100644 --- a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls @@ -29,7 +29,7 @@ private class LogHandler_Tests { LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); - configurationUntyped.put('LoggerSObject__r', logEntityDefinition); + configurationUntyped.put('SObjectType__r', logEntityDefinition); return (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); } @@ -53,6 +53,33 @@ private class LogHandler_Tests { Test.stopTest(); } + @isTest + static void it_should_not_run_handler_when_configured() { + LoggerSObjectHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); + logHandlerConfiguration.IsEnabled__c = false; + + Map configurationsBySObjectType = new Map{ + Schema.Log__c.SObjectType => logHandlerConfiguration + }; + + LogStatus__mdt closedLogStatus = [SELECT Id, MasterLabel FROM LogStatus__mdt WHERE IsActive__c = true AND IsClosed__c = true LIMIT 1]; + + Test.startTest(); + + // Use the mock configurations + LoggerSObjectHandler.configurationsBySObjectType = configurationsBySObjectType; + + Log__c log = new Log__c(LoggedBy__c = UserInfo.getUserId(), Status__c = closedLogStatus.MasterLabel, TransactionId__c = '1234'); + insert log; + + Test.stopTest(); + + // Assumption: if the handler had executed, then log.IsClosed__c should have been auto-set to true... + // ...so if it's still false, it indicates that the handler did not execute + log = [SELECT Id, IsClosed__c FROM Log__c WHERE Id = :log.Id]; + System.assertEquals(false, log.IsClosed__c); + } + @isTest static void it_should_set_org_release_cycle_on_insert() { Set previewInstances = new Set{ From 492ab3e249a12bcf3d3fe80f6d2f4a3c2c5823a8 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 7 Jun 2021 11:26:06 -0700 Subject: [PATCH 15/82] Updated screenshot of handler config --- content/logger-handler-configuration.png | Bin 101240 -> 102252 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/content/logger-handler-configuration.png b/content/logger-handler-configuration.png index 8ed0aa27d74b9f4b794976d6deb16f5cd5827de0..07fc97df1ae2ae27c1e0c89db429bbba001639ce 100644 GIT binary patch literal 102252 zcmb5VRajh6x-FUzAh^2*C%C(W;O-P&xVt+E8a%i|aCeu&CAho0yZfzlpYBedy&vv@ z^-$lewbry>#u)#s5Cu7LL^wRSckkXIN=k?*y?Y1!<=s07c^C+AONna~$GdlLZ;~QH zDsGF%>9AfZGY@xX$4@EA$M~>X^PNyVp-)O-n`)TWw2jkHv}Tyr)<;TpvxH@Zb+4T? z*(wUOi!}G4>I?DwRwPD1sv1+4r`C2yTNVV3Ps!xu>sNJ|PDxFUXH9!);Qxn}y)@Kb z1Lnw2Fn<5JplM0bD*tZy(TM=74k?84@2lrm5G37SPrw)`O!Y$~u;O?>>0PDp_$G6< zj-av)_Mi`6dX-&=YTtwt%zRm+`|Aym(FnQ~4W*@}_4TtRHBBq0dQ3k!cO06)jp}r` zxVR4w51M85ndPgde_pFo*?*-}wS*h$;_*$9(&xbGN;WVhlGs~mp?ZXf?kdPW2G-<( z`(UtU3ggA8``^O^e-OF*%*eRbff z*Lc%C=h`vMsVn;L4twnTY#J)G8b)nu1{%$jbxwZzc_quF#3yS2f!IiaN>eP>va%a? z)D*o0NWtlH4V^J+I%~fs&GO~aEjUu2D#^V+{pow`CA+PprzBE_X`sE0t85rwV7DQh zg*h@!FX3(j5gpuP2qeV&V9>zaGT%5933#{UaHjDh2GX(>##3PZKK+PI(`j+>ez}=b z^A}jRm@HIaPp@E6?Q9K+6HAKYH!Xgz!@6be=uVA$T z+FN!UBV;v^0b=Gi{Mmr?dvj|I$42qB!8wVR2h1Fq=ZU6S$H{na=Rd10lJ@13f{uoM zmF5lf)|bRUuqkor+qI1tx3R&hbUD?g8_FipKziUB9f92 zyG7RO{X~yN$xgf}#D&u@}!_XjJGNqLb_}quJO(z&@Q8H-BK1t^<%Y<*2jdxk}qo3LP)OSC?CI@7Bzbhx)^z39_D zJy@lEZ@F1exAL&lxz$(t^(3qynHm$k64|K=$A5wWIif5nB(nre;8%vkp|iWYU2
*-*)kov9xo?nCb|yvCg!HfW_sV6hplBM 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⋙2diZ>i+lslcLs94n;gr=l)e)e?ph%N} z9g``=V6A6|(OeRwJ~g4#Owtq*u!uv5{EMH1ju_Je)dkpQRPL(n4bXAGa!yoGma>|4 z1M(a@>RX`u)``-uR&%OFA1%cI_*mqwQ6tjEYKiO&8qUEVk>!?G+U=;CYY zTVUy^Ztn{k^@?TiMW>{ihE~01x}1e}0hmMvo%IxTR}IZ=YB5$NrjpV2>@ZToO2dbK z=B-Mn{q5aeDxaftE-@Y;6Mkz8_rJq%2Js^X<-<$}V@Tm7hOKI{VAf*W=56LK@!U>3 zijE!*7QZa09Wqr5EG}RPU0GlqJtTkCwtB4*T;@O(sw_p7M%C%rHVpVTuyAN4VX>((F1e0`-1R{;ChOa*@zlgG$I^$ zSjHtQ%!h()u-*{4FRGA=Sj-pFn1~IkR5+$*`UOnpU@E+FTfNAZK(G>n**W|uT=s_A z0IYsTmZ9zB4rWAFQRLjXvx(cn9A1_SMa+%M_^NLpQ-%D@?W>OlT0Zp`SyR=qtf27g z>uNC65W6_zbIuLAKRo_+bYI ze9fd4bAeEu$fBW5sSCQ4h$dhvPExsLkiR7@VLX)4k%RKTuWIP*5Z4{?IQkPoV?+x| zf2%=bq_fNR3WEu{8k;f7hM3BF$ZWFkcqkIz>}leK6~ioqR+!a6S6r_N{K2mcCU(U+ z_WI@!>kKoLuF^b$1+~P~i%bcf@O1p@1_nG144BP!M|lr`o=`>3@3%Lo?T&j@!`RO&s9k|v6< zIOj3N60Ee9l(K*u*9IM|+f7hUn1NVXPF8y?0Y%C)yud^orO#TJImAhVo;u=s-eZp#&MQ# z5PdCSCAn@#QzVs7LtwSVtk;#MlC?K7tEJ9OwZ}_MSMZfo);IVk=|Y}LFzv7!%UJ5J zX10psA1=vp*vz`M)s3p_E*G}YPcR(C$%7_74zs|*3vR-4P9I0m`#UGgYQp9(?D<5I z3r29wb&ahaj4+V$O;d!!2DoFf#3mT{Uw;zoFj%8;o38 z<`Q=nv>iqB?E0b=^Vd8!IZR?30%1PV?P_R>Fd8N^%vMy-lI6iX6SwOE7=H~jGAHEh zEKFAZ-BzDL(#b+{Rt&u&lmPUljm)){$J*Eay860vL*@ewJnKd#9He4ti9BNu6b{U1 za51796{7Kej7=ud)J59emXda+3RMMeY6JB7f|w?vafJx|@ASHjwM}u2lnKWNGpFf| zwSKN%VZuR^VOWU^rdv>pv_Ws-!`uxGW2-S0OuJK_VV|SjP~W9iC<@P=_1(65?ywM( zm9kvuOAIjE=gCa@SK#5o><(ty$)t)*hjQACMXs!x#ujzclmqkC9Gk_3*$ji7Q#!(( z!r2;IBK{UlcJ+*_9M{UBdPCC)tLcMS7S3VCE_kxs2M~89vu!0g*0oi*hXjQWWeXqP zRM!N<1gsJAal;a0)K-?b;R>OqrM#ZqHTA)U=609{^NfV>0a(lIV4eqQ8(=VAWSO}! zY=~!h;*(+MQa0eg6vc!pg)sMMhTa3?4!2|6;S!c;75XvgcHpr#hoa~fo4|02@Hn8Q zCj-i1)@BFK*Z_lIUk}H8jR4&m30TA-MB$~+4KH!S^kUP_0IZNl#1~0LBv%q@!PDZEv za5BdUdM63W=z+P-7{Dkfq;^L!sAMcLdSD)`VRo_sSbGwfCyg0gz!T5)Y=OlWU@_+F z2VJVawH-P~Lt1Q6mcqtnG*lEj>w}mBB^8+hiwkCKaBHoY*|!BQl{;dfL4ni4A`^Eo z6F}Q53kJ^E=4}pyFq*rN!4RANu=uM^Tf_A~t046$oE|_4F4J^7~>ZZEzz=uZ- z%&GFVU@QY&@+t65B#Tks5Daq_L;b}VK4mnv=Q3qSvkp`x2BXWpKamOon)!|Je__3i zrv5A9^Mm{S{! zwHtS0=x#~awL#h!tvJReD=Y<@xXsgyL7i1oa+X>FZe%0N-N}7dnfsXNX=+uH;+LG8 zZDG!*&Eb?E0ZT?M4k^fn+k}VJ#L}YcwTX&_4!gdoO3GR>d$+PQhey`eX*1OQmN|f9C?Yl%V{AK^B_A`ifG3TGGUJbfuLO>( zD1H-Apx>n(bZ*EU_R`}CCr0pe zZud5$d2Fh-Bv|shvOLF5e=FN#@6cGXt;Q0!y{0k9)5-T>(3DcIlp=hH7)2r27Eukr zlTC)1?lRZ5EL5-9&#Ajm`OF}9M}4cexs7+oJnkMmzKykkgr=eKYb(pM!~6=W7W1Rr zGgmV0RdIhMK_i7gy*z9{PB8IjtC0lJ~3J1x&9yd_WE? z&TH9~^B`#D7#X?|mz8X=hR?$i7rs;Aw87(BQ&S&L;IwA;7!5j@ux<7Pnwa#) zJ=x1)swqiO4`DjQyuG;pCa#mAXRw&`Kh*fuw9D{$C{iAs$HtQJ!8i^h?~#LGeu&27 zb~6iM0rMY0;=u=WXdnZ+3ewJU>rqQnBs~o_ESbKTD@+_7`{_L%Mqw)(7nJf zYNL8X4+Eo&!)jui2RsxvP8FbEf=a@4f9}4AF8p4YW-ym?Rl>%3rps36Z}kO22?ecp z)p5SFGncka-T5d9g|5rlO|(7?H|ITvnvZpct= zP<$_RnvA-2HU2JksafKn!Azasm{R8j&8z_Cb6>Md89JUv^__JCxzBMxhAo z#-WX82Sd?1e_L8E!pt8Q7esjCV6FZoFcTrJu)tlz6UarK4xek&d|cK-EP2laW8Df1=j=f z8F-GWNh!~V0Nvw;T4-%Co*5Y$k=cND&=T{$gga$X;V?c)MNu|p*~Zk>Iu=!WD#kaMv)h3@vi$^&->?6ug*`EZ-7?{!L9GUkh}CFdo3FyRALS#{!Y%&9RycrMY(K zEJCcy-SM`E$fo*>WKqmF!0=CWr-H3SD6ohXH)&}+Nk zUG$2A4uzcuPB*A98@{utE?{IX>wM!^W@(IJ<=@cK4*eqz1|lqgF}N~I8PNfLO*pc$ z{b!c$Iv{rxR-*CvQG*L$!IKtLl5Z|SN8_}bH`F$E=b)#~FrsWMft5M*gYaDRqM&GZ zQ&SO|aoyDtuB~t73u7*>S(zOK9N&QRA+pITC zP;+IOao<=Yw<#=7(6C}R%rgCLm^Bja#BA0dR^t9{JF}2tKg83q!{gr3*rsZQ$qgvY z1X?xbPcTPOyV+RP$q<^S8P2g|LK8*kT#u3M6?>XmnN=Mc z6D2U}yagH*+zZSqS|d@IMVU={rxhNu9@-sW5b{|R-?LiH9QAd$V~lBi;R6_8OAugX z>#~{Qr)&K!FnIHDNMbT#r4eQ)o z$_i#z%oR@HO^i3H1ZFR`LxumLCK)0DN(}B1=1jGX%oUf#xK&v3w#O3iWYsk%S_8?# zfV`|6yQQ%OCJiBO$gS(X6*I>cnI-y3=9x~ur3s-rvMhH8FTix;K3q+~y{xXPH+JVb zopL&c-igJ%f>s=XXQWMwquO5am}~x)NKHeFPUAylHlhj%cf@AK%&byY1{XM>6>rA$ z>M>NWSgTN5F&6?<1D4)x{YBYo0j>&4Uj4ev(#8*F2`*t;1{D}8stp%ru2sz5iraU< ze+TB-pexpphGku>{19=i~#G)yQn41m=c?kb*}ZTWtCBg@E| zw3HE9@W)0LTo1}Bnn>UfW4CPgHADSO#f< zyle|RFZfaD5y#i?)^n%j4#h62$c{s8Ar!sPYh*}+evX?8FS*CVD{AI9g(GD8*J!19g4 za0ayqCNnTzZ(_;*SgRCFEIT1I5ZnSuMf2fbXDePsyJ^I(P$H z%6GzNw)vWQQ2#x>5$;Ak6oaP6w|Ij*wWW}XNLZflKxhAOjH`7#G$d|o;U=qoXt8T& zQ!BSr9flDDW$0?`7F4BS@P(-_9EV9u83wd!P&0_3-y(*BHbFgyD%y@#;ga2IbXbh= zpkXZ?O(l=xC}2_@caUkCx>QhV%-Z3! zK~cw-Ts| zSX242yMV^ULsj+8i-37bELwva9bA+>UQ3iwVo^`1qOyp8nthloVlg#+^5f zMrlx9HZfRksKsKE4fO*P*bX8sUdnC6ln3n~h?1MRCV z5``%fG+U@G4x7nlHu!P$$F&BlVlqrIM-IS6N}x3olQGs6j6N{WbhF^LE4TaLj$v#H zMdDT1#pz@@S%3*luh_`a2))#t?v4GPL-H(|0F13IYg znSd3EM4J4Kp|-YtczpzsIaZs^<<2pgOuhU1=<8q0cUacfHo=T)Oho~Y!r->UgdiIR zU;+I>jL`WG$+up1@_-YE=JaudD}o>hf*=TjAP9muL{Svs%gz4zpVzFfYf%p}8wEMe zEQpIRRF0uBh*4iq8P8n6ibNu{HPyL!d5&ynf8Qo?h!SiLG}PCZ3@GcJhIPWNZ|YbA z2#3`)yu`V_1_NvqyR&i}met#Qf+&s};Lgc1+<)PS_1^YlN0eGk``AWEfQa`VaM=%^VKhWx4y20TizvDyq8jUmd$JousE394>a9`vS&Oy>#SBQsaHh* z5^N5HLZQN<;$D3B=d<30+P||YRLqjCRyDLlqVWN_4x?V&;=$kxY<*=^9b49IAP`)F zCb%WIy9W4G`Sj-95OwyZftj_q{jW->aVtMxCm)m&`f$s=WZ>(YCQg z)HLmO@P7N*J?HPiClKevh64x3FIsyMtTWmd);X|7$FQcGJS@Dc z;#^e$g-(Piwc83~xOVJJmVjk#Y`4nFyGzO)McZ8;w{k~3#+ z*5<|vZmhBk$Sx{%_XL$AQD769$3+8OMA~zD6@&i3zAH3s@sNHbY5E7g>fX``TtK$9 z%KJ*{fVNe)KM$XWsPF{tw##!PDIhKwjrM)FZiY-@pm`c534&^4EoWB2x;-`_^ON3U zSPu<0aJE(bd{FRY-J>edL^wQuzn?}L{l^R&Wgn|v)Km9h++wP}qEn2>F&5OQ7FP0v`046CTra^jGrijOt> z*Yom?izu>grTS5Ii_7tM;0vt3-JtuWWA{3&=~bMmRY$ul5h)8floZ~@_)7%$PpX85Y`~gdT z0XvKYiA56(?O}cjg?&=n7_~7>TGTy%&|(|M_=W~dLH)N$#}zI$RCe3~a~rcDlf5&c zF=9NNDqMRM%jPpfyHR>97KdI%F#Z@{RFMI!QU2I7tY$xhi9Do~>Gz=pycles^}O1f z`r;3E(O*@dgMGiZye|*HXvkav`mi!z1Qz@4mDN@9t~sBCThPSG*j0AgBzcqn+qhcr z#SNei*<}-^*j-Mo8qMYLNtB3geIXR*Y7=j&@*v-6O{Jc1Qy|>f)1Q}hEHy%5(KMe) zFK}n5LanPvwZ=s&iLmV-JfCj|4B+?{M1H_oJsoyASzQc+JuA4B;KO7K}@k7rhrgV z_)2hgn-X#C?^WYrICYs(qE_339ZdRAp(o+8JVyvACtZT`ZR?5Uxgb zt%7&@LgaP}uvOF@R@J5CX#SsS$w*LOpPFbPi^~$I-H)deG-z&VM{!OacKy1t#$GP> z73hDz#Iv+S|mUK$K%++Lrl z>qf}P$w#)7OiWG3*dLGV4`(_KzvT!&KTb&l<2qmLd7sX1I8V=zQXNkkFx8#bw+3SH zQ#mnLD(B72&CScG)!7Vhj^Zel4z69;F4jfx6%-XazX#%bd}sxS+U2=h+fD!>mgP$% z=`di`nJ?bl?`Ei#%wU4tD#(%R@AFdlv&IKVGoB)QLV*E)H!e1|HYbgTr6PFF-G|qT z^72oYT}YNK*E6>(?n?PnBgxE%Gm93R_$lnRJGPfQ`&SP*b=W*|va+%)T3)NCfuR6q zm}X{v*1-3Wzfx_-a)0Lkc&*My3QH`u^fJ>w`X!}b!%VK(b(7weLTkD4Z0HmA!9$Zg zht=TO29)P@%u6fm-v;%WL*OYh+|Z?TDmH2AL5>&%GI+jyoX!z2@au89NYlwyqnOLkpXgaQl(>ixk|&(aT>9m+D1#GdxF_XV2<(hSQ&?l|awW_^)17z+l1F zt4VPyI;?O5P8^WidC!DyuiXpbsCHZ&68F>D-T8-J)0d}vt8@fx)oM*OKC560oAky&5n3xtcQN@BnXT2P1Sft`0VFllGNw%4+RL?^=+{dsi+E zJTXNvsUF=k9*vr8fTzQ@zu06*zFhAb0Wv_kOI3L zN9&md;EHE8U5{6IpVpyvcz;gjdNDg+Z2ca73{2TQPG$xMF1l||D_ve(RD&xfJN-y^ z{>)e|yQ!x#yrU2DMO%yTl#fZ{2bJb^J$bRSi1}D7Opc;tW8OI3hFe`oV>1aVT&sCV z8W7<~zsn{+4yCRNoHw-a^PDC=>j?#wsM(4KGWum-)MwQucqr)o3I_jY!R;c)4wKIE zEuDIq4O}7n1cOV)lXQB}OWaAdtg{NUb@uFMS2MXssjE2P)HEh@A!n8yS6f`BDHN2j zc+BROZ6E8AosFlSrBr5R@?%Bm;r%PwVnB}d7u%Md-;P5Y8J?10Xg!-o+3VHIv z+||bsQ#Ld_3mvaVD(xGVLa2j3?rQ{W!aS3sR#$tz{5^^gXB+@smw2F#;!>I7Nl|{T zEUTKqp9ym!-7-wAv{lG9B?o6+BGO!zC`0@oG%x1!U!T_8Lwgu@U!WMD;`p|=f9Jua z23vuw@opGYo`<{5T=9f-_ZgKU#WEUl@+4l*7yDUF&eMk7>ca8YFzh}^D!k0+B*P4U zU(43>-mCp7CAY^Ctha~$m>?Wp4>u6B^5xEm>(zG=9<@pmT3XBFg&NjnCt`ILw>7|f z+l(%@R+p>cNtHnsZ(2O4v0<_9*;hu}6~{pm&SS~WC|hcJUPY?4yKFD6g$|{> zUVFZ+hPo~B>hav}c)e?DYG`f?_5Q0=_^@UEu4ugHCG8mdFe;+`Ht{`1tk|h6F+^nF z6T=wdD^ID)*-o3EccRB$a=3L^QWh5%BRMUOwnAxvO2J~W#J1mj$zr);R-^iQ(~Av^ zO7-;x9(c3a`O=JKk=FBmsJFKlRf=uBSv1DOrW1yvg=cbw$6)wFI``QkI^`()ZtBd; zOzu!TP%K6>cwcu?EKoQM2#?^v#I@*aoqD@AHa2$CJw1-*D$X8S07n8Metj1E`Q@b$ zidW2qS_{|tnO_t|?xosiCMBK~;%@gC-xa?23mg4KmU%v6?dVfR>UT)dwpn)?t(NNM z`+0qD+I*y=Q=PvpK!9je?*& zXn(Y7s!h5gqQ=IeqWjjmk)GFaZ8WbgDmz#hd{+{{YUFrSMLAE0_ymEK(*Y2JL=SAU zo8D4Q6y=rWS;WE{(obj59iO%N-d)_5?feK*2vyi1x2OH#8fJ9SGrkLS3(V&^iIj9J zxXI4Jse2w?{y&Z?8d+AJd?iGq7C$il3&YsV7)fN)T4g7XbfDSqQN8^DWwJcT{cBm# z20d%*sJh9wj%a#>d;&^vY1{VqLg&|q5f2k^$`s;7orXMhy3>|JDf|~az!qiK&-o)Cj6&~{yS^)@8WO}Z71`@&G$G%-nJxbevKs&l zaeCTGh-d*|$jDahEHW+ZFCWFfR}BjXj*tasOQ9_0ocG29*u8lIA48cqWO+8-BeqM& zZ??ngY9Lavv}{qWZb|}z%6ng~OkEzHmI19?y>0O-!*no$OzHuz^}_s&7R2Jt?yiL- z74&!Rg_ywQDcc=otvfL?gAv-GT3#q6n}(h$IXm+}E%yQd*r)4|IoIE?w&B@4MRXNU z975n5ADYc^JXIATPPpz1p9)O15Yc&e%IvKGd@*V12gikehU>9w`xnv3=B9+*BdPYr zTM)uH_RNYf1HJmdh-iWvn3mEIOy0Zinb7usae2q1G2X&C z-K9QVBG$pBK@=PDCsoqj+ZXYrx}@5U-f?C1(VhK|y_7sv$jiSdK|2!oF*i}!UYoS_ zwiEr^V}k2i=kX-JM*rw-L7B$rjM8^r_lWe?ulta&;%dFnK`!lH?iOljDV351NBB=E zxFQBtAv<5uI5M*(j%-l9oqt*EyI}BNxAcWp+@9H8my>0&Hjk}Nu#8#X4dfYAM=aY&VY;*lkrqq`0DDP zgntJleDQRZ=_yi~9wJQs4T2xD3gDnx*$~7BzhIIq&+!qk+UwB)aB(N)Sd7Ob?w7+$}+ltNSnLDQa zQ?9`I{n|qr8Y4>(j)axD9HAcmp0XJH8=1e~ers_>$J~o_W2=DO`HLeSD&nh~@xnS# ziboRZZYE=pfN?L&mMp6cXO}c>47*CC(rkG;k*(PP$Nwi+v;(<9BI(wBfiFEsMxzZ5 z;ImM~uDag23RZI2as5*$7rc-C;6oPlEA-lC$ppX#pXUnk>4l@=(?z{*AX>*E5P485 zYQ2|8Jk~w+Q^F2kW$N8RcOMdXjA29^A4C7-$51?g*M&H*Qu;(kS=%Fq+QH21a$Rbf zJktPUrEtOki@jV$IO?&_zZv(J;b%^GE`n7a6rXya2x=N9N0|Yvqukn~Tlayt^%9&} zf^!@tLdxYz18@5|hm%$&($L7Y=g(W2pXIaKQ%Eew7tCe+C}sbs%4v*)!M4}C22tK zpl8<8p^q~pxx-7mfnT;sC&KS;_fqL5%ZoXC?s;Ye_0E(To5)7l8)-{u6OQ_}qXO4erir zrQ%~`a}ZKWr8Kk~FK@s=Co?~$17er8jO{|&X;9Oo&4m)z!*prDnL0>S3kD0bQ`Pfu z-*yGLG2|DG(N+nM4PlsY4l1dXdaIjr!l|O7B8^JrkJ;_w=eSvrCxG?R8`cA`Y3kQ} zT6ncj$6=KhXrHD6=%a!kA#1${_s9y zmhrfUxj?9qV5st28Rfu$33PyO)=!e)mI@$)`zBj6ViuGo)l;6!SlyAj5>nc%!YDh0 zTHm~;b6NbNDG5=NkE^d*X>|4h>WYWcB=Ko!*=0VY^{bxb_3$k3m`vA!N;}7K^;GLC z-c)Sk@<|cEA@g~k3q}kccTy~Q?zdvf01H-)@eGZOEI)#SnjEN8KWcITe}@Y4Qjn1; zHyFV>Zd$Cf!k{3Gm!G&hUbY3VJly^Vv{L+Lz^14=CD`mfMx8 zQI1f2J2ss8`FU4o$G=OJMkhpZ%|S+G_6K`e@2Lfp2*?E@4pEf52fTPKMMx+GZ*l)2TjDnVMbgFTCf=o5 zg52u#`h434p!c(n9++oSR&qYV?FaWVsGYXs?rP;m#`|G?9 z|Mj-*wIz^Ik4Os=+?!sv7s8kC7}K6(`Cz)JFA~3uu;4;p1ozEc^_~V|pzeI7{&KK&p%*%=e|^Pto@B~h8I@*pVkm=E=j9kL zuOvVd$~>Qely}bQV`)v_f9%j@$(|-vVwipNZgF8jI1&#yAJ-TXFI-rf`}!9kDmglL zsQWD(J2!@DK(12L(yksu+KCu~!O__7jc3W&k)}IsWDALsF72kfo2H|e);*`t>)7lqGEPh=M3UyOvVrnJaF*NmIGMGI6c5v zFEO;76HGiV*Wr*dA=oST02dCE28Y!`oe9ewh{U48!V^GwJQ+Rf!30U9vVGICnFg5U z;NW0#O3Le5ATO12`5Q#Qz?Z$)mS{`|5<)^flx5Abs;aPtiY;3dl$5`Ns2+u_3&=N= zS9=2au*yJyd_;20#X>y?tq&r;CaO~5yI)NJ_lKulTPSVV!SeoCoaTNr-=Sr7@T-7( ziGa>@rr3$gqYu|n&(KgHsU4l?`D)6iw>spJx)ZMc$Ky%Um`+8pa>d3VWm$1i(UgZ- z-R}EFYr^5JP(c2GBWzPmldAK0cFCV2|8cY_FBArP+lE^Ye>Z^yXrdvMrC&)j>h-M*)#-xSyAl~C5G8+1l|+=NPW+c1 zo&*c(XiUO&Fl7Ar1hlC@T3c;Fjd*@1)62s>67~9Cw=QLfhRWG))2dmk?fP!gle#1L zOaKD56bB49>TR%BjnPE5@l;+%#+kR8MT7p?T1OMNuSr16PJ6!`7$OeaS&C)rdnWLi zi|rxcx;JdJ^Vs6?;$DiN(CUD+-S)>ug#-t?vmpAu=AxMF)l(+df;W2Vaod!i;lV*l zYWVzc&EHF3&fy6!g$?UJS;>9E@=h^cv#ooo?NTI`ox(}C}*OwlA&hlm#G){ z6A=Et@~JNZkDseRf7+e|$S#U9&aG|aN7z@I2Ln{rS}fK=vtGXn z^`rv{4Y|YTQ<_ITN#@s>P*BpGrnSQ%zti1%An@a_C+qM@(8|W8Rvc-Ftrz{ok!YBh zj*bCtt3-O$`m)NTqEnHpOD)bvuqGuD7q(@Q}sT zk;g4wxx#jhK$2c{J#7JsS;32!2CTAh&U=geOLk}eE*i_ToJgL=qspO7GCPj6p>3ay z!O_v3c*Q5(!uRT9;4>CuU2W4UT!Uvo(4=|gqL&y9C!PcO&KRy4$XW-z-NC4gBW*Ri$F(j%OTB&*JiOy6<0q2q`GN)wKqrjJbr?2p0M1Q6b)l zS}wnS+5v_C^nB`xM4O3`W>sr{GT z1@9zDGu$o&khmdUJ39ar@pMzyhAu12T39dvYzM6~s@KZ&#D;`~0MHlLg9rz4ESb4z zh~NYulhmMAx2L=FC+ZS>{RQV=k-s6=EATz3 z<`+jhQY{#AzQWAR_QPuvMs`?oFw_1hLO_TF^@e?XTLVrp45+T_oxf04%$;x46K*Qm z|FWxfJ0R%eIe7+>1S`g@%;H!WnPaL{XXq*N8(0tpqrLr|P#)7ggUH`2Z5gvAxd0yr zDKp)Ayf06$*GXl`d~BOl1ifyM0+LNSWU&zwhxJDH_E3VOhj{)Jz;4`^w#34_O58DD zB!MBfNXg8mGmK+gF%Iuav=a(r!3sMjGG4Co=c^1IU-r*8`^GYOGulpo+W1w)6(-rv zPa{45^4L~Bu4D-N$j#9ttDx4*bhZ?i)dDA>NFE0f3KOcqD{jCUB3uZ&JtxcXu7_qH zaBYDGII6|9E+pRK)?5QZiMI#s062@}y6Be}w5|K2+cfj&gZgirfxx;1e7N-t&>U`nIZ#tmbEH}P`uRcQL$_%Fsm^-ECFA1#BpWbcv!Xa3guQWRYtkQUaxt-nf`4Cj5QuVGCx`$c26T;~h z*h2HG!=P5}2I<-0k$qts19mn0#chC~VM(Emp>+^N0*}w6$8iPRSb<*rD~vLxrjxd= z?j{ibFw-!D2U{`HCpbPWffq~W8h`D|Z-@ks9o~;n9%^fp3UE?>6GnjRdI>6AjBUrs z|IH+Omw=PtxQ zl3S2w%xA4!{<=%6={qdVuPA_xvbrHXpGaehqQ5OVZ|^e1yF~rN!J&QTEPwwxXqD;* zf358VY+CM?26+5ejNfhC_qIGT#I?4N2{o`K^^`nT9ms!Z!T)X&vGCLtU+Ac|^8<&p zCPgIwJmLY0CVAnAb3)dDp6BxyZ@$fF>jR%5uUZZ6Mtyd-#iiS~7dJ=;#t!`>w<0$I z4LwUYbt4BvEmd%YykGytVmk0&2fEtrA#}U=)R2|C_JFg0O5obmE3-=5EKA?!!_#`4 zDe>-~7X4>=0b2$w16?Zy%}Lem8=7)H1V$R~V!nI+%jaHhy^*G{ya^!E*0|xld&d?OPpn*-%81B($nNHrV(^*HO*))1_*8lNtJ!iT^~y_J z#otXEB-j5mr?HW(VJJrv^bZ#c##Q{nESHxi6I+E<9s{aE-o&~t%V)Aej|kPra`qD05ch>R-Hg~J8gYDG0R8w&|jEV%CH$E2e|9l z)*&z@zFGaMT?E#aP=WK}TzaA;_V zrqjAVNGdVvW@b2varXJFYw@(X>y_(t$(FYMtaBiSl$Xu%f=Niof4&A<2OwVD@3#{;LAD9IyM6dhYhY|_R%>4X-aa`%Y72H4 zBhBNDAFa=h68u}~i5bmrwuEA8b6F!6MYBUuRqxp_3hQCCBZBSiK>6MA^%q0@PpGI^ zT5gur@OjAJeP4!FM&dc^lk?a!7^ zIHA4z@Q|cOAzL1&4cmVT)7>v%)a5HHd8k4{sK72U3)T@^Tk4qX})Ait;0xig>GN##X*s?v$HDLVfo07a1n_!Es2p)la^o$~)zx@}v(bV+}-6d*%E3dqhfN);)dp-PW*kcW22Z8X zG-7-Aq>`SGI7pYy-gJmC96e#iY6d5t<&;UFH3uTiITQ8KpVy^#I8WGJXa{ zOrZm4g=yT17EgW)HfR57r z>=51yrlOO9`%gMOA-X*hQIum00avOCl!%f4+xiyirf$fJon#q{9MQ9B%^n|R&+&~G zz@pzsVJZZB`IZ_2AZY;;v;B7Z>Y`GYqw_wX#SPec2Xt|dZFHq!*AsT9!=tKE)fyLj zQPF{?`%56hsgljr7-!2HW3#He>Nr14BcP0IC_~yj|L# z1@XGx9DR|KGdA9DI&ERKSgMyHvs;J6NW0@sEx7& zVi6&hw7R9=xN)9aP|O1b}Fl7Iv`zd(|XR&%{g_#kfyR4 zPfAO%@#W8oEG+hgeZ2fvm)T|=r6RCb%3e}ZBA!59R9u`2^lOZ;E|b^|qtpZV5g450 zx?D5s@vxsiVf4$SCjC4V#03c4fGcaH<0m>yD_Btg8P?%wjyRHIP>aqgr(Az1UW3Wm zh5*@X))7EM2&^k}t7B<9fbX6> zyVm$rlxpQhRJd!UjZ#akojQT*>Sq0nYXCqS6sH{Cz2{Bq+b{8jVvmY@2RNTw;K_ax z7@%n=y+>Dql*sgfEe+~~r4d$y@d-i^{Dv%uDWm-2_I}Kd(8l#HGsn zEz4C}HH47N_gO&)^&%NXZ{j;y`~-MkiN{-ao!`Hu>V_#>)`Toa`>(4OQSV(mqGg(? zf_NYv8@M{ei%E1gVGU;j%l!3M7ps7Y@D;AS^BQAqrN@%B%P(TX&b2-AghT(EI`qH+FYLe?GJ4r#VHx6ts%!>tY;(h+S zI%hhz;z#n;Z!@9QZK;brd-Mzak+tW6mT{aSnGmVt!@eK6r%Jovxn zQ~hne>QkQjE&YH0Fz@JnF!Z6OGu}(jtDVXeH$~X>M9Xa9|M!P8TD5)c1~kTIYtkpD z-^;%d*T(MDHe5v;6GkJX?dIilz>o9(pEr;D{pR}=Z^iitBc|G{Q;zHTQ6n}v(?!hL zy8MdQyh=)29))!OkHPE-7|R9s(xGyf?8VrvxmSNNkL~gT*66JDMN0Ezw5J(!r_ARxDTDVV1Pitr)84PagohETZXjnE_M;dTgo;lN}&X zQ0`9SLB)D*+l4z$!f&N}SU{3?JJjX2f%F%7pHaWX`mMu(&KF)|9fX8~;=z`F^XeX1 z!-!y>fBab=H9+Yy( z+>!hZ=W7;r;md_(6rVxWmva%6lM7v*vH$h*KAke{*lmu5_q&qeuB3;OvrNEXSQ2iU zW*{icIN9zeSNrkVmQCKYf52_pb}(DD)sN)wyH-S-T8k|ZixF#qvx*pJUcUfYOVXPs zC5JrDFJn`+6#(O*ZCPrk1Q9o|6o;65d068zu>z*DKLiQp1H8 z4du7M36E&?f5rNh+0oZ_2Q4vrjP1tmrOxoJ|1)RAtizH+pM3#B&fa+FJIJGR>L;YH zd&$OoFi+B~VSWLjL*Wj69m_s^8`$-ku@zY6`6~`~Eu2LkR=%<%RSu6_BKW?1VIBKC zVm5i||Wb%D1X2|J&v^BCM2uwU30 zsi`u!7D9a)E=cxxwr<3eR9g&{PZ@7~$CayGaIRjs&30*@0u`KlC0tctHn>2il&g=3 zKS-N9fZk_+hw1pv2P59i(3Kn7?GA7!Mnb_0{@LPscCU|ZuP zJ~aG@lS-CAW3owL@30P1#CaLFcArP~%M+T-?id2=NAFHuQ@leLoT;<&=zo)pfn6vf z-`t$_E@wJhGLfK0IkZAKVRma7XIA6e@EQhVoB@?;iI7}!#jqJgg>x%n+I$^`+aTMT zesh`lk+eWuaYJQdk5EipBa2|Rpvw50`m(6Xpf}05itQ6hL>Na2Z``9{J*j@6HZaxC zRcO@dyVB6c5M#m| zAz-UPE_=r6&Xti|Q1gW@vnH+w{=<*SOcC*{5KNr0e0ogV8jMx3TS#}u>?q^;6SJ12 zHUF+k>rb)bbC)Gy4x1R`$Lijq8<_=h3!jb#ZKfFb(|?KB+s8Z z-h~&&TiyyBdxsrwL@F`j%|ras@jSC}sP|&7M%9UB3v?0{5!!;S-fCBfSP{$BaUy=jJs3m6{6ul)oirgz z?3)AGkBy1SX{uT>Us`MQF|>n-_uYnr;AIpD=c8qBU}dUdP$dRGo^X6{u3hoj z`o8hKZ?lX>Ut6j@YQkB6o3j&VfeDmQi*We9qA<~$Es?xVdB{%Rov2Gj<`mHpWY3V4gCkquz zTW+ZF=(ci^IvTPH*W9rmlh_a`U|6t&K0fV!_qtHYMd96C<}_=oFt{PsD6XOXQm@Ea`enF#W)7F zL4>maZMzUgPzxJI=NpPZWt@a(7!WPr%nN;h1hx7L%^XIV zc%2uq$P4CqC8@LAnePuCO(S{VV{Ha)osNm`l^;tB@uHu3m1U`afrxJ2Y7)amGMHp zn^*i3K3xRgJCK!Ml#4BYVtvG+9aD6)*0-Xliadh6CShT%DXYY{tn`ZEdIT5BBhb`b z*+2W9Lr&fcO-@}fK(C_rT&a(gGP#1Yx)^!!7aZUy_UD(#vM|dTGjm3ag~(AwaZk2S zsZ0nHPw<~Z1w;AAR>OaYV75sYZHeA(M+zBYh-^D`Wg?ZSlVPVru2Lk5V@jrG3!!%6 zyKqTUUuDWODqV>+>BaOG^($*nOfQJ>F8f}5dsew9jkaTIUY|^4hc^?BNoPp|nMfwc zCYSp&1`~BqlTBlyje7+P&M09yl3|RHD!qdLU4nUXQJ_gm_2yR^Q4{+-*iYak-n?HB z+Be*^D#6b!qLQ;dOclyH47vHjn?^{}Ya4Ni>cMs`3@Cd^K@j0`yu3{cpm}mGJLZr~ z#*@%Q+m9J-*kQW^7d81w|DnSPBY;E6GUg<*|Fd#&`wu^R@V>Vp&V`fXT{U{*3klht zLSPnOidIg_2jO-^?5Obw70Oxqd(b`3sA!o+=`M4&WQ-*j59=*ZPrFul@+du46w7a5 zVZP|zB))DQ zrcsGyWfig6#ZeqdxDtCiX_Z(zu8dL^@@(7!FP{4`e&)PFou@_0*L{YajaYp?Mb1p5 z#rP&PzCCt2L7}xJe-;bYqe)VHE3j6huf2vIom6}TU(zpYlI`MM11OXY&t*2B7I6z_ z78}Q9olDIA{z?S`)386>Ea04g+JN^?KwiO&g6T$y85%)?nQJcZxSy~B zJa+*8M#2y6+M|0%OYi5mDW*zM#<=laEQcBkUrNYOxh1E^^QVV>lf62>gLX`Ir#MBO zO4$T3;wT99`dIyq{Y>t34kY~c4xQ(d54?IsKg+a1xmx;e^M12oppTYbf0x);yXm#x zzxYW>=|Xc&DS%Iz+Tinb5kr+nQpxuNwZHGOs?w`J?$Ly2Z7N83W-6~-+>n4`r@GD-*R@!8~! znM&~nHY29cVF!cC%OiM$I>X0*p7fgPC$?Ym@kZ4lLlS6Ugbnu-&B32wP1`JzEPdxJHVnY47FtY%Q2`kU=ZI8^>!&gdwj}K$Hi=}F%b#@UyHouK86L=`M)%)Tc z59-ve)M^uYmG{BzKju@+2+$X9M;S8`By`Gj2+DLLbKd`8RxuU?qf*b<=wH^$9cbe8 zCe!3jrkq{;@J7C5NWQ{=3d$LND8oR)ZXeXBWxT>Bah_hj>8HAc84U6M-D!>Qck?~{ zKv7D0WIe5ZNzO2+nd?AOT}2~;qM^@(6ik8)A9HF{3`TYF-E?qx5n9s3QXlw zA{cjeZ@&^1nnXPzt)Pw)zs%NhuUOczUBSOyOi(5Mxkus>X2LrzNuQ$%!6>{)O+x}- zk*HN7LXH`MokWH-_JVIDZ>rP&B&gQ;!xq8(lUtMlcJ-;L_qP&JUcy+*BC#Zss<+_d z7>TTJk3B=SqE(EGu_?WOY4t;L_6Y;HTkW8_YaI_(7NI zqI@Q~7)SHz1%CBi02K~f11&<6PSg35M9p+1Fmtj$BUlpICI_pMQq$tRrZ3awj#-$OK z{1cr;q`C{^uEGp!&z-R$XW)@6p_K(_c*J=Wl0OxiPu*JPm(ym3AwX^khinzdAYJb_la+&nQW1fniIDb-| zvXD(r!bIS>Bdo^z(c2Tkv}ln#UrWBXZR)*6+Fk{47@dkditzrU(7c{qxS0q8?VtB% z<2T4xMDp}TiWSOM28!_v9~gUnsTV{%pWN6xJ_#6EuIcpfbmR72B)JWymeiPFFD%LrhL30gS1J!~UL0OvRbZa&O_TR3%h(K`FVTWA zPSpAP`Gty-egdOX0p#|NMKv6k_SkO^WhQkLqdqS09gd6LKqY1$%VRs}!It6KA*vq-u5k*lm%O7ptn|f zNiE%u2YNZ0^fjN09I8K4>die3Ce-2w`tLLt>uG%8f&rs%MMGx?@=NYjizcgmWBmeo zer-2v{Y==KUt2}nMm_jg9PYh+<3pm3SSBzoOO-H}m`WK|K5b1AUYm6|gB}c2& zufe!*=Vmyr|Q7E*g=6F$|b3U*;UVMRno=IZjT89 zh7Wv26)ZOYP}$T5>27qq+_uJndxtuR&Ko*nd#AxA3S$Ef`bmLU#fm;iUDvQ4`q;vV zKxmwV4eQ0$5f4LUFrAlg!d02D(uC@*xbI^b)`0n1OUs?pO!zMA7&DHNaLt}tqQY$4 zK0exuUxzRK@ULXa(T?DqD1N0p`e;d&cti%T`T*&@o@-(dv>K#izjCl&fp-moC_y*d zt=QoO{~qu9OD1K6i0QU4)WO`X4qE@~$ONJeimh7sDRaOev}11+TkXmL#bFQn{Mpz! z2SJY;gLhnsjR%fvxwfX`aJ&;V7kZxCq*+yNg+bUxzLQ|i^1f$|K9c<%sD_MMS}<(* zy?_)6lZ|l(* zvKMdZ5lhdX@SY*wd4G(N{cJ2g#x(8r8Ppd_SkKrc6(k$E}DqNt-iD9mJTp#IHpO@sPv zj+?CqgrU7kPq9Ce_KQxngLEMeU%)*|V|pcu6P4(-0hHX9qi$VCdG6=VYn4_~G#WE( zKn&8r2q)1iyh<%uPh-8Mts#2&=0<%C};t6Yw=c% zHM?xBhfU_P6xk_Uuf)fxaSP2WVOnNXFG1aXN7RbiHk2WymK>SRi7O zgNh?R%FiB}(z$d+?89ex$@*A@eUkv+?2@=2Dq{HtrquT`!@J5fkSY$Zb_#eWo9%J| zV_*|!tRu6ocEa_-6@2`jq@l)ea6U@L^A>g8>Ay?hg52RgOq{FMWHX>dNqo#P2(xI;}+ z6B3*d^9TqKtdDGS0ye37L%&OL}y6npFIjuyaX95>h4`q%+v3NgH$J zb0@@P8H`K?wGnH)iW+`M)!DGF5ODBon-w`TMTGq%}>O*}cQ*)GzbN{3ws>zVz zgXMosH6pjNDpic#xZi%p42~Da5amE!ORp8k6H%q&2rGB)uWUG!fp~Tqq@d--UBFp> z@I>|CCe1(t86>n$_o;$A8n$=22}$K5cL-!V(EdaQpT;z+M?t6F-v)_k3jx=?#bA>^ zC9)v~b<3OBNFM(1(G^+hn_XNgLrk3swfgxV#e!d}pWGTSZd8VGI)ol-))M#udbFp% zNXGvm@PQ9SGYTbK)ENY=#0JMToSejN(~S#QVNrh{g0uhD!Xxud$E}}m{~Y1TZA?}JgtN$DUSp4^iI)aJ0os3E7@GA(HtA!N-J!P5I zolbsK93GfiU>#hn|CWmy`PY#OPav32fEWg!{chDHe){4`|HSuE?WYHh@NssS<(@!0aXF0T6b)Z zmmv8m*g_bU@j3kyEbAgSAQ#Y`*T}4+7HbT>9J)j3PZU<~vKV6=W=|&0ma^k96@gah zeLLvhF`+;!Nf9fO1by?Y+IsS!izrqw<6vf7!Pzrp&er1945fq|u_vJtR}Cu~#L63P z#b{0?H@Yo}v~LW^6`Gqk=7%C`HOTb4z9g^1skO`oLF|}}FHA6oo~~B-w-HN>lF4+} zpYz8nkk%*FKt5n0@G9wDrbh9PqRl0sb#;e0IRzTiNAG+PhFP+8%joYP((l?g=+-iG ze5h_^XqPH@eC&@#+a|QaO2=ryN3;IJ@o%rnF*shu!V#6oC;?!H;rTs&%Bin$fMVV_ zSVj!VG^qkLQb4dNnBqvKc8qxa=H?*eC0iS5?2InvLONWL+fR;Zq;^DJx1ER@j1rVLyyB0#0pbST2il(K)z>JAOe1lu0+wAqXpwCgC-bgW^ln0y3`06Z$l$Tsiy z4#?|t#06i_Kkr@R8jnI#5#dHIC$m{!5mDu2rlYi)QbHkFQPt9dR?{YFY~nJKoC_DtXPALm)})odre-Rd0~;XZ8JN9?>Iyy$sVjD-GYqvTp4O&5NXBH9u7+&-g<_ti@R%8}A!*;vvaKR9u5->_z^f zn*ZAXQ>bpCc~f1A0JfhSO)G#zgq(*0feX^fKdj>;^%H~};opY-D3Q$xIMSDQNn03v zmQg-mhs@CIa3b_cL()gVk}@~%F#pF&7(t1T=Kq)@uYsLe17)YEH-gV~h2M3ZBWQ5dmo(cS*QOX*q&$ z>Lojx{|azv8|e0q!x;|=e|ItKkp&CcR%c6!PmCa}3Jn?qTVQ`quN&TEf2VU+dfi>G z&S92Gg<*;CPR1~c@FE|`peGeql_ao|DAkQZzv^=HEtqpu1x66$R4^5NPdURvVLAj) znvTWX{3G8I(n3YO^9NfG_*+;&N?wq?-nA)fT-N9uC7Bo+sgEMb?BAb}&NEfo`}|-S zI8YQTvDVokc9tZ-+{Zo>3o*cUa&6~>pDd1e?w__0i}M906!Bv)PrE=Onnpx;;Y%U| z=?9OtIopNwFeIF`lX0pcm~aM3tASl2w>-KA8^RLDVZltT?@tv;z#H$V6YA|di|1Qp;$0Jx)CS!RCk_4Ib;69{wk|u zjEGIIi{mRoMR@$tMN~gTub<#QyBa1XQeA0fb-Ss25O7AmShI6tDfSy| z<8wefEwNCf#{7E{$jg(x91|bIC2_Jt$h>3UI5R=u1QLW|0)^>|_J% z0vmTG(J~wLNuhZAv9M#HY% zpvAo*dsCZ-Bs)z~9(z5wQUb|#+@luQTzs_{$Nd6!HC*SslvQTr3qYWxNFashnC~K0 zWYmTX65ovw_H^MNGIpf1yvUjZIl znXN5rD!F0liB03GFU`PvoR-5Et&(0S;hia`nWdYRtPylI5aB}mF{FD6e^(zI^5Ek< zDhDJqq|R+_kP(w7kPHN&!MsJJV&W}1<|5zB5_-*{Qj|d&4Mda1$r2ZHJ|`u#z!Qq{ zl0UCmszaMXP*u%RB$^_oxntfzW3N-=v=tcOU)a6Pt~WQkCYabbl*u@AnI>8g!deb; zuz!6ome9AzJ92a|OojaJ(y-g_Xu>0^?>iOvpV^7i?H0{_F7@c}7bE!~Lky+98r(4^ zYgvudgtiv_)GUkI(?SfL7seD?>=MZp1gaVH2*N}DwNNauYQI_!T6dV9LB%6w! z7e9J7&W*tP7ML58thywf>nVjjUt>Xtdq!%*rlo*7U#I}_@%pFC3~NpeFH#$R zzq@0#k9IYW5{)BJN?@!`jq4tIN<&>&Hpwhw4pfS=srWrleV4&XK^1DuZ#}ryqJNrL zv??Gc7noCQzTu#Ma}p%v| zU4xQHGQP0Ng;>=*`0jUxodqE=c>!?zY?|c|e1ov0J}{_*G8PnUE;1_7CHw(qrYo|C zi7&7XzGD6i!0wO-$uVmrgh1MOEi;55GkI}ZV zO{;p1d)nsk&af-Ee4CB^y?;v&~CsBBhd|^+z>OfSM&)^OYpsRlSS-JJ$N)tO?7pXL;1syb^dZ0z$&>D=v!u) z|I&rq!s`j9&o3TJ*eiR!h=)Jg7UdD)S1j`CF`+ez$HVS*P?@WCInM{Q)~d0HNm(b zB?`Oi0+}OzMS6=K9LU8AjxWqp*s;F+3WN6KJ1y~`(mWSyKcP5AlxO5cyi1CMYoTXS z#Q0_ESn?;fYeIF9Cf7_kvF^N>Qmfzxy(S)v6?cSj{7fR*d3`>fu9()$qQ6=sC87bl z=~56-1|Zr83)@moL+J@54$z(FRv$hGlK`cB?@h%Dce0Z!*$tJk{C5ELMu2;t0iXCi z2Ms2&kS1NZiAhDQDIUIa^J`l~xRU@98o{mpG3s0xn0iBZQM72O!LTY=lA5NFMx4v` zz!0P^%AO-#xMaI^8Q8;ptmQBpy} zj|Yj~a_93`i5I`lTlkEl2?R7Vlv>k@NgWxAO=bDyNrjSe^@;A5(b>ulyX<&KBz#_X z_Qd;(m=SLDrz_xC%5JG#fXCZRn`&i`^lO)p;5qFVn@rF8jT{m4)9$uu?DJCm825B) zyNKW6vCTY`3T36#I2ZlzODYsQFNYeCYF7>9IRP+jkZJ31?Ae32z#cIS2uo#Qm0@W)RG5M{hsYgs1QZ&c+^dF0z?4b7rBP zs7nRRB9wOQpV~v)!@Q?}G;e!#*lZh+WDM;-9pB{2PaztXo~P7?Xm^0==8G(q9Ie&m zrASY*sp(-pebeWw+3>m88@nKBn!B2jE>)3bU4hV6XnisAy}{M8t5HPz4z26TU1KC6Nf zRhjwxv6Bh^y#1y?>RijgQ&*Gi;AkNTJf1sp$#Pck|0KlUV#HBar58Ozrh^(7&e~uC zs7681&Ds8RhE*nJ;LnTA9h!JQ2p4WBDP6Z#<*i1r$JkM}+!jrYiZ;yT7R^+@{M+(I z^qP^%Me6PVeh*F>V-9e zSv#N4rY4k}sWhj(@5CXiB~WRO^exKt`0Q97;0a+=DOr1YTPPVy<9F_hg8ztrhiK9# z0147BR3W#Mw^6N#nASp#)je1{mw-CzZ}TzGRD{A=BRlcOt&6j^X2(vbLZ9C`Orz3r z07eH@!ZpIeGIhm!BMyawWe5UKZ#OgBx>O7Q`WR)k5W>^?YcDuI0Br-I`^2(MF+ZxP zxdH6{IP?Z$FakF8HeISTiWdgSb1STs8gsIfe~afmUTMJ@QGHdPyJ?h#+QCu&2&L{7 zi7{lM;H>JZ$*m9r7Lh9N25 zp(Jn6&;Oo^rb{mt{6qVKD^h1UoLX>#+Fs|cxVR$}D*P66;9Zl5^dNx2RW49OxZ-N0 zc(e}J>c=7Ol56@4LU~mF$q;*zz@FWuWY^V}u)zZ9jk^>Ymaua!LCOgI&f>d5{7pju z*z=?=>cNSSF{YiaFvD>>Nv&@I&C7FC_0ZGQ^HIeKR51l^oso-?U$IP-ZMqReV>{R$ zuFyJ&VabHF_vnUy_f5D7u0wX>#Ue33X4bZlJlH+vqj(B6NN$3pH#%i2Qwi0$Y|?E! z6r@SEeTMp!7>w=M%t;WHHj%$r-!1*fAdETj5m(oUzb{`LG<_BPbOZnH1kdeM1#@V!5g3eHZqAE{lbXJPYgpMbFnvUe# zHk+)9assfXQBMbD^@I~2dJoX}8W-W%=(Mef$*N*D&*|(<^$(X@6G;57wJ+tPo$KQ& zKY85G<7U5}m-M4PPM=&9jx3SH`(gTQWQP9Q&;_h%xD;bhN zdG5{)UsFVyCAV=C|2snn-Jon9h6^t3w&I$Hb!%Tm}jWDBE}paGNZa8tGSE36H|RLipv{`(k-Xeu$EM&Im<4Cx$z~Byl#q*htRA zhBc(~cI%RkHs&eO3Yl+wDCz`y3?kwXe)ykzqp^NIibQHIi<;;zX3DM&IDNS*j1TsL ztcqnvOwdaz%!50^xVox%u&KGN;-d9eAYr)((J&cci3V&GwH`r8tz1fKZXK6S_iUFK zEPlou5YDHTL-oxtEu#|qy?$iZ0Et@x=>FtgDKYY&4;DaV7yneLi2y#0{$AMsQmHWMKN(0aQzYWG+tdkTW0+#&k4 zS1a(PKfeyUA=NBOYT$CS#akCp9B>bj!i6qhcEF*7*ET_oL1*uYP=B=5Y8Ay3*^5TY zq2I>FQ*AYz6QCDm6w|y`%ut)G$C!;;AUO_OU1Ccq^pMJoOS(47CP~$s(#5fu648!V z?z2@sWKbCCw{;i9fblWC zq1%sAJMOV4I3t#ckH?l=yoW*yU@EfkGz`~XNFwfr^}a@(%@_iI7-9&=^&C7&wS+j_ zhH4y(`vEetKME5Z7ecKxq#*sB&fx69gIJ0hA}dEQj) z4^T-sX9#Mr?>Vovxnu5cS<5V11@M^JVn^s{Px3<`avT|p8poVnMlJGor?0^=a>)#U zQO6AfkqCqMR)@Nu27JsYOBjc*=LLQonX-xu#@hkcyOAcm;8HTfj=yE9wOQ>bjI#-7 zUieXyb&138sXTGE9lbHbna8izOSLur<-M$-zFau^Za>rG{tg6fo1q@8x*TCHBi~#9 z_!}pAVO;=;_$6~GH`TH3YwawImM5#{oDv8~uCDW35{H6i^JNsC9n}}+B&o<9g)B?9 z((jdYp5x1WR8Bxyw~Mhh}`IXYRz@Jzss`&YZ^m?_jARm` z*sN%^(0fcd?zBJk08~MdQ)}t|(a=Sw?42y7?XNeqvnR<2 zOk~itg=Y5(0v}lbBT~_!YK1!XKua2i*}nf%a46!MVlz?F7l73xiVw}>-#IT}Mi@H#*UDQ<{* z8Hb)=ouxL$eqXo|MTtscAr6d6f~-Z~Vh~dWv*qxnu(WX6CJW2td%R;d)MJLK|0Jj< zN#|Qv0M&Qq3QDopy<}k|J&(yPHR{s|rn9_{YpP9CZcH*+ou-`#JEcGYux!`GCj{=I zF2qwLBW&t9o@+b#jz+dQQo-Cm)9(Y9&{*q4&8uzRs}wzFaqCc)EE4Qt&ZtH?esNUN z<`Hk$ZItSOgJcD9()$}*8odtiZihTr$w;O9CPa$A((wUFxjltk+`G-|(v^$5 zE=hP`>3PG{(`q5fP(^vvZHnsiM|Yjf*1CW@#}SVxwWh9fmp zQw2NCh}qQ5m;4n>`Q(OBmPfXkm6LrTU!i12)sN0M7$d3zfTbp#&F5xzA08c$+MMm236PK;woJH>k1VHgjg_<>`8iMIt~9}Pjds$ea}$w&fUVP08z!&taK__? zjMu^XCxtYWD7W=TdID#RZap+xiGldJsAT8DYcZ4l=q@7%;N zE@|ZCn|J0!m!#w0MB;9`a2ti+favEOhQ;ihu}X@Tv@!1ohsNXtT)p1flgDu(#Q?1u z@CbQU7_BVLx3lir1ya6x0d7cGq`vF{Jl?8ztA?~e=)k(_N9==s#m?9J&d{WT(Et-f z^k8j#&V|84?}MA)NAr^6N)JSIeru0wR^iabAu8m8S7ts3H)ntFU=9&y2jw!rc>4l@ z4t=s51uW7mN3c4>x5L(UQ-{XnoruO4P2@dzcEQYIEl<&7-s}RO(qcb6@;5EkcRikd zJtldV``+VE`ba$bQ_~vJ6^-?#w)Z>+w&m)_=_H}Oj2@IZaW1b8W*3j>-3H_Sj)Yf4 zTl8xgN=wAP%&CKtt{h!nT_9&I83{o!dd1&gHL?pdmYy!rFh4ClLLv%$>Q3;4OENr>t(*mM&0BiwJj*A7NyiR zVd1eq3#I|-Bcqlm=L9(Z1J!5XRf- z3QD&`fe&u|EgU4CR?6C#dz2R);yRIynR?~uJrF05;#$aj5$7#;LP<~fYL$+*qyGVcHGJcq#lCbO!g#<@()%m ze>U{tcb#b$)i61Zk*o?bp&=Gp{>5}Y4X2k<`}q(Q{iWGu6RDdhmO^L$!2Z$i-1^-i zs%__qMcz;Sel$0?$*6bS@7?Kc^WcX%YrAuXYaUL=jY+c0m)~#~Q~U6qv#IIXPJPN= zt{-PB!|BrATkX=F=8F(skBjly90%#=)?7D(-J9QE`*0doK<8ESPTr&0yqxZ{=|LZ# z%48R=l4laUJYLI%Rt}GR`S>q<-@$ae)-Rdgtu|N9S0Lebd`dLpULo2DbhQiz7|TF{ z>pXMLAm`EbzC5Z$DS++Xo)fCsEMAlzr+u(BAV?(YcCzx`0}bb)N3;bGO|uf>3X%H( z!kIl;Xis#yZ?Jq6#Glpgo`Sj7xCG(Kc4~}j7BfrIcd_%?_J8$z-Svw`53(;DgD{QU zacDPvz0YupBQ9YZ*&*U@w)sm3E(AZR-eQ^@hc48X0D}Pblk0N(FbqlC7prsInAmTCsqntQX{RA34Rtdi~y;-mb0QPuaHg43D8L0rP~4?wZ#<64VU+aBY0PW$8D${ z`2DIT_1RoWu_P2(gJtm=sdITk@u#Z`7GEw^Wp+gHCU28}1IDEJuJ~wwG0Bu+%E41+ zZ|}hF{_sHsX6^w`O0?%s%PX;TA$-bG`KRQY{)2MK zxd1w5b!q8%vWMC_>M%J z<q6N z%lVb={QDRBVZtN{ETz?FNF}HO!Pz%mFrx4?pXMalaGSB>|iwUUR?%MB_$t;fFKUqW_uT1I8j_gg~iE zD~gsy5MiH|LEgdmkVg zZD;ErK-l&h>({g72`TQoBe#{z#YyK=%5dZBeTE}6AHAX}ILl*_B|u^a4uK+O&R3Ih zrR3^$<=9C}zZI}vxEGX=P-erT9aliCuWqYChk(u2wmN>3I;zC&F`pV&H z=0m%6VW5-};c83q?Q@Nv+L56_9qIReWH!=44n)1yff+Xz6H0#z%SzXm_n zKmUi30(y%94FGzPp3Dn{86*VD&h6zx6Y>f7lS*Frq_5OS;kEni_kd5 z_Ln~q-1{ir_x&kRR$B%(`=RTz`}M|kg64GReu4`cKh`Rx?uK}+m^!9 zr*5GZr-uqqxg6d1Ew+2diSNET88;ztg>>u1#}2R4*8}bL`=giycnzV3=gi5m)7R=G z8P6wTMvS*dhV9{HT2o3|C|vBI0{B}sqVLYq-f_8pop2cO?^}&DEM*Ace=zbfw^jt! zLY%Y{fenc%6$^)GCK?NH;nsAt>;>ywLzAIn833H3vj-R!_Kt>}t>d2DFg#sKcKTz; zSw*Bf*`6>$K?mBHUcyiue)Vl!Mp}Y7`Qi zQAaKRa!AKh>scToe+%)z!#B+)1w*_aDV&k5WiLO{;OyuNP0@0agtL?oMQ`(FQ-xzr z&g>X9mjX%G1pA@F@S9t3VtSwuq|WSe9n3>k?aWx&r-+0fFsf&mhD#!QfSBhj9>D}! zB?cFwf<^@W#BI*saIDF#@FDfq-4qza6~D%DCP_|h7mfV6M|r#{xRS5#d*(6}ubz(h zAz~~SZnrMZ&H?3(`@M_DPyL!H$^hVz3Ji+N{L z3DWqeq$lm#8A|<~4?cj;lJWOE92B;+LR~hkkpp>17unqBb!#>WbZKzt7M6lWuQDv_ zC1g!BZ?A1xeJ<3=)T3Y_5G9n+^?~+b1>U5GC~!!yyv3R<4Dx(3Uq913#ST6;UQv`fu;Eb=QAwe#*4e8^DY8OFmewB zrgFTDE1ZoA9!J!IHcAW1 zVJH87R_;0uX00#*z=9XH1}P}5n{&VetliU{X*?CnOzX}HL-1f=*+gw&DeYWol_};% z^ip2(kPFtSca7ID6vYRprthE25l|6m4v949ooC`f4Gp}OA;YLP5g>ywa#CW;*;wS0 zQc^GwjVv@VyxzM&=_%P)ItW<<#vT6*LP`}XW29virUT8MWy)nWMj+ft#qAde28r%% z77Hc)va<0M{a0qe+oRSX$rsHCp_WsT*eEEaiL2g~5MMOnu$R2&kXn3v-4BRx&pud( zGU?w8D&=N%r9wYSzNx?!zTRZ;M30={$1)3lL!zi&w4#X|ohefb@ z2(!S^d`zUJgkNN`SPv8cAojqu)1V+UGL89F*R5%F9q2$;*PK+csuAn7cgCfq0~fQO32D&YG>6_R?fwwP1}x=J2wnucuu7=oLjL}VV?AWoie*mm$B}p2J$g~ z#~E18@Lx<7o3=fwQPf=B4yDOHKrLv#VERFPFb{(V z-65-y2q5>ce^JsKln34o9P;7;K88QTe5OKYLqswYbn`znwZx_!xZ7OD+SfKdNH_Wp z9RM8)h^IUVa-$V>bYWKP@Lu2a;eE0$0Dh^A$9)08KK;00mVKoJ4PHtf7PSm(IkbNw z`bYtjhe&%ra&bfu*x&y&$2FJmvj$2&%I@P7!8S2nRiw_;Hb0FlcnK*F>6+Z!N|+TC zISAZ;zL+@w$geuMHC0Pi&Okp!Y4oW8(tfY^G;Nvg_>|P8k$QL)yJM_B~NxQI+aF|sO(*T^ys@A^5&FPFqg-!bUFv{OTHg5qdokJ{Na@TzxZhGfTV<~E@ov{L7@bvkug{qH zs8?MU5{*yQckQ>zX72AHCTF+n$@+RLBf@02LwE1@S2hig9_;C^a*DOXI+wNeF1JCl z=Y!!D?CSTMb6$@{w^%W>?Ax+pE}KMG9I%?J&ogZJw+l_0SxV&r1^BL)y?Jd;_oZ?; zuH)x<*nH-=_0t<`?R#MR8(4QlXr0ZMF0u}ZjPD(EEwSumIu^j}6OA zi!#mW>+eQ&X?NGB+M=}HmyhqQ-Pc~*ryE(Vlhb$p0UY>N3OZE$XQKSF@+z`TH422l zkm1~X2eC?X^`0Dxp4`k*$CCc>nE|^bYKJ$s{fvn=_$K@o4L4clT6b1ToNoMh!@9`q z2!#>r(I-y*R%Z7^>5bj!AS~{X$4-x45_k7^ITIQ2b(5GoZ8Wnt7oOBZqT3o3Q156m z6f;!9#xYp@Tk2%^895wE0Wg*vI`t?4tmWiMlQ!e!7eKp_NnIWU3B>MK>90nppj1>m z_)xVK6?#iu^f9QeT(sNPXI5PHJP>A&G;6}_tjfkh5A=*mAZSP)@C~Xa&-^$rW}$N7 zI$6pV%L3lK!|-QmI3s^c&derELpXoaod=aHOH3gh&k;+?{^&Hrvk&=a_q3k#v3 zg5jCc8cRGS(<|^RhyNi11A`@5>CCD@;(D>5p)V_!!vFcm_K|5j#nwen3ON(R_zv8x z+hl*%v*wuf9h-qAa7X+yZq%J-AvcUz;M(rHPtI8+ALwbnO)J3XqqssTvf)~#EIFPK z!XSkFN%f<-R?b!OCnwTpTeGtwQfj<>O-)=7%eGHlID;cd7z7DI3G}bh=IxXY+n`(T zC$MWe&dH-s2l23&3=bgOEN(pSXx_NOwt^C~Lx486a=~jUDH*Knz(v?LC;}cH;#8J@=WB z!yM>D`FCG+x3d_V%A}y?gf8eCqAWnCWr1W|$uZw~%RnkOGk-e$pivBR9*w9R*ae%O;*AG{ zOLD_PQG4-;SO1anFQGD_c@-uZ6exhyA~4zs!q#Qd4zf_sPpAlUnocQ|nt3(gc%TG| zBJx}wt#W3^FA{y0*yb@CH^#J37M14qCW#A_2~}mKPN^KBRkfpw59UzlvI;?_A51rM z62f@HEQ9!d$Y3l4(q}T44HOp?>=6JkH?w*ONyz`fCsOj4g|l|;K`uid@GAQI$*k0Q z&iO=%NU7=bD@H-s!8gHusL%r+LvZM#sds-o_o+z-75P_+R=|`#;Mfuxiek?TCRM@@mC=Y+2Zid(f<W^pK`a!h?24*mriwk#M8joZwAz)H|CaTbeX1QJ0Vpdwf$|0YKJ1EDDu_rEXo zSJlkH7XW`ayc*Q0#EQ4mOPKFr0Cl4t!2B5~YCnmtk*hqE2SC-284n56QXeLAq)9+V zo$g5S$ @Q0uXp@=NvG#c=*v7>SjW%A=k*0yXsGD^VeXxjAKg90*N|-y2WL<#X)o zSw}MHaXkLXo0b6dq5H26!-q|B9*EcUho>m?kHNEq=So9b!xY@CwYE)5w(bkI7{5^F zTwumx0)g>g$6gSsVW5&zmu<&@VXMiDbgbsRT+^Y~&$+*5>0jxzVI^P~dLmE#Cvm2K z-pg#{;#^?zXQ!glKtR#tVuE}CT&9WlbgPY$tF>m0gD3&kRL;ygVxFtbY(zpXUh>24 zq3vQ&1V}sk8}tq$VSYnGS57^?x!gPayI{Lpk2K$t5(|utVtV`oGM>yb){Yz>KeYYr z-2|+oc1Wl#FyY1r{8i824^2ylQrp+3iYODDwX-`mMrHOKHqKa|>^x23z6 z(bsu3$3wTc2(Qg(w_2wRuc*g`dg}Dm)BN(r`=_V)i^)~{dsVwt^xy4=bxpcmprrfz zXS}EtcfA^X6V_k+!+ z&#f)x&y$4XBB6V>;p_V~x=R~rYw)FqLI~b#1(}Z{eBRb}1m#Y{cRoy&TkI!-EZ@g< z{Vcbc3FE7d9TrGkZO@stajh?J<<9f>;0l-P>nEObcXXVFHM6g$0q$*wexBw1ucygj zuIHUe{O?C0>okN(?d+F0w(0D zI_PEY_t1Pg&o!4h6)i3Q|3Rw~5E)bTom(Y!cFJz<+Q_}n7DumA2R(tXYcf88xA@4w;FxejV> z^RxueWi`KB^19MZ2i8<`83Zdhb?iQqN#k{mGaxH(IfZfIwC-LccfB+{Z@WKz_{w|+ zu-|%5|2=5cAE%ReQrWpMzfM?8`>+Dy8PUkw+vwnUiog|jztEU4vM+t$eH#C-=sR+9 zuB=%z*7L_T_^Y(m`!9~v_(EvUMNy-uHQO~tOM1@e50~FM+zT)j&0$CQRxdlc%3jA+ zsT0s!HeZIpT^59RJ#EJW#b3wxG6mxxg1rfm#-^36y6*XIG+K? z$5ZVeRPP@blYBtu!`9NCSH}5)8Hk>zt=a0|yUWkNYMkC)M}xf{!nzw=F30BSK41pZ ztGEmXPycQ^tk=rKZ=ZqJ7y}vRBxc?DW zocF~)y@*H+a=xei?X&{-ilJGx*!1K3i#IUnI|a z?d}~pmUX0{L~3Z6QJJ>z8VssZ_h;zmWDc^_9PvIcns3XUz0YS$bAG&bdrM&0PQ84zVCaaxdcEJk=q7tZHOv`)9aou%HqRsvVZN2HrHJ|nM7|r`Ib-t|e zk~%-QoK<%{q<_tRnrS{56fWaF8{56{*{1>|F_GQ9-1|KVTyc$C_Z_CO4gfyVQB zM3()PeP!D0d2y)=ThX^n`#r`}a)jQh0OeL}~6Uv~~a9%=<7@zD*B^YQj~ z`{f?{$-VB-qUBa1SfgpZ@rR?^-lbl64xi0+6sX*NH_Xd^C04hvklg(Dv-g{Orq0`8 zKw+zWmuOkr@jyE1v$?v%@H_hRfa7>V>wzwN+r9aF^ZW=O{}V+5ZAi`i=tyGADD)b? zYy3SP{o^Zxo0@Zp?Ih^4er-E&rt2;Sm-p^`q1)r`is}iTP#fRWYcD7~%Ee4=#uKjP zu#)#{7Qz{!n{yZQ{rh$#Tf=K09_eW)J?ihnS@PF4M|G%plZ@s=n zio*|K!Ge$>PQp(h?GlcKd@qX*e?{c~;VU8;6%|jleOb%76KR`Jg_$ltH%}~2)(AyB zxj^bb?*6!A>>1boQRaK4CNK+6^SLbAYiHv5nvvkh`mJYp%dQuc(7e)hGkA;TzSO$o zW-q(@_NY_)rEz^CW7X^^`+aG=nsw1p~?q#PE z+r1s(3m2H07RFoh)|(agU9C-y&4=XTv^@G_MNZkuK{CH)yxa3FJ@~qNY2a|%^*MOU z^|j&lE&to&t=miQ8)pW~!K~&f_sN$u5y&r*Z zJn^@^!11WSR{;HiK3|El3^_P7bWu9^NgM}LOlc_D+<(X=lvGDjX{ZqaMo zxZ%m-g+-1EBSwEqZ1Dc=vFPw@9lJ4yU|DTrsEs*>ht~LOO!s382k8t zd>+e@v!2_=S*yK1U$?(Ec;t4DvYC7y53e`4lVn=Ecr`8GvaCmDKp$S(Dsyvs)G~JyF<{!3nJx6i>FZ5Mlh?=Wtuf$c-s^jQm zg|=Lo#N9#rNBsXw_DsC~Dm`q$nTcdXX4!sr(3~!s0Q4;cc<*#q$^WmX4g9D@&9si=|2Ck^J5&Q$?_ysM;C#fT#oyipgL)QzVoOV5z0f!JAP~zD{kooUg=5A4Xr3 za_3XkrqSDOxU~aBEGUNDSE!m4{--Nxxs0Ej(I>WVd0%7m62;Ghb~&Rq&6cPpV~@W? zPER2|xu3IAv)Xn<;OAsCfF+KBlCIxd9SGx@i>YXm!`l7>RBj5m@3K!eJd3}V^2fsX zjoB0Vh9r*jR@eAHVZDELow1&OGU4+2QhLU`^rD#^S?sQBsBQZTr$&u?==Q4hXD*Mg zn=4)>?#CaEf(P#T`;S`wF~>oRN<%CM&5(ilH7ED6E|Hln%Ku5N?~Tu4fig`yu$xs?X9Dt?%K9tLO=xs zgAfE%1f(0J6+{FClpMOdq-!Xpkrt4aZkQRmQM#oWhLG;=em9q1_x-%zTHjjlAJ6>Z za=~KeH#^SrIFIw#`xuNfuJdf!yxRHmanV#Fq!+iXCmrhEbut-64i3l6Idg2h{%5+N zGvflbxv$F%E5=!3{qI+^2+EQAE$&E)p1Zau|9^v?_j^sxwbT5mYAc6V={Fde>y}7* zlvtaW>NTydE(>~vMsH77B=x!{sL8pF9x0>?2z`-w{SX3`m#QqXUOshxGQ9p`@1R_A zq4;;npRw)JIH-YZbncv2v0<^_S;X2%Vs*cXUI2^{<~OW8&wwr7aYe($2Hc}cf}-3q z#ci`{30xO`da$NB%8jRA1MHxGdtnM+?t~e0#CdDGZ2!QK6W9P3vsath+TLqWi#f=k z6Iubb?Vf`PQ$8tkD)o!p#Z{N5YrsdbmPa zEGX0LB=A|ux}UGjpsv=9MaV@aJkB=yTt`YMLueqjqLi5@ssX^3?cv&S!t{Aozsc`W z(bR40t3zu#;GQrDoP;E{Qk^FRrgp%6$Mx#MJ3?D7eGiQjcOt@|^Vh#lzo;j;h1+2o zH(&Ul3zD}90z|YOoNecvq)r|P;;+%;7-^laoQ7OkU2Viqtkqk}3TB@lWZ%NR`W=O4Q83+C%Hdz=Kt#d&rQ#FdapJo<5}W2v-kn6w&!xI=(%|!t#QK;ckl2a&)hXp1C{AjvtRI6tG`XU!LnsxAhaPNAoE-B=P zrXv!I>Jpd)7AP_t&)iQrZVseNK7KA#t;i7FwLm9w($VMK$~jV`nIM~e#f}NV?U4K* z(2BC*_=GOy{OivwAJgB)c9YWGJH|Yodk@bOUHa))mM%uut6Wr1^QLTh>71r7M66v& z!vIXKUd|@}-Lu{QoIOVF$K>x>k;#GKdORzkk&@K!u;`DMPFu2Zesd?$F&ov%I{wqY z1B%v8DEB~|!*6D(S>FXFur8C;4kX}`{b22Ly)J|Ws{Uj#Vftdz>DpJVMbF08mLpm5 zpg+uG{|jetBi;3S1ZFFg?o+@wmw)+jsoF5ERp1EJ|yi4wx5J zWhpX$J^x~;>*j?)+RW#7GPx2X3t$oUxkx2*puf__;F-_13@ z`q&Y{`n7=)I>kD@|7l}td%^*?c!;3>XU#lw@HD=5!#c^)w0o;?O#waA$+AL&`;kpC zs>~WqS{Qe9>oj8PO@pxA*}z72{psDfpsh!S7hQKKek`3mU-_K>HapqH*)eQT-6>J~ z>V*AM0!}%_M&AbA*1?X5$QKC^>^09zLIxrpc4Zd$u&Y{CCzF(EM6v&KnYQ0{ob{9y z8QIaogX$~?!Q$}ppod+1=jC%fqo~leTxuWO9pEB9Z^-JV%9BtB?5BWd-QBAwOVn|O z21{EL@u;TLq`CIlcs-%gBVaK)1om4EFm3}z5ORKXifC&yx{Nq51FL>U?UPP&>sp%` zZFm+$wcu=MXsErto%+m#uPzK%>%T$Y*Aqh!fnKnnaeoHc=Du~Ppe@AaRd(z(ZM(^u z_I)^aI;)est;78!(XtYccuA&VoBm6?k_rl8La*;DcJ@hD-j|>Zz$83`_ zW?8In?M@mN{t%Lt8fK(WwA44ER+(9}mfUAK3Y|GgPF?$Rc|4$K(BnzgXQVr|KfLQ3 z87~YK`0&=7%6M&~Vheuy;kFLg2!_CMSW5ASal^%-z*gcS7_-`Lg)s?(n&^xPxve1wF@Ucz)Uf$f0s8M5!%Nch7L{m-Wo1C(#jaB+jkr$7MN^`TI< z>k~Tq(x6y+Tl;c1mVKS-Vp+nOTH|n$x8Y%IOVs#$LbA(ZTqP093$TYSMcj_iNyVeD z(4pl9_ithhWHO4sZ2TmT5r~!XS{z@TFyr}in#3DKLa&CNFZ_P|{PDnzb4(0|=g;dB zeV!@eD!EENkMv0nH$YugoJF?jJ32Z!mULLPAK5uob$sQup6W#iOatH2)3xFnd>GW3 z>{q^ag_UOf3y<>`+`fAEhx3&3^;&{TYeovy_hPa+y+cFGy!5dk#zJPpz;v?#tjTqJ zQHSrGiFe)$vfSn7s7rlh{lxxkhLj_ zy75GwSeH}cq|+foSjE`wQu}>rf*lMOCx-Ikl*6poEtc8ZD$S)caq%T+(&Z8zl;Qo9 z$VcPSpYt*)2&77BHhs@HD!$f8ZNL`S$?iC-%J&!<-}lm{-*xiG=*kMYT8Wh zBV#PR%}k!<1G6M$h4PGqlu9IEH2&XlMlZvy$sb6aUKLd)Fa+%v(m(Q!Jk;1%Z$% zS!_+!aa{q&?KHoTz(7eUsp^k27#qF}?^s`jQFeNg?{GDy4W?^1c@b~lhxuI-C?uW?vda#Pa=5CN7fs?F^3)xDVv&_4l&^pGkqVF zv!&EIIphkjGcem$zmtnWA>e2*oP~Xtu`vjk-<=d`))=t<%K4Bke06RYzYLsfm8^mB zQfg`{1;71wJ{ubwV2>S+1u>f>odVD8?UeVJoc<33Jmq;Pzv=ou`cSh{L zDwX`nlo&7MOI8IN(+*VcER1OepG#4{=4Nl%V^*Fte%EbpTp3r41% zMxEX!Fupj*L^7x{MHZ%feKT(JcyFgdS;cZ&^mjyZ1&y{uC`y1fBm{S zg1THF3*m*IRB zg~^QCuM!%@eaS)_<7Mff-;W++E%*5j1;51@>{So)Cp>jo|T2) zGYlZf=G@)FRN+QjizwiB=?Q#x_Zikv6=6=H=?Y(E z75QT!1oSPM?Tbw6x$fOEa%F0LyO7?|P;V_@hfv+0IoiS1w$?YCPFW8^JBiel z8o>-sPuk_DiYJvc-2E6rRHG*sH1{fy2GZTSHRUqz?ZztnKK(|*{c-!Zxosk~Tn+qv zQJ2DTHmX<4T`3kjMP-A7^071*QTm8^p4c~tu{KMB0n;u&?2?4rD|G)vFO)0OMk{ki z9vo7rhC=%&-=T9M^yC$nLh;~~!q1P?oZ04GQeeGEMKiRxP759kDL`o(LPCo+uC1#b zEtzVR!i$@hN*+r(p7b<5=1G}c6(_ms=;+Yn#V;QRPI^w4=Pn&h>s$|-xm61YDJknMQ9LAAl>GJqnK~9*>$kPbiA2tQe0+cr?Mm<0R|~pD8dV$& z40*sc^XzcrKI6-^Ux}5KmB4t*`GHQA5aZZgOC%x_%sB|9F&ip}qI)XdRMbuU_jm05 zl0*>>diwezm&f`Yl3ojYgI*N%r^`MxQnPQ3^{{gEfG<_n$-2+X!OYl`J+&%)*ibF^ zGXhK|)dc(XF?M0$6G{zF`T)MJ$b5t86Mu2=kpTKOH_?ESp@ zg~XpL#cU7;d+g~*C^x4>0*bo-Fy^_^)10qQ-VVGSwO%kVh;uE=okgJqYl<=o3t2V? z+y#-bxc+n%7^@=7^2aWuH2gJ-wW@40HL7g6I0XdM-`#k2_EHeo!0W2CuisO#$*^?H zbO$EeZ$il6`SwY&pmKd!c@b> z->vG^f@{N$O`OuP#h4+45c|lE9aHeGf5A>-RF+DS!Pqlt{75m6@TXC7%{Q0Xef(U# z*KJQYrCbuUBoEQnYMMRAAjACNa!p8zC5JJ2&*3vhUfL4(S8u$qTG|rJ{5!w0Y1GFh z>6dTs$9Mp9u>3b1359AQ`%;WlVPL0!=)ODlbY$bLBR-Qln1X6&!USjEZvL&IV(k=v zsYk<4sHr~}#-y}WCkZ%No$M|Ildu|zy$>dMWB~tEf-`I*2nD89s&w2PsSSbOIC2Ev zanC4v3;VLs(JlS-#UH8n1JQ87KtE=4IsNt0^DZ@KSTeXf`NVMX#}%^-U*cKL4;)I%(S4*aaL|f5hL96k+>rw8WOF9Cg!Fce6sTT1^6sT>ETK+df%HhZ)@IXJj{V z$K_!BQPy`VvJ`^Z&Dl>16B_HG^A>g_HTR3dPn_j@=S3Q4i?r&-Q^ou>YaDmf8?)q6 zge}I{4)k^4ESv?sMFiT_dy!fTx_K+SiZ9WXrKCE+h5pU0)W*wi^Of=)SBL0XF_>Bu z0+b}#8+T7k8*eL$V8;Y28wQW{pFC@nKN$(%rO=T9UX9(~*yG~jpm*xN@3Xx3#7zzU zc|zZu=l#zBe7{N0fFAQq(D(gL+-Hvn@HL;!=$*KU+N<>}Bp~-G#`L1sogR!^(Up!- zy*613@w^a-fU%WoAeu| z-Z7z-S&~|#In70vyKMBcpXT&rZ^>zEswX9k_Bs~>zxK@9wmXQ_*k?|1PYmXGJCa40 zD{(=xnAWD%8ps!X=XubWW|XVla0x(To?`9*NV@>N1GmjDYVte8qQ!1HN_mR(+}uik zMnMaARPM?8Xfah?K!1P#XB+}Y6lO5%Q6G&%A;JxDitQ-u!eZ)%sVJzNA zEWIvULgu@4c9cmu#KQWPV`lp%-TGbS`L;$q0wH_1zC9LKv! z+x^HBwBg>LcO0n_XGtLp1PaO+ydLMrx9-!vmXJ_*0`N5-dAF9bB{zCZ2|Mig~K0eZ1L^_cPii`&Dk1}E;aJ-rJ=w1M zQeWpuBL?^`UNu^-YOA{x7Nq!rA#<{$ORh=E#e<~F*;@I7CNf5UK>y{!heU)ZQH$b4fauGS&AGk~??;Cd!@ zYej^QFXml(|KUv@07aqQT6O_4ziLGD`?1%!UF%rh=9fVV%X@>$&&)E76Ta@ac(t7V z3_yP`D=Q0-dMuNwD2h@T`i*7IR5nv88bE&9Ls7j~1Tx!eO2oGV#0`y%1`f6(s3o4w zFeGW-0+lOtZKRM!I>x~5OHfc+zR6UBn7i$d5}v%J?U|;lgJMsxUS$vj3&I}f&eg}f z2|b9{Uegu_!z$W!fVYAQ50|SHYXN)jD5j}dOrD*lB_iUvdq|qP_@=MB11aCWeWO>% zg7Gog&mnJ{8zY~**nQp@6dIb$u8-~Mo>cc81jiWbfi;i)lDZHhCI5& z^U7m{Hk3JcjF#y*T|pD-AB5V?<4=}FpqT^jSWvoruRyEgA0pGk^z-u@_)ro{`tSBD zr-VpeE!&SrV!M9~@3mO7(CdK<1^m)OXx5sK$@t!ceJ718IVAK9N3TgyMubfj4VpRd zt9xY*OR@6oRpP`16CIxgADro=FDd4{*99z}y@L!1O2BCo5WzSurWdCN>5TKBD&;mE zc*f4Y1K>pI9ZkyM*dx6UG*Vy3svQ_D@7=ri^bWQA%0Q-3PkjGy*$*9OU`@G__iZbJ z?lC0|iQEYUTe8 zgU{ChOXPI_-KZCW6qxw{#jMwtgi;6$Fl5=naldt-*BVNMg=*cGLH*a zV$&0b>x}VR5)Pr^pGF`M%grB!u!(VLOh2iWDHp1F0_R|msPa(#Rn2mEZG# zE}*C)CMS2BZ@=5t<;D<14Ddy0k@Jd_8<@n1h=|$YdV_}dDQvnw0k3OwvTIl_QC)kr znqPcODI~*^(};yj{NCIC<~qHFq7m3_xvnAPyvh^vtHb&B?WIIDHQ_8P30$Tedd&e~ zzjk6X%*s8{Kp1rFuMFlw^XN3sgNb6kvaC!}(uxs%=Q#%)9MaOfP^~O&G<5oor0@Rf zusO(PL+j8+XNhEC-*7DfhM2l|#T2>}Xk-~tP3G5-XPLr{^3X|gE|bT61hCt)T!ei$ z_;18~2Y`RmmqhFMe6NpUi!BqIio@V0_X?;=Y1|gM0TZF3?LK@EA*F={iL9=`PQnxO zzoS`ZMifkPcC;k|s1iSX^4%rAYLoj6(B1itb%@z$kq{^pmzPcA_W)__xHaVt_FPbQ z)T~gR`DoE~Ewl1WHybBu1A+b83+p-#w!8+3Vi9xHYT=t*clnfx8j4pp7HIjuGR^_zL6F#_zr zkj&-S@IbDh;Bcu>(uG%67mw+=7O}Ok(aizB8!O#L=AlSEF4bk3a7!K}Rd;Ux_!%9r zw<^%aD7a3{KR#hmc^uE6tQ(knjhjf}OJ)7VGVxqh_A3LMlQqC=yJHlnrE&4`>szj8P7QAL>=?`0lqIwfvD~x7jMuoTM}|eEvY8SvEq_GCRTH(~Yj4eB?+!n6I|h%P*JczJOaMj=4!rZ%nZc`;n;Vpq*! zJQp$eh==LuGl6iW^|UauQQj$}xw#qGmS63(QDw^}iISoR1ugyg?!Q^WlVeT?H@WgR z(9I*YvWLwrHH$6kiq^xZyLnXK83k)yqnIcx@C+0;d#AV~rf|ttLUm_MW>4BWPZ%51 z%(qrROiSPi!Qb!oy8yAN+(Kvl>({US=@NS%;9b#-M~5hDPY_F;c4$s3ZRS8=62Cw6 zn4HI=GC1tPZaQf__w^j0ZDIh{aqUPGf5e(13ia?WyYL(sA2NQ9_+p?7J7%bkE#^%sJFIjt0hC ztttra8)sJBlKG`hv-{yn(3kMF67F5bTx*rc;rJ`dkaR!ZQ%^66&_6h_PF*E}s>J*6_+HmWx>wvhNlvM~5-PaswVBR5@HmbpUs?Y zK75j| zee@N)Gc(0YE-5Ate%u=!lbbaX@}M*Aqch{O;kAupn(beO7C7e zZcdy?9c=;!@n35PedX3yXH#`djd}0u&%d$jXT6Kt?Gw3DEYfgk2_g#PHs=932sGnk z=`~&3f2FFhXkWv8z+o-*CbV@<17@(n<6;cTL&wb>jrE30WK8FU!>S?_TKhwX6aYOp zY6+=BEfFz)ywp=4Kfh};alp}>%n!=7@CQqLNOwIb-xz0xz`U~3{qHb8B;&W4Z3gq& z6~nwX-Qa0tWCS2wg~gp?xO$ZHm(;&xc;dXU#);JSITWSXsL$$#GDe`ja@`RYP!jl-6#gMQCIg|)Wh zx4^)_wlJz}%X8U zeyZgaJ9p|}$YHJG3S1B4QRCn6_O7DJl*wfLmveU^3U>z?m%w!KJ6EY|Sq+*!( zp3>5?2huuiryXvfM$=sE+8RZ9Qk=rb01P2f$hMk7WQqq9Ut{Uj4!ST(0cC(MsS8a6oly5j^?3hefOrS99EetD?4OJ3aI0l?Y(*9Y-?V5H{g-UWR5lA&4qt7`!3>V&n{{H79MiT{rPR%WqQ1LkrBRomt7rpv=@L zUUXu)=gwp7c8lG5#duUI`~b=bHkx#utq zvczpZ(%jlAk54C)__pD)Qm+Qr6zYR>vb;A56F4mmz*Cr5hU9!XpZ~37QXFtkndT}CKBJuU^ri=_4ey0wnY5q><7Gia4BMUU7)&t) zpx$;oPRqJ!KD=u5#&7J7-ddSCY6Mwi$o!6#v2Y?wCgGvBdy8wx!t{|ILBT|0=b;hX zaw(Sx%3|a#*$v2_q=x3(N~}XsX;kxiv|WrLxJ51RHKAsnu>m=59!^YwbOckQTD8T) z8i{T?Kw*73YF>N87~qt~HxhRcR1IB_GRT%yn4KLdR(ArA1|qRsoM0S{Fd$xPFF~VY z1FV10v*Y5Vrq=)U`v(g~K@^=FkLPUQ9tq1Y+N7t{pzL^VPFzlsw}de4n!tvfv#me| z1_wWX{(Le3hVD5wq}Ng6;I6t@HayuJCYO z=9|Tu37xuiDHDf{k?UgGb>sP?4Sx92GSZx+c!*Hbf`)+wMis!4S8NqGI78N{+P zN#7m?3W4ZIg3ML$ze6#mD$)6uw~Cj;>HZ2}RcI}yJpl2KIGXCx54fII z%YpeNrF;;t6XN5?bM@Q0yWer66O+@QTi7C)Zh*$`DgXgewjAW&Oc%T3w(8D`Eby4h zH(2vk{QdpqQrN`+_2L0^4p1R;;^4XmP4TxEy87a|^QA|NEY7op-OpqbU-YXcA^q5! z{QZ4>;Uws3PhXG|BZid)yZP)E zn`Pp5QRSAU0%nd3o=vSGh`Gq!)<*e>NrGulDhi6aqoe7Qmx|NfDO3+1c4*g6A8on= zN&*!9r;rjOD@>+c4TJd(h3v#6Ha)Ke$5E`)qT|bo`+)Du9{$!%OwZae0E?JeuRy6W zEqnh{@d4=PJTNFEx9S9o8ly(AGA(*v+ z2{4TI#@0znB3Ba)o}N)1_FHvF9%SVC2%H!L&kTy_K@h9~@%7W#l}u-0eqQiu!ft10 zM-iTrle52XkCbsS0N;;dyyD8H}hG2h!1*aFQm#XQB8g`6DB zv!jyFN(Chb4IkjPnNqkUEE(b!y`TcAc`Xj;My*3g`JjI`h)B zHO&+3=Bt&hPPpu;m6|-+RMbEsH*=&wLViXk_atLQPWWVgEspbu>IKYnkQOvxDD<1K z@vWw6A3l1dkt*s7%KrMZDYw}iCB#nQ#AbXdhuhJnklDToRXwA}xJS?wnp()BnNhhx z4+SP;aabC2Uz+#~z7*&?MD}Tp@1v%~BxKKEet(0PxMn(zd4(H7HN-4>s2~v(WesAZ z8$$02)KFqK3xB+-Cj305S2oq&-9g?so}W$l$rV5Dt3LQ7vgbZjYXL4tN`Qs+790Dav>`9E^v+ z6^KvHy#785#!$}Px~`b2whc3Y8axv_V%A3&%afJMQbnFVrR6y_Bl$O+Bgp)_5Fn<|l@RdM5a+Vzr1I%FAn^=~Z|?wO1Y5zLR2S-QODO~O*{%c>U= zkC68x`Ty`@U^aH;+`Wjdocv}DtA!8a;`w7bK$~+(t|scA>JNl-yOfo9yH@t zLy^8z3u!fJW%hZWc%JyNGl=rv+=>Mrr0htMSZ29QEx3?8MqHn&dORPj0Q$6yBiJc=jj1@b z5D*X$c%N=yAJk9{$$WMTav~>(q<3{(3CdfZ$cF(K2F!W3u(D5`~rbBH@8plVjs}3CbZ1sm8SQ@d?Np6eZ#@Y2?*30!!_lR z8=yo#cIY9Cue3ekxPYeGEdkzpkK$l+Qh<|MjF`bjZ=cg@eGG6_gFaftDKAXr!N<_J zc^Pt%U7gQ`0Sb4ZxWCB{&SnnY(fw>cHSoXH9WN~UHj>u(|TENa95SOaFFSi1p;J<5Y>Hh-mlRz9A4DSWh0oJmQMKAnF9OatL> z!J9ByqlYrYB`pOJT(4fK6>bPbZrq-1GX-JxI4LrHODH2xwa1@{k$<+^=$<`pKUXC6+mTh2_JC1x7^xEq)~O z+5Ih6KL3DyocRgJL#21c&)iPM5(E|{@CaZziT^((&~*N;s(PEG~^xJcU30 zeyN2)F-c7z@`zLKMvo#MEJtRfK=nQah0t~nFQZ~kBd9I;_CPXq+CqvACj+h3hC6^a zv&x{)alY0kGHN~6$N+Y)r+}<{FDlX?)7xbD zP=Tzl)c}s@67YyHCi1WZ%ph72EwK*VRF#WWTC!HF+G>*Dc;=4#yE8|y>{n+=4Nt!R zJJv%u5Y%OTM+4qUDOugf$i{2N{)3v9x1-w@kDRozASo@al>E?d%w)WdOfsx$r2&hq z-$YUj*@MV;(HM=6w?U0_4nh`)8Avk(+S)Q)AC$U;M>JEj5(_?MW)7UxO~}wYRKgRf z?ru>?=)$fcj~)pDY#fw~ndYNEKI80l($UZqUM`R@Ty3X{2}Y%9A6*=f^pH6HSOe|b z2t(;uzI9FsHk3Pe3Q30Uc7UfaI@z2^r>NU$B?l72ZOaoqz7tkE zu(nw1kJI$XT@65o7ep^gnRoGAEB;g-+m_OK)`Z0!vZQYWEgu~%?A^yEWpC7buqD;i zCr>gX3qU`#hSihVfkFpMF&eCVG>k-?&y`eFNlV*_o$*KKug>00V?p$wcAzb>C?{xh z`O}xOxORY^Lw>#N8Q(3Kt*z~)fa$>gLrz2qBCEOO0Azho(`)$QKmfz^iOV(Uk(? zd}Oj3(yFwqf$@|5II)A&1AjE>cZAJki1$VV8InM*9kq*yPVu~qW0A?k0NXwB1-oJA z14_lf5aQqHF$IPY)6m=yGQE6aQ3Q2)6_8@>9LUcX>?9>&{>F-V3J-H=Bfr%mE2PDm z8Ky=8)P2_xge4RXxEXY%f6@=y5=cMiRiDY|(WDUs?gwVYT32K|Ox(;pI&1;t zF}Lw$-bv|^vuIRqi`=K(E>e%Yz?}_F5}598|46RWzyIrrSPY9M85!AlwM+tQ!@2wj zOP$-%$l3vrss6TmfLY*Zi5eKS5|$#_a;CwB9iN{8H96qrPF|=+c2Pn?Yn0dD5^+L7 zPp(b%h((ovDOrwh&D$4ET8LOj@^EI_g5n-G*{LZUV)xFdV~Sb2c(^=Aoe2Xpzvt7+ zd((=}?e0Qvcz7)opw}_x{pux*)>U}*HFxYc)`yhYFTyWV+z(ZEMoIwHcnOdIB`34lCo)J?n!NtnT`b7T)vo z2K?b5A`6|jQEBO!*# zIJtg5su0Sa)sr~_kzc;k?cgcA79u9lx*S*4RgGVxd|z*}R{eCpcpyr$bE781c<}sZ z@^rYkdcPbzJ!lpxS^4n b6C<1~AgZbJKFSG6{~o(i?H(OhfDQcr@hd7r=;RaH@# zbNWMErUwKmvA=;Z&e1=;q+MeE> zvcKjVtr_V3#Y$Bj$*3c#aaC_w#ac~N_N!Kk)hvRQ;LAr@k^%i(W;J4IvMG4Zp^q2l=+*32?a6D+Q$uUtZ>NuuZ#9TlZe zC7%fhJV)Zz0NqeZq47(kvGqiy%{6sEMt;^CaMyHYr70~P91lVLlF#g>9RzvXgb~Ox zH_~)JV*?!s-km!|?^8uVzL<930>Gu%ZmAcag2Moyqf&%yc6xF7R>RdLqmb)cCnGV% zKCmnzn-p#i$}6l0u)9ZRoUFIL>7aa8ch)Ol|3M{JJ~K8w?aunNT(si4w|Gmd$LR`K zl%}Kmb&i*xuq@6UE`K$Fu6l10Zy3uRxg`FBeFeD>3BN*HL#U{P>~ok5^|25(3o8(Q z$MyDPk7cGt28HVVFU9q%lQm8=$%)>fM~(874U@tRJ)cv3@9PBKjnreM6K;;|JP93) z9C-g4kM(sy!g~1&8<`lhK*J#39=^3qngpYVIIL_O90TG6Ol|yoyC<~0p(^k@g70kl z7a36R;i*Hlh$8dlmAKz&P-A==+=NHGD%zI4Km&OY5=IHBZ&7$Ql1|6RR|Qx+F+V(A z_u?_=DVrW+NrC@CRGJ(=@)Q)1h8Nk(DyPq93=xEF$fC^JnkmQ)YAfkrgPP0rlD_N1 zXyM_H)l+(mYmB&!)j#k7k>XUT>HUoW5BXcOA3p%KHWgSwmhv@@mK~Qb9w>8c-E5Tt z4GEE?4l4KkyXu~^&4EDAkt#Hh`@-`Q%H7uPSZ&h(G!Jw7HQdFNe%Sj^^lAjo4`b*r z*LFW3y6C)Ad}G%vmIbndatIl>#^3nk!iGIE{ZM}M;&XYeRDuAF=^l1t+LbevPF1<} zbiHx1$LYB*F5-2Ee>FJKHm$INqLWDha;rY`;<8%=SMyPFw@sWrlKd8eJzJtzp1A=* z)XSc$R4?9L+FOGnPkR?jbXvqm9&_3+zaJ^|qq%8@!GttX)#H6ia=_3rgu|**JPzYQJ~>XRpum@MP!il4Fb2<0I`gmO$RN($bnEgY8^>T zF$bE=W98`*VOipW=63F1`ULmzP%BF*p1mBbj<8x?q`b!$Ae$y4h*9zKRVa`G3PGbD zS(KlzZ+{{nVs|MaMgQV*Qp~ltesj>2Nzr9BKtLgpNV~;e=1M=4A(-yOQ0_Vg2OV9u zw4&nc*Egs-Z#VY$-7=mi8eIGl=}V~7agWd=S8gy=?DL>Q{cQLQwEmpU7j-f8rJ(st z9{#OkgV`svsjjAwK+}$&R(J{vQXm#SM%^u5Fjp|Si}Yi$dSZXr3AnMUoT^SVX?SWP z7DP)CwXv3ywR2bJgjgDqQM*(QBOf$*N<*^%gk2QZ)VmtEfF&FhsiQd`^v{oX_NTz? zgBy|>rphhV)$BlIfl_do{CYf<;sp9-y+4z(lU;#M)NX9@<2+~vSd4<;nV~mYsNS~d z2~;1Y=6QH12Ov<(g(wTv-_dn2l6aNS4MGrLo(ht=>I^y}!GIw$K|>52n?+~N{G6t3 zY6{Bv^_LJ+u-fB*wgw!p0!s9@FAw)XarLVkcSd`!#WS8?RYH5U%M^g)6_pLC&y?(}$LS{oX!IPgay-)VaSHT>MCwQVdX@05G8 zRhrqrhlk-iCB*6|zg_ipOQnZa>UHCDuE*1hhOuoU#93>Vtsy+TQrsNl7l$6&RyLj-=G4C`qDm)x09jLC!Ptbp2nj+&eA=Hjrv>q=F z%;cQq+%=i?ygEw>{^(yUNAm)80J>&Z;3TmCihDQ?N6e*9x|ewmoD0_PCqM-ex3snG zWimC+x*15TnhG-ONw7PvLrx{5Q%~$ShXIA|k;#xN_(qvV*&hf(eSCds=;)3B9-^Wq z>SAaD>gB$GfSYP5v?h0y3Vv12R~>VXiif|+oj$=x+z)yb|lbmSd~~!lCqT%@v%7=O}cjGgS$Zc zc+XnGE@{iA_<5^X@zLyu9z#rNKG5qR>l|c<)#Ad2c!e>Tv}Y#2zc53AINSdkoPYpg z?bz_}#z?Z$=*2K9k>n8M>-!*K0ihEiuAc!pD1c%KxEG#Iq-qAIN7hVo*YJirbfsw? zts|o>1#}wGY{Yn?qPt1@Pr=p&bOcX68!jy8{Ca6|AWI9#A}{VTf=^i;gU^Agr2P}m z$Q_2Th$|ogP@Q5A;ZB-kAK)rh0((}#tXu&ug^)r-k}#_^W7|0WySn;GA?s`3-cV0^ zT>eg~gI#MpW=nCDrxIT3lQ&Nu3Be5P4BX|%-cjD(mUc&eMkV&dZipUkzc2>BIqC_V z`zqkpO~tBkp>UHXGn-M$Ma)X_=VJ|o_kiYvXgjYibM6bR=vf6^C7=gzC*M_hT^?Pc zGBSwPHOTo&SsmoC@~Y!sVsiOCe0OGh`|!C#w$>k^v06;k#*HiAvwHHt-}s({*pVxJ z(k;N`Yj1REOKU#TfBpLPOQk<3)rC-pqKY0aZI}GPbl&Oi)5cGF21>K03s~j(J`-*h zO{*u)cm?P0yKyzTk78fu_f6t36RM7eM6_U7;E2uzW}o$>-+S4FuFX4HY$JC&kWdk>w0k2fVm;34 z-{rj;W(mLXSWi77Ce9i*YkB8$G#lY#B|ODk24MnmqxUDpc$sYW-f;bS+0X&|wLAIgiwAChVH%h@ zE-Pg*pv!+7aZSF~mV-S5DhHxwx|%oXrl8UVO6r-d>R**Yt$-`J4vM}mU#$KliuT$D z-}kq!4;2yqhx)t&x{_L=|I(Q6Ux42@-}-NR3J{#XY5v=|#6&0div8dG<6TQHhmCRW z|G`T$C}dsBQ>>498s+zduZbt{dY-JP^@6$)BYe-&E86n*?h*Q5>h?yCPTgJbP`v+} z5B2YGe2hKGUahl8+dW~tEW({Yzy9*)k8~^pbNk(16^pCT3Z~aW*V^6Am=H3RkTx9I zKIlrmtB8!nQn~P-=l1S1^&+x(PQ9SfSoHrBD`qw zf?(*8lhZgnlHm9Z>(4xfD{Oja5-_OzbZsgaJtzKf(lQA>q=@AK=Zie-@U;1?WgE2W z2u3Inx?c8fO|{P%c#Wz(WzS~vGwR%^(z^INEcwb@>UQNB@&;hhksE1!9>e9X+qtze z%^0f2@Ik0{;6cOjs>x?@Tw>JG!6DqJe0aB7!lKSDe?r@G@LpJ}!P?t9!s-2j z($MfzYfMD4!p(<%Lsq`v**`=7QfJ2lkEuod=8CB4q}_TlQMK@Cb+6y8dnsbEviH|$ zt8c-6hJ`4q%Uaf3vo}U&jThZ^`5sg8_IWtV&WKYj$MWl`dJ7!e{f$~i;f^U8??U~W z^X|gD_c~StOxZN3@<^4YgjnqB#fQNF+Sm_k1=Xr4-by;{`ydLTyP-8#>zNDKCqH`v zvs*0pluP7ss5O#Sn=;vLUPxX^c+1ChAa=o?DF;yk*tS{x^IO9`6o=^Dm<9 zZcpGhBp!i7U^tnzn{V%JeFs3Z1CvQG`W$|p{E4^d^tb;X)r00V^E7#1YurIauk zSoi`v#u$BM6D6j>*Wk-`q|KGd4)W_iQRk)Co^a!?hQ~mn9yna%6&v)NTGo*ql88-MBw{6eK*C8-Jt7zr81N5XNhL{v(L^c)c?3 z{igx;6P#yil>Sef?KTeh4eOs%FyJkpKl*?8<9d9UR4mKJ7Uo|~=FRs&6aY?k{l@?I zvCw?~*W>!XAruHP|KBo-v*qRa$z>6SbAiXjX`y<>p%XJ2TBAN34hKJc+0SOwP3ozF zt^t~o|KuY|KEiuHX~~QYpENSquA*{JTETF5zdRoc2?3He$ASj)8-&Y1!t0C1*a(K} zpAijvferbLjlb)Z`Lgiq*9WK9XXU=v;iCA>uyK@DeybY1N+=S3(37 zg=Z;OP`F-81@EG0`4 zVr+wuZKiBlA|^}LB4m#kJI^t?@85mjzt8)8p67j^_mB6Tf6B}?*PPdR9_Mi$%lG&m zHlNE~l9WC9o_=`9v4aX?p+d1oPXKHc!f)dYci*gzHO2N~jC6~oeFvd*hsOUV7{UWs z8;#$84;}3SllHaqXHtSYkd(Wvpec$yja^{U&0CWf>Bu#&$sMD5(MQpWPZPpZbWC#4V{Gngs{p;y4}FU&zXu4ioBwtB4AB;1wglTmBZ4(>*I;wCszM# zSD5W3rP6|z#Ebwn6TG$91QBk(S}^z#6$(F|Tr3_Dy?}Easl7va{?etkS28Xp#R#n) z^++m|^=yMOhlA=>3z=}1c9Qc(EZP=wEm&Khnc5D6X;cLH`tgT+33zbe$bRDHHHj)m zN)VAjX4gU(_yQ@LcQn2vh;nP74G&ZMWsBf9AiB|4NP>Q(f!$_@>k5QrzQHnPhCOwH z-@2X)HA;1I#-M>*WRaj>9CEfx*ZA-Rky(|P-bOq*jQu|QvzMTQf`oiE&*`s`^-o6w z(N#yu^YG!n^u+V`4=GX0OzX3s8G|Q}1B-zCmN>rH?Hk~pPs3EDP@<&X_FgTyc4(o8 zk%fhYfq`ep?^$X^u?;pb2Suk10o<`s1ZwlcEfjixJF^K{`YKAfi4J=lIjC`C6D}V z3&gC&@$O98H7g@}o=P@vG4F3Wq0%S7<*ajJA8Hz>RyB94f&4g*Ak0`R*H48vK|~`#Ou%Hc%#XhK^zddVWtxY8E=azR~g5`nt?!>9@>jGOO5d zmYDn~c^UJEyy92bF?=ud%^MSSBWy_XeC)={|IECh`eZ zouU6ec13myt?`@J8z6bqbj7*0B)*~Vy*hUEumNoRAiyD;sbuIuRJFn8GJ~ZYCRNv* zj>|Gd&hr}hLQqkNgSxL@KUPkbuqGU&D5&fm8nkhN$p5%4Rp}TR^B`q`1x`nWNxb%N zI{3>G2q9J^X}}g5QYGQQiBT%{!ap6#8z;#Hz?2S|^Z67L67W?gVE)U-9;NQil*&c1Eh*M)3yj%#eeaKWFIdUXItK4OP zlrsSs$&%dO4VWQg4E!qB2o)diRB`>KEf9*2b`coX;Bc{ujGdnyDvuvM5@C)Uy^@a{ zfbh8nmtSZH2?eC*)zH|uQALeVry$Qm{Gn+OilcR=2Tts^UHb_rkf`$+qg{ZvmiM0i z?j^7M2f%TS zrXlt?Ua0cdL!MJM7Gcil^y1+egX+3ox52#2bG0q;Li;Hx*8?@+rr)+$E!EXm{C2m? zO-rvMuTvdkk(E?dzRw5IqMpoFnrimIyG+8hnP~u7-|h&hwIp1Ha|?i*P4%=$T;cqX zMJ`gb-02l6%X)pcVPNT>3+Nzq&%c{FaOrVHAt`%(ET%^)4Xj3x8gZbu|s+ zQ&gfJ_L?nStYrHMQq~C@^?Ql3s3_=T%=yR7pZR|C4|-Z`2QZ1}o!7U_f)I$;eUr5_ z^u~)-WEo4QPsb(;lZGzV?u_k2_!W#__UkMViY z=Ru^Y6;>u=-t~!pEkTCM{@EcCl24;p z#IKg3L>(Ii0ZMcjxQE1*9|kd5Qc_W+Ded&Ge3G2)?P7B3&fC1<<5Sk+2(_&KfL18z z^#eQMh$R`?%~&L%t<980JTtZGhwfZb_e^il^Djj37S4%1Cl?u36H=^Znweo_keqIN z`VB_*QMaskjKdfwM68Km`o1=&IU7>XAdJ;4Rb81jG}e6Q!^k3wtSq5Qu+bGmG8W2V zPHnf~+T>`8e0Rkq;?h-7>&~2?PXJv}G30hzS7 z48S2_OV*PXvbFewCw4#ORL4j+u#4BDt&8^3YA#XgchIbfj z9YAgsoD9}J8tJk1zA7?-Vg zwr4DAg14QQ-q7q`^{-Vkz4I17G5Mrze@%P&CK$BGSxtnE_{5H7P6@>~&#S%li>J~P zA>|_Q*#f<8j#Bdbx`krYW!2q8oP^y8Q`63=kW^0n*g2X{uDQqqM>ngf>D*bIiNnw% zo-^yly{y(Xm9c2c1^P6DEv}QB2avPP!^Puc?X^$O21kFTY92;#)LQAtzo|i;u?eM`foJ8SF##!vOI{#uE`{FHU8qPJ#Px%l%fY7E?q& z4~oo#_~G}XwLHzr1Y>k2{TV6W>bmie_N$6PAFU-ORq)nRhVbKj+DVLDTrnVffvwl2 zva&3c-KU)$P5e6w#Fy5+Uo-_6klYfteLCoIZ+emPuSdrEJR^Lx8LBmE01#h$8_+i_ z0ba9pEs~Saf>SN1;VL(TckYsFh55YB95&+Ey0blBesmMfJw(Q zGTX+w5V;6ibz%e&sax{kJrqnhi|mKTYJx4NCMf_&-25rjAqh(lpxd#L+nV^@{q%w6 zAy(8@ttyL}rX1ZSZ_KUCr9LJgvpBmHHv>VP%g!M^=wdZXVFj+^!unU>dq8O9lGzuf zxZ+8>Hx(miASWwP`e^B$NYaB3Ub7B=w{x*^dv-2lGJ_xz4(lhBD$6Rr9~I5*clBuh zo6Y2Jb4`+bJ~>@ge#SE4(nGgYR!I)^$=_knpR-fPL_;G&)E+H`mBj^pR5(V_>VC7J z2~SNew)n-SgX@9`@8>4>)$6n(8wXOs93d4CeR_2Q$We|q!cE8l{fJM4^VP53z2b#x z@V#_a%UcHD=eW;;c#|yWg^_w|o}|O}mEcm$GkbNKMQStHzhSiy>PcInQA6{7rpOED z3cge+DUe5e+j;PEyg9_$DF30lXOrI|WdkBp$6okQjs>0uKK* z{o_=q(UJXjO3zNYRdx8@y7@ye)i3(J_#F3jYM`OAL66HPTp6LzLec>+>&o;k_1qXm zMQm$Ojp=hLX2iL3HsyzhE4?G_P*NHRBug9d9MC@GKeEr!6(PtUY)BNLb_FHc9vzAr zKMA2iEaNk%(3QY=T+TbI+5?gahsV10W|XS5jiq7m!jF)u!Bvx11#%HUMI#PhUt>jy z)V(-pO!5`}oGBQzZ@n>^w?K{iWCT#zkUh4=eXs&vr~IT8TNeF|XKv$W3YAd5`E^ol@$u7g0o3UvI+`_-Jrn{5!IvWqB>PuV zbxGV9{hCK`>V87L2s2I4cY6 z681gi8%r*N`E1+VT$U8Y9`vB+a9-!s`boI?FexPTFc8d+ix;m9*Er}sfrH^GA=}d< z%5c6)TtMLcXTD|5@zJ|9`_=UF`(JO9Od$l~hvW(wvsR%;m$)W#WaD9H0V89l0~1}!)xL|?Iyx~W+O+%C;)M+7L%xuGK5b9Bj~*>akNDeF zC%Cp(`?-JE?VgoZwb+0(FZp|M7@m1#bo9ziCcLEeudL0NBhnCeU7ntJ{jHnEL1+8B zd;jq}s6B-TqCvVN%v`Grnm5acKRCJWnhe*X1>8oN1OwiC;YC4_Ju&CJsu(REv{g3+ zQWc2!GX;b;Euaty@Q=S%>EqWicz+c6HSGh*BBmgT``&BN1IU*eij}jfoH4{*v)iyT zRKM(8__$(R9#4Hp!a&edH}g#9dF5`@;B*6g{hEA1&45i&x_W z+0NvtbJmtN$999*$hN4J9+DUGPtdfL*o8*q}y}p17(yElKn>NF7d|<2g z0Pehhe42#NI(jDW%89U4`Z%sTaL9is+Vr!1 zSAnhV_>W9@*y>-*Qt)GV(G^hqiB_E*&KZI{3gN*^>i_mRNEQoeK_0QH>#DnVbslkAjInexdh1@R+6Dv)fxi=YEXvv+?;3s@6QUrPpV--oDYyH_ipq^9m%4KL%>+E=nJ$5--O;mEd@T$@(j~w~Ol|tBH)Oj17n9l1mPesc1HQzZb zc)=<7)n$rbP904sV&=|6iAWYvOTviQ#?F*|zhCM46oDVNrQLF^1Kif^GE1QAdNCa-)UdTIwR-%Oc31hH%d_zn-7b`>nqXtY={%?2Py8 zvUrakrh6akhvHC!j{|oi;u3FQz59^jH6Mc)hKH7&O0MZ{mHOAgaO>)luuLe``iSZ7 zD(;zY>KLVwbvxue8(9H~Yu4&mZ;nVqeKu)cLZHc07j<4xtDN@(CcTlyybVvQKQDmN z5ek*16Hj(~H{Hn2{c9{sAf}M#JZ333z|q*8!&3c^<65v z{Up*|%$m;_`$);b!;CGSm%w3u2ySlIa+_azE(4|8!&lAGb5(`CH?IkbZ z;jUbIcq$Qc{$4?Cy%JVPvyApLPZu$)wl0ubaEXdBwiMTs*_thy6P7 zch5!>ek+lN0+|T(De*{}7CtY#=TVj?BTkFR$7Jm%fB&NR&ZU~=K3+{46eC#_rJXb; zsZSHRZ}4Q-g_k7wLdI-6{m$Y<-ag?eiA&=K7!LJJT9{Ssv|F!*$$FmWa$eBub_^kewUo0VT`i;X z%NMS6CK^f)$vv=l@FUS&;13_Q{4Fbn3Z-rl#uO4(C@^Ho@-wdJNC;2iqH9Gdtx&v( z3O}ZA-RQtgUc8XW);9}WieT?)yd}m#Z9FCC#+#MpEa|x`W9`K9!_1kcjIC~@+;`Ol zH09Gu;C6H}tG3)xQQ0=Q%1s47CI&yoN5;%FPHCa;aDw&EE8#qXgAWoPwns_fp>s<6 zP!BHdsrD5}$-o!j<4>@`p8j&CXSq5qKJp+8_nX9QnSCFpISdY}_F!=5ADuO=`Tn9KbbT54NhA!IvhJ@5 zW+xxHHVNoD4;+7^T#(=XG&4gN;&8yiA*T@H5-vYheARF0+eNp)O&CqKOt#kzJ|(ED zv4@F|b_=x8FyYQ3jiP(OQWh2Pspy#%q}T$Md|mqPBKKBM`q5y(!Zr|>%+J;Ewdspj zewT#M_3z1@I;o28+Z)kS1HHq;&k{vV4VQzAI3|j*mjt+p_0c!1^NPBcWxG#%PLx)B za@yI_Qe$w?^?%y#V$vOYuuylzY~u#0#pOwuaN{b&{hJQ#srXvuRc7}(CJA#QNRVyQv+o2VM zX+VJl*^D!V6J|NtG*2&5s9}Pf4cPqO^)dEpWLwEbm8G|Z9eUQ)|4PZR?}HwjPb>H5 zcBR!pQ`a|kdY3yNXlTVZpW~3FM8WcV@$AWR^eLzJ!yPs>IV zn&Lbgz6sCX&(5ZPHjF+zb4faG;mN%QRnz>5Wo?X*z00`cn4*HWGUGt$)Vk)R+EYz} zLyP&;C7Tc9uf%+bO(O?Gnxckg;$2LK<>%aXmv?tMN>sM9?+p80eI{G2__)B&zuyfV zA49640NR6{{@&Vz%RdV~5$=+f%ka(J)3j0!wA2(xLOOrrd2AqSmM~2Q@s*XV8ZX}e zdwRIe*{`8RSjfcOp_3PI_EN+<=INokr_9gE?(N^6dzYW)G6zXcEuA{^;mKIyi_1x} z;eyx3D9$7eQ$OtS%apHUR1E4hag|N3@LyrDnm^`P`{nlTFv`&H-4JRH7^1sUUkz$b z2WC!bVvDk|6RD{;4f!@2Vh~QV6*a?w-`t_lenz%1z;TmkR7{bVnwt7UR?OHRSe}8H zwqEbJPGN@B9Ni?5NNi72!4(G7P;m#|5V#tb;BH9$G9`NEWs7%KhLuT3Bb$9_>dW<@ z%Soe6wGAnxb{7DxLgsI@nzDqw%UTIdNl*7h3J`!IsZjN`1krKUK66Dc&s~?WAsoc| zWtZn#7yhGT3Ar$BNVJVz8ydQ*)Sl)W_9BclJ;YX@bckj5k&Fu;I(=Nsy!vcR31szV z1578vtxnP!0!Z|}jUB6gLFIHVvNilz(|i_>j-P#}4387Hr8JT&i#i7bT_xsEgmWA% z*TBo3e`v*Ga)hMpdhQ)b+-}OTB~+0UsPkHuO9kvq)kjLty2z$nlnpL1F)wAZpTrIY zbJJW&y;#00bXH8vsefIQFz$AdB;-ye{M>)#!bEsRvSX-A1ndeT_RdtT;p zazi7Qk3*DSdVEgv7Gvn$uq%-{@hyTmDpooiJ7ENUS!*T10HMUFhNJ?#P_KS%N)fi- zcP^aM2bCPySx``XfEV@h;<;+)q>Q z^9~!QV>InYC5sy8w$tc>C#iz5)7+7@lNFOn6vFL#Hs=Tf1ExD%udfy#Rc8`)9l^{- z#W$r`=~CxM)LtZxCt7gDW+7X?8VRw@$i33#z3Q|=o42Hz+d^KD)t$h*BTBlFlI0&sY-e2TT`Q%m}exy#U6mp4|$nzfN zZ*2?B&9xLBE=zKPt$YI@65|J*#+1-^sEb;T7$zM~GO2`TB;l*bd86@T-|BYkQ~j>p+)Z#-`j=!JH^p_} zHAf1Ou6a%yQkWMw1ZL^*t40kxOia;-Au5M$qg;OHm&P9BY;)1{cf@=3{ZIj!{V(Pu zi>|1s@y7Sm4Rn*_mZk_nJQrQ(>UZ3!nzDA=zA~!=?%t2@wLP1}20-gA$I^`aZ1{o3(-kCKQ27$7qYpD8R^zu zElX^gM>5e(8y$!Y3s)glS^E8D9^7_z;Hxo>eiHu1C;6!qzDVYWm8|G(u6{b!hg5$v zEe;liu}C_gtz6J`uIt%utuv`D`<06tkA02g)b+!S#VGh--zkOvsb!dL87vR&nIip& z@S$6SDraw`m%&lS>$>^itU#FAb>LD1bL&BVDk3u7n(xr*JT{+jmOo`v#%A zGQ3(7@@2BXbafCKjE>K^%?>rJo*<@c&#;I;!F_Lcvt7QS*EPO8KyuE)I7!yNFZ#9X zkf&ro%-R-9q0%NUMP>7wO#0KM4G_JFh(_gQ~+2!ct!KM>K*qcNXTY)mE<3 z!5z%@%yJ>Trh!i)QbAufs=Dg+*(Eq`E1EF4wxtz)h)LmS0cuujcP7MQ zO=VYO)2B62-+?!7w{443P|wL(Y(B@!V|6DS<`OT)@TbeMtUsIluKtGo*iUgok4zNb z@CTNRyW2FF*@yYv(@t54=tlM73;&sp zRy3CJ=;Uz6U6L8jeEA{7_ZOcP^P%K1nwQf=CLm0Mb1}Jt2^`@y`_&~?z|*P zvk%j%S^lY^=o+!PsdoK=+E}`WP+W^qf=K+r`$*;81}A#OAJ2!_E#nnVzd~TXo2oJu zzL>gQoJEFooUhgmHX->Zr)Oa+=&$ZWHMHwqi8a;@^fwqM(_PfV49r~NGow;-c_7ALJ-cdj0FDm?q7EoF&v>h$yEWyGlD5QG9g>qL ziPzM%EiXC%ZyX`HXz&KpEy)-*FC>3Oa|W%UWI(nZ}85?Ompa6LBFdbx zY$>gO8-qH=hvFgYVY1a$yE+zBh&uD(2cHH4ekRM6P@O$`=;aO8vC-?pr8eNNegCAd zJHKoi@3+341pPA3MdYKfCtbp0eW7rDbRlH5Dj#rlLMp&B(K}nU0KKqe!S~X^S>f;P zY1%v`J=*+H=YT#+lwc@z2{AZ(B3>V1dBK+UqC1}R%L6I=yLf~!QD|P!?dHZ1`|>z_ zJ+Q;2`HtQv+Qld?z4t(`yrU71;*$2?+8G1vNbhtU0Qp>lt$q@B`)YT0uF>J=e;Fc5 zdda_saVeGkzh?X}wT8U;pZ@Y~~ z7~6-y;i=dVG51|zc}fMU zH;5%^JKs3NxoZb@CCP~fdxum%MW&&Vm5d)WGc!P1W-eSXDhxh(=|*e1?vtdZLeIL? z8v+gHQ+fg%!UsJGOE>f53$qC6C{H0m=|l@lYfjpDj*kel{kMGocx8wB^`JgUaQq4? z%gNDSUyPi{sm8zIaLfGqTG50lXe1|2qpma?dxKrzSTAaYI9zR2mj$FMeUFPe9RmxO zPkC2O-DM22aUx(9x*xa1IdMG-xgCX=!FFRtr1SZmmxnm}r0O;dCVtDGa-_Gy z_sx<{>x<~uRGOZ^uTg{h{;UC6t1P-vdtCeRM4T*>LRPx4(T+g8h)>{VX20iz~vr~RX zib+TVb&1QlQDHf`#Jj>H%Ti{yVC29QQ_4OP*;P4fP%(8kZY;Oa_%~kSbSh#dMT669 zOAf!G=IIC^P^R);ULA=DPF-k?3*|b~nl`c)Ze#8|t)8xqIYKJ3; z{h2V`+thhTcSH6=1B^PY(Z`G|rGxe(u|G@5yY>uCzggGU6^Tc8(eyc&1E&(MB6`RYfv);ByCON4)4h`s#;tcG_DimHDrjj=0-i zrY@S;s%so~+Fgjwj!9cB2pUUWllZ}+5(HVaKjzL_mhC*w?Er$Y&T+P#ridW&JEkQQ5a<@7o zA5T8L_w-=Qg(ar@@9(j&SXCP}&Si=8zM(nA*llOmaXdiMxuRwd5S^^8HZpUm| zy3j8gLE}N|f|h=;OAlwVWrq}=zMWj;l?TlU(h*)K8v0+wYyWZbMmg&$t$c!+zo|bC z$Z{26sZ!|ja;f~mK5+9O;`y^*V!-;A)MN3-YQ9_04D`#Z`=SizUxkW`tSjx-cVI4G zg7fokG>JZ3n~RF!U!rloh{U}QuqVNN4vciK*_Jnz zHd=%W11A+m@x5(A8D%Mfj~Ezd6&9Nm zq+k6Ed>G#zBEPmDf$|p{h3qVw>z8*M%#kqMtK$8TOwJ&$9#`M!RJ^@eH7()-C)5E$LHrFi<7w-AE*6=Lg&`R%H zhPvi6{f>$x#5Rps#c}7rA9uK`XNy}~G{(|NZApQn5HQLI27qgjeaVT|%}w4NSYSxO zEAcw%;N=YNp?KM{K&c+cSC2ydZs|WB6KG_YNgalP;~MJvm0?34IwljiR>xfnku4e5 zLFm@W5*7_7LuQ8h2zlD^9b2os^pT8_&EZv(y9()32Fg-FaM}hzL(Z$fT5+3_=3OID zo=^=S$2wz!W^K~rA-8|GrEdIEs-hgH*&7eLibmO*DeaN9Mp;rj)-oHkbZIXuv5BG1 z`>t}}l$Hh9QU29^MMDI_8KMrn5;<7n>7swvI1St8aQm^VhTv1NTWQ| zWkK%MrYxI|G2`@9;4~36E7aO>PoA9UzR1@pAkb7? zzF$bOrq&VPv1ni{Iv~2U(Tl4E?hGoAXly4mSe0BpkB~m6@Sn=G(p`U4r|^J053sjo|5%gECp@A*fDHF?o968&R~j;`0-)yrL|t@! zpFYZ9%@eVx-GX+>)W=Axt^tL~T>7cLuFq~{SK~Mcj6rX;eb{Wr|Gch{Oals9K9I5+hQ^1rv1y^{v*`Fe4%Rjf*cL(|xF z(RP00H4=^(%yb!-A=rj0)Sq5tCmr1Rsp$H~c3o~k+X4&~doq=Dc8oJE_=|upv zaSj<}NIMIAS+yD3zRJWO1T;0s{zStZ$meGMyOh=HNu`DuDgNO@EPyyaAw%LB4R<8% z<%(SZ`_gHLx7TL@2Sb~l%dEK&L%nhn=0Nr!bWH?C=Gbl80cZ=|`|{%BQBq4#^T5T1 zuh%PH{W!y6R_1Ixu4?T9>sSFCFm5#~JtWNp>7g~~SbNw9+6`vpbhs2O)+_|MVR=$% z#ND9r_fkXHoJVAO08rcFzCF@XEqvG7=h{~SLzl~JWfE|vdK zMOGJ~vLDhO7>n&`XcEe9PGT&poGG9g0EW4mxv~M+819P=EF;jMmx1rny~Q5C$&^Iu z@NKOGk^57Z)@7I8HPQ$FxFhpbM~K_;diOG5)y3a@dxX>uSI)K+Fjvq03DXhNsjDc= zVFC{)&rXr|$y$-!Nz37Kbp&Z=Y#mBDxY;2;lSe_Xc)FU_jQxvrqgaFTRbY}h^#7G$%}ri|9zse=j=9P$jjgi+kpwDpZWNHxc^Eks;JIYg@v4sSYhqjg2Iw+J~Q6a5MdxhE5 z`M!I81Yq6VebW&nw%=tD!v4}(i9l?8frc<@+Upx_rLY3ETE>gHHW}k$hVpDqwNOzs zrZza>1t(SOpC=VCQf68pwP|jo8_wV1IO~h@DyM=5H)X}R10>ehM z!-YWOVU<@IFe^bz&HSstpj=)(E~@=37^Elm?C3qLP1C$TY3K{m$l>7_(!u=a<9_CX z!zFEZYqHA5mK&Jm28M}c47!Tgoh&E9f;7aG?*P$R&QJEuIXD$%f1Qedy88bsXWZcc zMIN-tbpUWZs1c*=LJ~nhWjmO1z#vbA>{Z#wBd|8u-yukRinz_81@o0$qvpK`qcc#1 zglvs*0};rG`&i?ODGE(#sK#o^6vWm;>fa7Nt@lPT-0yj06cliE7Y47K>%xHD91TGS zh*Tha9wKOR_eS;65O`C0_l&3l@O*{#^3GmNWXuM?f|(d#Db?J|Fq=Vi)Nn7>`5nNO vuYMUfMv%UV--~coLdx}ja!U%@q8*i4od7gzNaY9&5phvn=l23t%iI3}J*2vR literal 101240 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

Tj+ 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 z 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 RC-@$fijv0V^oxkc{|8zl8wmga From 8ed788b1b05baf054844216a47863591ade8be0b Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 7 Jun 2021 15:42:42 -0700 Subject: [PATCH 16/82] WIP: Fixed most of the failing tests again New tests are still failing (they need to be finished) --- .../classes/LoggerSObjectHandler.cls | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index 3a06643f2..d2ec10873 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -12,10 +12,20 @@ private static Map configurationsBySObjectType = loadConfigurations(); private static Map loadConfigurations() { + DescribeSObjectResult configDescribe = Schema.LoggerSObjectHandlerConfiguration__mdt.SObjectType.getDescribe(); + + // When using CMDT's getAll(), it does not return relationship fields for EntityDefinition fields... + // ... so dynamically query the LoggerSObjectHandlerConfiguration__mdt CMDT object + List queryFields = new List( configDescribe.fields.getMap().keySet() ); + String sobjectTypeRelationshipName = Schema.LoggerSObjectHandlerConfiguration__mdt.SObjectType__c.getDescribe().getName().replace('__c', '__r'); + queryFields.add(sobjectTypeRelationshipName + '.' + Schema.EntityDefinition.DeveloperName); + queryFields.add(sobjectTypeRelationshipName + '.' + Schema.EntityDefinition.QualifiedApiName); + String query = 'SELECT ' + String.join(queryFields, ', ') + ' FROM ' + configDescribe.getName(); + Map configsBySObjectType = new Map(); - for (LoggerSObjectHandlerConfiguration__mdt config : LoggerSObjectHandlerConfiguration__mdt.getAll().values()) { + for (LoggerSObjectHandlerConfiguration__mdt config : (List) Database.query(query)) { // Schema.getGlobalDescribe() is the worst, so don't use it - SObjectType sobjectType = ((SObject) Type.forName(config.SObjectType__r.QualifiedApiName + '__c').newInstance()).getSObjectType(); + SObjectType sobjectType = ((SObject) Type.forName(config.SObjectType__r.QualifiedApiName).newInstance()).getSObjectType(); configsBySObjectType.put(sobjectType, config); } From 89c7e21e4dcf3eba58cc217e9d1a7e60b43f8d8f Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 7 Jun 2021 16:15:24 -0700 Subject: [PATCH 17/82] Added tests to verify handlers dont run when disabled via CMDT --- .../classes/LoggerSObjectHandler.cls | 12 +++-- .../classes/LogEntryEventHandler_Tests.cls | 47 +++++++++++++++++++ .../classes/LogEntryHandler_Tests.cls | 31 ++++++++++++ .../classes/LogHandler_Tests.cls | 5 +- 4 files changed, 89 insertions(+), 6 deletions(-) diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index d2ec10873..7aabeccda 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -56,7 +56,7 @@ private LoggerSObjectHandlerConfiguration__mdt getConfiguration(SObjectType sobjectType) { LoggerSObjectHandlerConfiguration__mdt configuration = configurationsBySObjectType.get(sobjectType); - if (configuration == null || Test.isRunningTest()) { + if (configuration == null) { configuration = new LoggerSObjectHandlerConfiguration__mdt(); // Setting entity definition fields on CMDT is not properly supported, so here's some goofy workarounds for handling it @@ -68,6 +68,8 @@ configuration = (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); configuration.IsEnabled__c = true; + + configurationsBySObjectType.put(sobjectType, configuration); } return configuration; @@ -78,8 +80,8 @@ return; } - LoggerSObjectPostProcessor recordPostProcessor = (LoggerSObjectPostProcessor) Type.forName(apexClassName).newInstance(); - recordPostProcessor.execute(Trigger.operationType, loggerRecords, oldLoggerRecordsById); + LoggerSObjectPostProcessor apexPostProcessor = (LoggerSObjectPostProcessor) Type.forName(apexClassName).newInstance(); + apexPostProcessor.execute(Trigger.operationType, loggerRecords, oldLoggerRecordsById); } private void executePostProcessorFlow(String flowApiName, List loggerRecords, Map oldLoggerRecordsById) { @@ -92,7 +94,7 @@ flowInputs.put('records', loggerRecords); flowInputs.put('oldRecords', oldLoggerRecordsById?.values()); - Flow.Interview postProcessorFlow = Flow.Interview.createInterview(flowApiName, flowInputs); - postProcessorFlow.start(); + Flow.Interview flowPostProcessor = Flow.Interview.createInterview(flowApiName, flowInputs); + flowPostProcessor.start(); } } diff --git a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls index 3ad3be6b3..b7a93238c 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls @@ -154,6 +154,19 @@ private class LogEntryEventHandler_Tests { } } + + private static LoggerSObjectHandlerConfiguration__mdt getMockConfiguration() { + // Setting entity definition fields on CMDT is not properly supported, so here's some goofy workarounds for handling it + EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :LogEntryEvent__e.getSObjectType().getDescribe().getName()]; + LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); + configuration.IsEnabled__c = true; + + Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); + configurationUntyped.put('SObjectType__r', logEntityDefinition); + + return (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); + } + static void validateLogFields(LogEntryEvent__e logEntryEvent, Log__c log) { Organization org = [SELECT Id, Name, InstanceName, IsSandbox, NamespacePrefix, OrganizationType, TrialExpirationDate FROM Organization]; User currentUser = getCurrentUser(); @@ -269,6 +282,40 @@ private class LogEntryEventHandler_Tests { Test.stopTest(); } + @isTest + static void it_should_not_run_handler_when_disabled_via_configuration() { + LoggerSObjectHandlerConfiguration__mdt logEntryEventHandlerConfiguration = getMockConfiguration(); + logEntryEventHandlerConfiguration.IsEnabled__c = false; + + Map configurationsBySObjectType = new Map{ + Schema.LogEntryEvent__e.SObjectType => logEntryEventHandlerConfiguration + }; + + Test.startTest(); + + // Use the mock configurations + LoggerSObjectHandler.configurationsBySObjectType = configurationsBySObjectType; + + LogEntryEvent__e logEntryEvent = new LogEntryEvent__e( + EpochTimestamp__c = System.now().getTime(), + Message__c = 'my message', + Timestamp__c = System.now(), + TransactionEntryNumber__c = 1, + TransactionId__c = '1234' + ); + + Database.SaveResult saveResult = EventBus.publish(logEntryEvent); + + Test.stopTest(); + + System.assertEquals(true, saveResult.isSuccess(), saveResult.getErrors()); + + // Assumption: if the handler had executed, then a log record would have been created + // ...so if there are 0 logs, it indicates that the handler did not execute + Integer logCount = [SELECT COUNT() FROM Log__c]; + System.assertEquals(0, logCount); + } + @isTest static void it_should_gracefully_skip_execution_when_logEntryEvents_list_is_empty() { List logEntryEvents = new List(); diff --git a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls index 5c510c4ac..274f2edce 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls @@ -21,6 +21,7 @@ private class LogEntryHandler_Tests { // Setting entity definition fields on CMDT is not properly supported, so here's some goofy workarounds for handling it EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :LogEntry__c.getSObjectType().getDescribe().getName()]; LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); + configuration.IsEnabled__c = true; Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); configurationUntyped.put('SObjectType__r', logEntityDefinition); @@ -42,6 +43,36 @@ private class LogEntryHandler_Tests { Test.stopTest(); } + @isTest + static void it_should_not_run_handler_when_disabled_via_configuration() { + String currentUserJson = JSON.serialize(new User(Id = UserInfo.getUserId())); + + LoggerSObjectHandlerConfiguration__mdt logEntryHandlerConfiguration = getMockConfiguration(); + logEntryHandlerConfiguration.IsEnabled__c = false; + + Map configurationsBySObjectType = new Map{ + Schema.LogEntry__c.SObjectType => logEntryHandlerConfiguration + }; + + Log__c log = [SELECT Id FROM Log__c LIMIT 1]; + LogEntry__c logEntry = new LogEntry__c(Log__c = log.Id, RecordJson__c = currentUserJson); + + Test.startTest(); + + // Use the mock configurations + LoggerSObjectHandler.configurationsBySObjectType = configurationsBySObjectType; + + insert logEntry; + + Test.stopTest(); + + // Assumption: if the handler had executed, then log.HasRecordJson__c should have been auto-set to true... + // ...so if it's still false, it indicates that the handler did not execute + logEntry = [SELECT Id, HasRecordJson__c, RecordJson__c FROM LogEntry__c WHERE Id = :logEntry.Id]; + System.assertNotEquals(null, logEntry.RecordJson__c); + System.assertEquals(false, logEntry.HasRecordJson__c); + } + @isTest static void it_should_save_log_entry_without_related_record_id() { Log__c log = [SELECT Id FROM Log__c LIMIT 1]; diff --git a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls index 11cef7f0e..624842d52 100644 --- a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls @@ -27,6 +27,7 @@ private class LogHandler_Tests { // Setting entity definition fields on CMDT is not properly supported, so here's some goofy workarounds for handling it EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :Log__c.getSObjectType().getDescribe().getName()]; LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); + configuration.IsEnabled__c = true; Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); configurationUntyped.put('SObjectType__r', logEntityDefinition); @@ -54,7 +55,7 @@ private class LogHandler_Tests { } @isTest - static void it_should_not_run_handler_when_configured() { + static void it_should_not_run_handler_when_disabled_via_configuration() { LoggerSObjectHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); logHandlerConfiguration.IsEnabled__c = false; @@ -475,6 +476,8 @@ private class LogHandler_Tests { // Use the mock configurations LoggerSObjectHandler.configurationsBySObjectType = configurationsBySObjectType; + System.debug('LoggerSObjectHandler.configurationsBySObjectType==' + LoggerSObjectHandler.configurationsBySObjectType); + Log__c log = new Log__c(LoggedBy__c = UserInfo.getUserId(), TransactionId__c = '1234'); insert log; From 1979b699a33a92973e80e46638fbdbf4639a61b2 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 7 Jun 2021 16:57:33 -0700 Subject: [PATCH 18/82] Added tests to make sure default configs are used when no CMDT is found --- .../classes/LogEntryEventHandler_Tests.cls | 36 ++++++++++++++++++- .../classes/LogEntryHandler_Tests.cls | 33 ++++++++++++++++- .../classes/LogHandler_Tests.cls | 28 +++++++++++++++ 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls index b7a93238c..bb658f9d0 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls @@ -282,6 +282,41 @@ private class LogEntryEventHandler_Tests { Test.stopTest(); } + + @isTest + static void it_should_load_a_default_config_when_no_config_present() { + Test.startTest(); + + // Clear any CMDT records that have been loaded from the database + LoggerSObjectHandler.configurationsBySObjectType.clear(); + LoggerSObjectHandlerConfiguration__mdt configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.LogEntryEvent__e.SObjectType); + System.assertEquals(null, configuration); + + LogEntryEvent__e logEntryEvent = new LogEntryEvent__e( + EpochTimestamp__c = System.now().getTime(), + Message__c = 'my message', + Timestamp__c = System.now(), + TransactionEntryNumber__c = 1, + TransactionId__c = '1234' + ); + Database.SaveResult saveResult = EventBus.publish(logEntryEvent); + + // Verify that a default config has been loaded w/ IsEnabled__c = true + configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.LogEntryEvent__e.SObjectType); + System.assertNotEquals(null, configuration); + System.assertEquals(null, configuration.Id); + System.assertEquals(true, configuration.IsEnabled__c); + + Test.stopTest(); + + System.assertEquals(true, saveResult.isSuccess(), saveResult.getErrors()); + + // Assumption: the default config should have been loaded with IsEnabled__c = true, resulting in a log being created + // ...which indicates that the handler executed with a default config + Integer logCount = [SELECT COUNT() FROM Log__c]; + System.assertEquals(1, logCount); + } + @isTest static void it_should_not_run_handler_when_disabled_via_configuration() { LoggerSObjectHandlerConfiguration__mdt logEntryEventHandlerConfiguration = getMockConfiguration(); @@ -303,7 +338,6 @@ private class LogEntryEventHandler_Tests { TransactionEntryNumber__c = 1, TransactionId__c = '1234' ); - Database.SaveResult saveResult = EventBus.publish(logEntryEvent); Test.stopTest(); diff --git a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls index 274f2edce..db3ab65a3 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls @@ -43,6 +43,37 @@ private class LogEntryHandler_Tests { Test.stopTest(); } + @isTest + static void it_should_load_a_default_config_when_no_config_present() { + String currentUserJson = JSON.serialize(new User(Id = UserInfo.getUserId())); + + Log__c log = [SELECT Id FROM Log__c LIMIT 1]; + LogEntry__c logEntry = new LogEntry__c(Log__c = log.Id, RecordJson__c = currentUserJson); + + Test.startTest(); + + // Clear any CMDT records that have been loaded from the database + LoggerSObjectHandler.configurationsBySObjectType.clear(); + LoggerSObjectHandlerConfiguration__mdt configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.LogEntry__c.SObjectType); + System.assertEquals(null, configuration); + + insert logEntry; + + // Verify that a default config has been loaded w/ IsEnabled__c = true + configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.LogEntry__c.SObjectType); + System.assertNotEquals(null, configuration); + System.assertEquals(null, configuration.Id); + System.assertEquals(true, configuration.IsEnabled__c); + + Test.stopTest(); + + // Assumption: the default config should have been loaded with IsEnabled__c = true, resulting in logEntry.HasRecordJson__c should have been auto-set to true... + // ...so if it's still false, it indicates that the handler did not execute + logEntry = [SELECT Id, HasRecordJson__c, RecordJson__c FROM LogEntry__c WHERE Id = :logEntry.Id]; + System.assertNotEquals(null, logEntry.RecordJson__c); + System.assertEquals(true, logEntry.HasRecordJson__c); + } + @isTest static void it_should_not_run_handler_when_disabled_via_configuration() { String currentUserJson = JSON.serialize(new User(Id = UserInfo.getUserId())); @@ -66,7 +97,7 @@ private class LogEntryHandler_Tests { Test.stopTest(); - // Assumption: if the handler had executed, then log.HasRecordJson__c should have been auto-set to true... + // Assumption: if the handler had executed, then logEntry.HasRecordJson__c should have been auto-set to true... // ...so if it's still false, it indicates that the handler did not execute logEntry = [SELECT Id, HasRecordJson__c, RecordJson__c FROM LogEntry__c WHERE Id = :logEntry.Id]; System.assertNotEquals(null, logEntry.RecordJson__c); diff --git a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls index 624842d52..db1843ed0 100644 --- a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls @@ -54,6 +54,34 @@ private class LogHandler_Tests { Test.stopTest(); } + @isTest + static void it_should_load_a_default_config_when_no_config_present() { + LogStatus__mdt closedLogStatus = [SELECT Id, MasterLabel FROM LogStatus__mdt WHERE IsActive__c = true AND IsClosed__c = true LIMIT 1]; + + Test.startTest(); + + // Clear any CMDT records that have been loaded from the database + LoggerSObjectHandler.configurationsBySObjectType.clear(); + LoggerSObjectHandlerConfiguration__mdt configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.Log__c.SObjectType); + System.assertEquals(null, configuration); + + Log__c log = new Log__c(LoggedBy__c = UserInfo.getUserId(), Status__c = closedLogStatus.MasterLabel, TransactionId__c = '1234'); + insert log; + + // Verify that a default config has been loaded w/ IsEnabled__c = true + configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.Log__c.SObjectType); + System.assertNotEquals(null, configuration); + System.assertEquals(null, configuration.Id); + System.assertEquals(true, configuration.IsEnabled__c); + + Test.stopTest(); + + // Assumption: the default config should have been loaded with IsEnabled__c = true, resulting in log.IsClosed__c being auto-set to true... + // ...so if it's true, it indicates that the handler executed with a default config + log = [SELECT Id, IsClosed__c FROM Log__c WHERE Id = :log.Id]; + System.assertEquals(true, log.IsClosed__c); + } + @isTest static void it_should_not_run_handler_when_disabled_via_configuration() { LoggerSObjectHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); From fc2f754a5d49cb1cbad9cf3a0472dfdca813a0c9 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 7 Jun 2021 22:16:50 -0700 Subject: [PATCH 19/82] Small fix for trigger operation in Flow post-processing --- .../main/log-management/classes/LoggerSObjectHandler.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index 7aabeccda..47e900918 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -90,7 +90,7 @@ } Map flowInputs = new Map(); - flowInputs.put('triggerOperationType', Trigger.operationType); + flowInputs.put('triggerOperationType', Trigger.operationType?.name()); flowInputs.put('records', loggerRecords); flowInputs.put('oldRecords', oldLoggerRecordsById?.values()); From 6d599964ab836a50db9f189feba965a492b224f3 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 7 Jun 2021 22:33:37 -0700 Subject: [PATCH 20/82] Changed CMDT mocking approach to be 83% less goofy based on @jamessimone's feedback --- .../classes/LoggerSObjectHandler.cls | 32 +++++-------- .../classes/LogEntryEventHandler_Tests.cls | 47 +------------------ .../classes/LogEntryHandler_Tests.cls | 11 +---- .../classes/LogHandler_Tests.cls | 11 +---- 4 files changed, 18 insertions(+), 83 deletions(-) diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index 47e900918..c4e767668 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -7,7 +7,7 @@ * @group Log Management * @description Abstract class used by trigger handlers for shared logic */ - public abstract class LoggerSObjectHandler { +public abstract class LoggerSObjectHandler { @testVisible private static Map configurationsBySObjectType = loadConfigurations(); @@ -15,17 +15,19 @@ DescribeSObjectResult configDescribe = Schema.LoggerSObjectHandlerConfiguration__mdt.SObjectType.getDescribe(); // When using CMDT's getAll(), it does not return relationship fields for EntityDefinition fields... - // ... so dynamically query the LoggerSObjectHandlerConfiguration__mdt CMDT object - List queryFields = new List( configDescribe.fields.getMap().keySet() ); - String sobjectTypeRelationshipName = Schema.LoggerSObjectHandlerConfiguration__mdt.SObjectType__c.getDescribe().getName().replace('__c', '__r'); - queryFields.add(sobjectTypeRelationshipName + '.' + Schema.EntityDefinition.DeveloperName); - queryFields.add(sobjectTypeRelationshipName + '.' + Schema.EntityDefinition.QualifiedApiName); - String query = 'SELECT ' + String.join(queryFields, ', ') + ' FROM ' + configDescribe.getName(); + // ... so instead query the LoggerSObjectHandlerConfiguration__mdt CMDT object + List configurations = [ + SELECT Id, IsEnabled__c, PostProcessorApexClassName__c, PostProcessorFlowApiName__c, SObjectType__r.QualifiedApiName + FROM LoggerSObjectHandlerConfiguration__mdt + ]; Map configsBySObjectType = new Map(); - for (LoggerSObjectHandlerConfiguration__mdt config : (List) Database.query(query)) { + for (LoggerSObjectHandlerConfiguration__mdt config : configurations) { + // CMDT entity-definition relationship fields are weird, so skip some headaches by copying the Qualified API name + config.SObjectType__c = config.SObjectType__r.QualifiedApiName; + // Schema.getGlobalDescribe() is the worst, so don't use it - SObjectType sobjectType = ((SObject) Type.forName(config.SObjectType__r.QualifiedApiName).newInstance()).getSObjectType(); + SObjectType sobjectType = ((SObject) Type.forName(config.SObjectType__c).newInstance()).getSObjectType(); configsBySObjectType.put(sobjectType, config); } @@ -57,17 +59,7 @@ LoggerSObjectHandlerConfiguration__mdt configuration = configurationsBySObjectType.get(sobjectType); if (configuration == null) { - configuration = new LoggerSObjectHandlerConfiguration__mdt(); - - // Setting entity definition fields on CMDT is not properly supported, so here's some goofy workarounds for handling it - // TODO cache entity definition query for Log__c, LogEntry__c and LogEntryEvent__e - String entityDefinitionRelationshipName = Schema.LoggerSObjectHandlerConfiguration__mdt.SObjectType__c.getDescribe().getName().replace('__c', '__r'); - EntityDefinition sobjectEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :sobjectType.getDescribe().getName()]; - Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); - configurationUntyped.put(entityDefinitionRelationshipName, sobjectEntityDefinition); - - configuration = (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); - configuration.IsEnabled__c = true; + configuration = new LoggerSObjectHandlerConfiguration__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); configurationsBySObjectType.put(sobjectType, configuration); } diff --git a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls index bb658f9d0..5b0a2b145 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls @@ -154,17 +154,9 @@ private class LogEntryEventHandler_Tests { } } - private static LoggerSObjectHandlerConfiguration__mdt getMockConfiguration() { - // Setting entity definition fields on CMDT is not properly supported, so here's some goofy workarounds for handling it - EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :LogEntryEvent__e.getSObjectType().getDescribe().getName()]; - LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); - configuration.IsEnabled__c = true; - - Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); - configurationUntyped.put('SObjectType__r', logEntityDefinition); - - return (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); + Schema.SObjectType sobjectType = Schema.LogEntryEvent__e.SObjectType; + return new LoggerSObjectHandlerConfiguration__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); } static void validateLogFields(LogEntryEvent__e logEntryEvent, Log__c log) { @@ -282,41 +274,6 @@ private class LogEntryEventHandler_Tests { Test.stopTest(); } - - @isTest - static void it_should_load_a_default_config_when_no_config_present() { - Test.startTest(); - - // Clear any CMDT records that have been loaded from the database - LoggerSObjectHandler.configurationsBySObjectType.clear(); - LoggerSObjectHandlerConfiguration__mdt configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.LogEntryEvent__e.SObjectType); - System.assertEquals(null, configuration); - - LogEntryEvent__e logEntryEvent = new LogEntryEvent__e( - EpochTimestamp__c = System.now().getTime(), - Message__c = 'my message', - Timestamp__c = System.now(), - TransactionEntryNumber__c = 1, - TransactionId__c = '1234' - ); - Database.SaveResult saveResult = EventBus.publish(logEntryEvent); - - // Verify that a default config has been loaded w/ IsEnabled__c = true - configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.LogEntryEvent__e.SObjectType); - System.assertNotEquals(null, configuration); - System.assertEquals(null, configuration.Id); - System.assertEquals(true, configuration.IsEnabled__c); - - Test.stopTest(); - - System.assertEquals(true, saveResult.isSuccess(), saveResult.getErrors()); - - // Assumption: the default config should have been loaded with IsEnabled__c = true, resulting in a log being created - // ...which indicates that the handler executed with a default config - Integer logCount = [SELECT COUNT() FROM Log__c]; - System.assertEquals(1, logCount); - } - @isTest static void it_should_not_run_handler_when_disabled_via_configuration() { LoggerSObjectHandlerConfiguration__mdt logEntryEventHandlerConfiguration = getMockConfiguration(); diff --git a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls index db3ab65a3..7104042da 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls @@ -18,15 +18,8 @@ private class LogEntryHandler_Tests { } private static LoggerSObjectHandlerConfiguration__mdt getMockConfiguration() { - // Setting entity definition fields on CMDT is not properly supported, so here's some goofy workarounds for handling it - EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :LogEntry__c.getSObjectType().getDescribe().getName()]; - LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); - configuration.IsEnabled__c = true; - - Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); - configurationUntyped.put('SObjectType__r', logEntityDefinition); - - return (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); + Schema.SObjectType sobjectType = Schema.LogEntry__c.SObjectType; + return new LoggerSObjectHandlerConfiguration__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); } @testSetup diff --git a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls index db1843ed0..b44b9ae49 100644 --- a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls @@ -24,15 +24,8 @@ private class LogHandler_Tests { } private static LoggerSObjectHandlerConfiguration__mdt getMockConfiguration() { - // Setting entity definition fields on CMDT is not properly supported, so here's some goofy workarounds for handling it - EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :Log__c.getSObjectType().getDescribe().getName()]; - LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); - configuration.IsEnabled__c = true; - - Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); - configurationUntyped.put('SObjectType__r', logEntityDefinition); - - return (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); + Schema.SObjectType sobjectType = Schema.Log__c.SObjectType; + return new LoggerSObjectHandlerConfiguration__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); } @testSetup From 128f8f32afee56cfdc8631c7659fc8ad868f68a6 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 8 Jun 2021 07:55:59 -0700 Subject: [PATCH 21/82] Centralized more trigger-based logic into LoggerSObjectHandler --- .../classes/LogEntryEventHandler.cls | 30 ++++++------- .../classes/LogEntryHandler.cls | 21 ++++----- .../log-management/classes/LogHandler.cls | 21 ++++----- .../classes/LoggerSObjectHandler.cls | 43 +++++++++++++------ 4 files changed, 66 insertions(+), 49 deletions(-) diff --git a/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls b/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls index 31a29e4c9..01e988988 100644 --- a/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls @@ -15,22 +15,22 @@ public without sharing class LogEntryEventHandler extends LoggerSObjectHandler { // Trigger-based variables - tests can override these with mock objects @testVisible - private List logEntryEvents; + private List logEntryEvents { + get { + return (List) this.records; + } + } - private List logEntries; - private Map> logEntryToTopics; - private Set topicNames; + private List logEntries = new List(); + private Map> logEntryToTopics = new Map>(); + private Set topicNames = new Set(); public LogEntryEventHandler() { - this((List) Trigger.new); } public LogEntryEventHandler(List logEntryEvents) { - this.logEntryEvents = logEntryEvents; - - this.logEntries = new List(); - this.logEntryToTopics = new Map>(); - this.topicNames = new Set(); + // Override the records provided by LoggerSObjectHandler + this.records = logEntryEvents; } /** @@ -45,15 +45,13 @@ public without sharing class LogEntryEventHandler extends LoggerSObjectHandler { * @description Runs the trigger handler's logic for the `LogEntryEvent__e` platform event object */ public void execute() { - if (this.configuration.IsEnabled__c == false) { + if (this.isEnabled() == false) { return; } - if (this.logEntryEvents.isEmpty() == false) { - this.upsertLogs(); - this.insertLogEntries(); - this.insertTopics(); - } + this.upsertLogs(); + this.insertLogEntries(); + this.insertTopics(); } private void upsertLogs() { diff --git a/nebula-logger/main/log-management/classes/LogEntryHandler.cls b/nebula-logger/main/log-management/classes/LogEntryHandler.cls index 7dce6b3c8..21cb900fb 100644 --- a/nebula-logger/main/log-management/classes/LogEntryHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryHandler.cls @@ -10,16 +10,17 @@ public without sharing class LogEntryHandler extends LoggerSObjectHandler { // Trigger-based variables - tests can override these with mock objects @testVisible - private List logEntries; - @testVisible - private Map oldLogEntriesById; - @testVisible - private TriggerOperation triggerOperationType; + private List logEntries { + get { + return (List) this.records; + } + } - public LogEntryHandler() { - this.logEntries = (List) Trigger.new; - this.oldLogEntriesById = (Map) Trigger.oldMap; - this.triggerOperationType = Trigger.operationType; + @testVisible + private Map oldLogEntriesById { + get { + return (Map) this.oldRecordsById; + } } /** @@ -34,7 +35,7 @@ public without sharing class LogEntryHandler extends LoggerSObjectHandler { * @description Runs the trigger handler's logic for the `LogEntry__c` custom object */ public void execute() { - if (this.configuration.IsEnabled__c == false) { + if (this.isEnabled() == false) { return; } diff --git a/nebula-logger/main/log-management/classes/LogHandler.cls b/nebula-logger/main/log-management/classes/LogHandler.cls index 5b51298a7..c57fb6259 100644 --- a/nebula-logger/main/log-management/classes/LogHandler.cls +++ b/nebula-logger/main/log-management/classes/LogHandler.cls @@ -26,16 +26,17 @@ public without sharing class LogHandler extends LoggerSObjectHandler { // Trigger-based variables - tests can override these with mock objects @testVisible - private List logs; - @testVisible - private Map oldLogsById; - @testVisible - private TriggerOperation triggerOperationType; + private List logs { + get { + return (List) this.records; + } + } - public LogHandler() { - this.logs = (List) Trigger.new; - this.oldLogsById = (Map) Trigger.oldMap; - this.triggerOperationType = Trigger.operationType; + @testVisible + private Map oldLogsById { + get { + return (Map) this.oldRecordsById; + } } /** @@ -50,7 +51,7 @@ public without sharing class LogHandler extends LoggerSObjectHandler { * @description Runs the trigger handler's logic for the `Log__c` custom object */ public void execute() { - if (this.configuration.IsEnabled__c == false) { + if (this.isEnabled() == false) { return; } diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index c4e767668..12980254c 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -34,10 +34,23 @@ public abstract class LoggerSObjectHandler { return configsBySObjectType; } - protected LoggerSObjectHandlerConfiguration__mdt configuration; + @testVisible + protected List records; + @testVisible + protected Map oldRecordsById; + @testVisible + protected TriggerOperation triggerOperationType; + + private LoggerSObjectHandlerConfiguration__mdt configuration; public LoggerSObjectHandler() { this.configuration = getConfiguration(this.getSObjectType()); + + if (this.configuration.IsEnabled__c == true) { + this.records = Trigger.new; + this.oldRecordsById = Trigger.oldMap; + this.triggerOperationType = Trigger.operationType; + } } /** @@ -46,13 +59,17 @@ public abstract class LoggerSObjectHandler { */ public abstract SObjectType getSObjectType(); + protected Boolean isEnabled() { + return this.configuration.IsEnabled__c; + } + protected void executePostProcessors(List loggerRecords, Map oldLoggerRecordsById) { if (loggerRecords == null) { return; } - this.executePostProcessorApexClass(this.configuration?.PostProcessorApexClassName__c, loggerRecords, oldLoggerRecordsById); - this.executePostProcessorFlow(this.configuration?.PostProcessorFlowApiName__c, loggerRecords, oldLoggerRecordsById); + this.executePostProcessorApexClass(); + this.executePostProcessorFlow(); } private LoggerSObjectHandlerConfiguration__mdt getConfiguration(SObjectType sobjectType) { @@ -67,26 +84,26 @@ public abstract class LoggerSObjectHandler { return configuration; } - private void executePostProcessorApexClass(String apexClassName, List loggerRecords, Map oldLoggerRecordsById) { - if (String.isBlank(apexClassName) || Type.forName(apexClassName) == null) { + private void executePostProcessorApexClass() { + if (String.isBlank(this.configuration.PostProcessorApexClassName__c) || Type.forName(this.configuration.PostProcessorApexClassName__c) == null) { return; } - LoggerSObjectPostProcessor apexPostProcessor = (LoggerSObjectPostProcessor) Type.forName(apexClassName).newInstance(); - apexPostProcessor.execute(Trigger.operationType, loggerRecords, oldLoggerRecordsById); + LoggerSObjectPostProcessor apexPostProcessor = (LoggerSObjectPostProcessor) Type.forName(this.configuration.PostProcessorApexClassName__c).newInstance(); + apexPostProcessor.execute(this.triggerOperationType, this.records, this.oldRecordsById); } - private void executePostProcessorFlow(String flowApiName, List loggerRecords, Map oldLoggerRecordsById) { - if (String.isBlank(flowApiName)) { + private void executePostProcessorFlow() { + if (String.isBlank(this.configuration?.PostProcessorFlowApiName__c)) { return; } Map flowInputs = new Map(); - flowInputs.put('triggerOperationType', Trigger.operationType?.name()); - flowInputs.put('records', loggerRecords); - flowInputs.put('oldRecords', oldLoggerRecordsById?.values()); + flowInputs.put('triggerOperationType', this.triggerOperationType?.name()); + flowInputs.put('records', this.records); + flowInputs.put('oldRecords', this.oldRecordsById?.values()); - Flow.Interview flowPostProcessor = Flow.Interview.createInterview(flowApiName, flowInputs); + Flow.Interview flowPostProcessor = Flow.Interview.createInterview(this.configuration?.PostProcessorFlowApiName__c, flowInputs); flowPostProcessor.start(); } } From dd86d6e966a97c7272e34648129bc4d9b3b695d9 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 8 Jun 2021 08:05:06 -0700 Subject: [PATCH 22/82] Removed safe navigators - there shouldnt be nulls in this situation --- .../main/log-management/classes/LoggerSObjectHandler.cls | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index 12980254c..6936ac9a5 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -94,7 +94,7 @@ public abstract class LoggerSObjectHandler { } private void executePostProcessorFlow() { - if (String.isBlank(this.configuration?.PostProcessorFlowApiName__c)) { + if (String.isBlank(this.configuration.PostProcessorFlowApiName__c)) { return; } @@ -103,7 +103,7 @@ public abstract class LoggerSObjectHandler { flowInputs.put('records', this.records); flowInputs.put('oldRecords', this.oldRecordsById?.values()); - Flow.Interview flowPostProcessor = Flow.Interview.createInterview(this.configuration?.PostProcessorFlowApiName__c, flowInputs); + Flow.Interview flowPostProcessor = Flow.Interview.createInterview(this.configuration.PostProcessorFlowApiName__c, flowInputs); flowPostProcessor.start(); } } From b3b6e0c060305d13fd6f4ae5a402bc3e785fd189 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 8 Jun 2021 09:18:08 -0700 Subject: [PATCH 23/82] Added extra tests for Flow post-processors --- extra-tests/LogHandler_Tests_Flow.cls | 44 ++++++++++++ .../LogHandler_Tests_Flow.cls-meta.xml | 5 ++ .../flows/LogHandler_Tests_Flow.flow-meta.xml | 68 +++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 extra-tests/LogHandler_Tests_Flow.cls create mode 100644 extra-tests/LogHandler_Tests_Flow.cls-meta.xml create mode 100644 extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml diff --git a/extra-tests/LogHandler_Tests_Flow.cls b/extra-tests/LogHandler_Tests_Flow.cls new file mode 100644 index 000000000..c9aacea0b --- /dev/null +++ b/extra-tests/LogHandler_Tests_Flow.cls @@ -0,0 +1,44 @@ +//------------------------------------------------------------------------------------------------// +// 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. // +//------------------------------------------------------------------------------------------------// + +@isTest +private class LogHandler_Tests_Flow { + private static LoggerSObjectHandlerConfiguration__mdt getMockConfiguration() { + // Mocking entity deefinition fields on CMDT is not properly supported, so here's some goofy workarounds for mocking an instance + EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :LogEntry__c.getSObjectType().getDescribe().getName()]; + LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); + configuration.IsEnabled__c = true; + + Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); + configurationUntyped.put('LoggerSObject__r', logEntityDefinition); + + return (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); + } + + @isTest + static void it_should_run_flow_post_processor_when_configured() { + String expectedLoginApplication = 'Some Fake Application'; + + LoggerSObjectHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); + logHandlerConfiguration.PostProcessorFlowApiName__c = 'LogHandler_Tests_Flow'; + + Map configurationsBySObjectType = new Map{ + Schema.LogEntry__c.SObjectType => logHandlerConfiguration + }; + + Test.startTest(); + + // Use the mock configurations + LoggerSObjectHandler.configurationsBySObjectType = configurationsBySObjectType; + + Log__c log = new Log__c(TransactionId__c = '1234'); + insert log; + + log = [SELECT Id, LoginApplication__c FROM Log__c WHERE Id = :log.Id]; + System.assertEquals(expectedLoginApplication, log.LoginApplication__c); + + Test.stopTest(); + } +} diff --git a/extra-tests/LogHandler_Tests_Flow.cls-meta.xml b/extra-tests/LogHandler_Tests_Flow.cls-meta.xml new file mode 100644 index 000000000..d75b0582f --- /dev/null +++ b/extra-tests/LogHandler_Tests_Flow.cls-meta.xml @@ -0,0 +1,5 @@ + + + 51.0 + Active + diff --git a/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml b/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml new file mode 100644 index 000000000..f40bfbea1 --- /dev/null +++ b/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml @@ -0,0 +1,68 @@ + + + 51.0 + + Update_Field + + 264 + 278 + + Process_Records.LoginApplication__c + Assign + + Some Fake Application + + + + Process_Records + + + LogHandler_Tests_Flow {!$Flow.CurrentDateTime} + + + Process_Records + + 176 + 158 + records + Asc + + Update_Field + + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + 50 + 0 + + Process_Records + + + Active + + records + SObject + true + true + false + Log__c + + From bb7846fe5721c6eb15f57d7b1c4741edb8433330 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 8 Jun 2021 09:27:31 -0700 Subject: [PATCH 24/82] Temp commenting out an assert --- extra-tests/LogHandler_Tests_Flow.cls | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extra-tests/LogHandler_Tests_Flow.cls b/extra-tests/LogHandler_Tests_Flow.cls index c9aacea0b..d183b0e7b 100644 --- a/extra-tests/LogHandler_Tests_Flow.cls +++ b/extra-tests/LogHandler_Tests_Flow.cls @@ -36,8 +36,9 @@ private class LogHandler_Tests_Flow { Log__c log = new Log__c(TransactionId__c = '1234'); insert log; - log = [SELECT Id, LoginApplication__c FROM Log__c WHERE Id = :log.Id]; - System.assertEquals(expectedLoginApplication, log.LoginApplication__c); + // TODO + // log = [SELECT Id, LoginApplication__c FROM Log__c WHERE Id = :log.Id]; + // System.assertEquals(expectedLoginApplication, log.LoginApplication__c); Test.stopTest(); } From 01f1fd4c5d3434f9b1ef5fdb366dc77fe598ef11 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 8 Jun 2021 09:49:03 -0700 Subject: [PATCH 25/82] Fixed incorrect SObject type --- extra-tests/LogHandler_Tests_Flow.cls | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extra-tests/LogHandler_Tests_Flow.cls b/extra-tests/LogHandler_Tests_Flow.cls index d183b0e7b..549e85483 100644 --- a/extra-tests/LogHandler_Tests_Flow.cls +++ b/extra-tests/LogHandler_Tests_Flow.cls @@ -22,10 +22,11 @@ private class LogHandler_Tests_Flow { String expectedLoginApplication = 'Some Fake Application'; LoggerSObjectHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); + logHandlerConfiguration.IsEnabled__c = true; logHandlerConfiguration.PostProcessorFlowApiName__c = 'LogHandler_Tests_Flow'; Map configurationsBySObjectType = new Map{ - Schema.LogEntry__c.SObjectType => logHandlerConfiguration + Schema.Log__c.SObjectType => logHandlerConfiguration }; Test.startTest(); From 8df593a2809f7caee4a75f26b07058876a4b8685 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 8 Jun 2021 10:19:58 -0700 Subject: [PATCH 26/82] Finished test for invoking Flow post-processor --- extra-tests/LogHandler_Tests_Flow.cls | 16 ++-- .../flows/LogHandler_Tests_Flow.flow-meta.xml | 80 ++++++++++++++----- 2 files changed, 72 insertions(+), 24 deletions(-) diff --git a/extra-tests/LogHandler_Tests_Flow.cls b/extra-tests/LogHandler_Tests_Flow.cls index 549e85483..e478530d6 100644 --- a/extra-tests/LogHandler_Tests_Flow.cls +++ b/extra-tests/LogHandler_Tests_Flow.cls @@ -19,11 +19,15 @@ private class LogHandler_Tests_Flow { @isTest static void it_should_run_flow_post_processor_when_configured() { - String expectedLoginApplication = 'Some Fake Application'; + // Assumption: the Flow LogHandler_Tests_Flow makes an update to the current user's FirstName + // The specific action within the Flow isn't that important - we just want to make sure... + // ...that that Flow is dynamically executed + String postProcessorFlowApiName = 'LogHandler_Tests_Flow'; + String expectedUserFirstName = 'Logger-Flow-Test'; LoggerSObjectHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); logHandlerConfiguration.IsEnabled__c = true; - logHandlerConfiguration.PostProcessorFlowApiName__c = 'LogHandler_Tests_Flow'; + logHandlerConfiguration.PostProcessorFlowApiName__c = postProcessorFlowApiName; Map configurationsBySObjectType = new Map{ Schema.Log__c.SObjectType => logHandlerConfiguration @@ -37,10 +41,10 @@ private class LogHandler_Tests_Flow { Log__c log = new Log__c(TransactionId__c = '1234'); insert log; - // TODO - // log = [SELECT Id, LoginApplication__c FROM Log__c WHERE Id = :log.Id]; - // System.assertEquals(expectedLoginApplication, log.LoginApplication__c); - Test.stopTest(); + + // Assumption: the FLow + User currentUser = [SELECT Id, FirstName FROM User WHERE Id = :UserInfo.getUserId()]; + System.assertEquals(expectedUserFirstName, currentUser.FirstName); } } diff --git a/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml b/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml index f40bfbea1..8929c194d 100644 --- a/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml +++ b/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml @@ -2,34 +2,24 @@ 51.0 - Update_Field - - 264 + Update_user_s_first_name + + 176 278 - Process_Records.LoginApplication__c + Get_current_user.FirstName Assign - Some Fake Application + Logger-Flow-Test - Process_Records + Save_current_user + An additional Flow used test dynamically running Flow post-processors from LoggerSObjectHandler LogHandler_Tests_Flow {!$Flow.CurrentDateTime} - - Process_Records - - 176 - 158 - records - Asc - - Update_Field - - BuilderType @@ -49,14 +39,61 @@ AutoLaunchedFlow + + Get_current_user + + 176 + 158 + false + + Update_user_s_first_name + + and + + Id + EqualTo + + $User.Id + + + true + User + true + + + Save_current_user + + 176 + 398 + Get_current_user + 50 0 - Process_Records + Get_current_user Active + + oldRecords + SObject + true + true + false + Log__c + + + Used by test class to verify that the Flow ran successfully + ranSuccessfully + Boolean + false + false + true + + false + + records SObject @@ -65,4 +102,11 @@ false Log__c + + triggerOperationType + String + false + true + false + From be7744a11df563a20aa9ca3ea681659ffb9b74dd Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 8 Jun 2021 10:41:11 -0700 Subject: [PATCH 27/82] Added extra assert in test (just to be safe) --- extra-tests/LogHandler_Tests_Flow.cls | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extra-tests/LogHandler_Tests_Flow.cls b/extra-tests/LogHandler_Tests_Flow.cls index e478530d6..057e5a358 100644 --- a/extra-tests/LogHandler_Tests_Flow.cls +++ b/extra-tests/LogHandler_Tests_Flow.cls @@ -24,6 +24,7 @@ private class LogHandler_Tests_Flow { // ...that that Flow is dynamically executed String postProcessorFlowApiName = 'LogHandler_Tests_Flow'; String expectedUserFirstName = 'Logger-Flow-Test'; + System.assertNotEquals(expectedUserFirstName, UserInfo.getFirstName()); LoggerSObjectHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); logHandlerConfiguration.IsEnabled__c = true; @@ -43,7 +44,7 @@ private class LogHandler_Tests_Flow { Test.stopTest(); - // Assumption: the FLow + // Verify that the Flow ran by checking if the user's FirstName was updated User currentUser = [SELECT Id, FirstName FROM User WHERE Id = :UserInfo.getUserId()]; System.assertEquals(expectedUserFirstName, currentUser.FirstName); } From 747cd5d5dadaa2088c2df249bb61aeccc4e8b088 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 8 Jun 2021 11:09:46 -0700 Subject: [PATCH 28/82] Generated new package versions --- packages/managed-package/sfdx-project.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/managed-package/sfdx-project.json b/packages/managed-package/sfdx-project.json index 6d2670032..12373201c 100644 --- a/packages/managed-package/sfdx-project.json +++ b/packages/managed-package/sfdx-project.json @@ -21,6 +21,7 @@ "Nebula Logger - Managed Package@4.0.0-9-managed-package-release": "04t5Y000000XJZ7QAO", "Nebula Logger - Managed Package@4.2.0-0-more-fields-and-methods": "04t5Y000000Xg4wQAC", "Nebula Logger - Managed Package@4.3.0-3-logger-console-app": "04t5Y000000YLDLQA4", - "Nebula Logger - Managed Package@4.4.0-2-config-default-save-method": "04t5Y0000027FFgQAM" + "Nebula Logger - Managed Package@4.4.0-2-config-default-save-method": "04t5Y0000027FFgQAM", + "Nebula Logger - Managed Package@4.5.0-0-logger-sobject-post-processors": "04t5Y0000027FKbQAM" } -} \ No newline at end of file +} From 5878d8950ad421c8d8f0ded75e5d461ed8b07f96 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 8 Jun 2021 11:10:34 -0700 Subject: [PATCH 29/82] Generated new package versions --- README.md | 4 ++-- sfdx-project.json | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8d212db28..c902f50eb 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ Designed for Salesforce admins, developers & architects. A robust logger for Apex, Flow, Process Builder & Integrations. -[![Install Unlocked Package](./content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FJdQAM) -[![Install Managed Package](./content/btn-install-managed-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FFgQAM) +[![Install Unlocked Package](./content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FKWQA2) +[![Install Managed Package](./content/btn-install-managed-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FKbQAM) [![Deploy Unpackaged Metadata](./content/btn-deploy-unpackaged-metadata.png)](https://githubsfdeploy.herokuapp.com/?owner=jongpie&repo=NebulaLogger&ref=main) [![View Documentation](./content/btn-view-documentation.png)](https://jongpie.github.io/NebulaLogger/) diff --git a/sfdx-project.json b/sfdx-project.json index 00b92159f..cd74bb38f 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -21,6 +21,7 @@ "Nebula Logger - Unlocked Package@4.4.3-0-guest-user-bugfix": "04t5Y0000027FI1QAM", "Nebula Logger - Unlocked Package@4.4.4-0-timestamp-bugfix": "04t5Y0000027FIQQA2", "Nebula Logger - Unlocked Package@4.4.5-0-log-batch-purger-bugfixes": "04t5Y0000027FIVQA2", - "Nebula Logger - Unlocked Package@4.4.6-0-new-save-method-synchronous_dml": "04t5Y0000027FJdQAM" + "Nebula Logger - Unlocked Package@4.4.6-0-new-save-method-synchronous_dml": "04t5Y0000027FJdQAM", + "Nebula Logger - Unlocked Package@4.5.0-0-logger-sobject-post-processors": "04t5Y0000027FKWQA2" } } From 608b80ab3139f754a2561987a9a3ae7a2111b6f6 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 8 Jun 2021 14:26:04 -0700 Subject: [PATCH 30/82] Fixed some config issues with SObjectType__c CMDT field --- .../fields/SObjectType__c.field-meta.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/SObjectType__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/SObjectType__c.field-meta.xml index 66a53f722..4195305a3 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/SObjectType__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/SObjectType__c.field-meta.xml @@ -1,13 +1,13 @@ - + SObjectType__c false - SubscriberControlled + DeveloperControlled EntityDefinition Logger SObject Handler Configurations LoggerSObjectHandlerConfigurations - false + true MetadataRelationship - false + true From 65006effacf4572ff297054f475e958d9181fb9e Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 8 Jun 2021 15:04:08 -0700 Subject: [PATCH 31/82] Fixed VR rule name --- ...=> Post_processing_is_not_supported.validationRule-meta.xml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/{Post_Processing_not_supported.validationRule-meta.xml => Post_processing_is_not_supported.validationRule-meta.xml} (90%) diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_Processing_not_supported.validationRule-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml similarity index 90% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_Processing_not_supported.validationRule-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml index a3992e7bf..47fc8ee2b 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_Processing_not_supported.validationRule-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml @@ -1,6 +1,6 @@ - Post_Processing_not_supported + Post_processing_is_not_supported true AND( SObjectType__r.DeveloperName != 'Log', From 07664060f20046ea617d83cbaab662624b93d6a3 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 8 Jun 2021 22:44:52 -0700 Subject: [PATCH 32/82] Removed unused describe call --- .../main/log-management/classes/LoggerSObjectHandler.cls | 2 -- 1 file changed, 2 deletions(-) diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index 6936ac9a5..ed2466f69 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -12,8 +12,6 @@ public abstract class LoggerSObjectHandler { private static Map configurationsBySObjectType = loadConfigurations(); private static Map loadConfigurations() { - DescribeSObjectResult configDescribe = Schema.LoggerSObjectHandlerConfiguration__mdt.SObjectType.getDescribe(); - // When using CMDT's getAll(), it does not return relationship fields for EntityDefinition fields... // ... so instead query the LoggerSObjectHandlerConfiguration__mdt CMDT object List configurations = [ From 9ffcb7b0146c714b6b2bbd4521746ad418fbacfa Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Wed, 9 Jun 2021 23:16:47 -0700 Subject: [PATCH 33/82] Moved post-processor config into a 2nd CMDT object --- extra-tests/LogHandler_Tests_Flow.cls | 26 ++--- .../LogHandler_Tests_Flow.cls-meta.xml | 2 +- .../flows/LogHandler_Tests_Flow.flow-meta.xml | 2 +- .../classes/LogEntryHandler.cls | 10 +- .../log-management/classes/LogHandler.cls | 7 +- .../classes/LoggerSObjectHandler.cls | 89 +++++++++------ .../classes/LoggerSObjectHandler.cls-meta.xml | 2 +- .../LoggerSObjectPostProcessor.cls-meta.xml | 2 +- ...ndler Configuration Layout.layout-meta.xml | 34 +++--- ...gger Post Processor Layout.layout-meta.xml | 101 ++++++++++++++++++ ...tHandlerConfiguration__mdt.object-meta.xml | 3 +- .../fields/IsEnabled__c.field-meta.xml | 8 +- ...stProcessorApexClassName__c.field-meta.xml | 13 --- ...PostProcessorFlowApiName__c.field-meta.xml | 15 --- .../fields/SObjectType__c.field-meta.xml | 2 +- .../listViews/All.listView-meta.xml | 4 +- ...g_is_not_supported.validationRule-meta.xml | 15 --- ...rSObjectPostProcessor__mdt.object-meta.xml | 7 ++ .../fields/ExecutionOrder__c.field-meta.xml | 12 +++ .../fields/IsEnabled__c.field-meta.xml | 9 ++ ...jectHandlerConfiguration__c.field-meta.xml | 12 +++ .../PostProcessorApiName__c.field-meta.xml | 23 ++++ .../PostProcessorType__c.field-meta.xml | 25 +++++ .../listViews/All.listView-meta.xml | 13 +++ ...g_is_not_supported.validationRule-meta.xml | 11 ++ .../profiles/Admin.profile-meta.xml | 33 ++++++ .../classes/LogEntryHandler_Tests.cls | 13 +-- .../classes/LogHandler_Tests.cls | 20 ++-- 28 files changed, 361 insertions(+), 152 deletions(-) create mode 100644 nebula-logger/main/log-management/layouts/LoggerSObjectPostProcessor__mdt-Logger Post Processor Layout.layout-meta.xml delete mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml delete mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml delete mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/LoggerSObjectPostProcessor__mdt.object-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/ExecutionOrder__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/IsEnabled__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/LoggerSObjectHandlerConfiguration__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorApiName__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorType__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/listViews/All.listView-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml diff --git a/extra-tests/LogHandler_Tests_Flow.cls b/extra-tests/LogHandler_Tests_Flow.cls index 057e5a358..876e19582 100644 --- a/extra-tests/LogHandler_Tests_Flow.cls +++ b/extra-tests/LogHandler_Tests_Flow.cls @@ -5,18 +5,6 @@ @isTest private class LogHandler_Tests_Flow { - private static LoggerSObjectHandlerConfiguration__mdt getMockConfiguration() { - // Mocking entity deefinition fields on CMDT is not properly supported, so here's some goofy workarounds for mocking an instance - EntityDefinition logEntityDefinition = [SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName = :LogEntry__c.getSObjectType().getDescribe().getName()]; - LoggerSObjectHandlerConfiguration__mdt configuration = new LoggerSObjectHandlerConfiguration__mdt(); - configuration.IsEnabled__c = true; - - Map configurationUntyped = (Map) JSON.deserializeUntyped(JSON.serialize(configuration)); - configurationUntyped.put('LoggerSObject__r', logEntityDefinition); - - return (LoggerSObjectHandlerConfiguration__mdt) JSON.deserialize(JSON.serialize(configurationUntyped), LoggerSObjectHandlerConfiguration__mdt.class); - } - @isTest static void it_should_run_flow_post_processor_when_configured() { // Assumption: the Flow LogHandler_Tests_Flow makes an update to the current user's FirstName @@ -26,18 +14,18 @@ private class LogHandler_Tests_Flow { String expectedUserFirstName = 'Logger-Flow-Test'; System.assertNotEquals(expectedUserFirstName, UserInfo.getFirstName()); - LoggerSObjectHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); - logHandlerConfiguration.IsEnabled__c = true; - logHandlerConfiguration.PostProcessorFlowApiName__c = postProcessorFlowApiName; - - Map configurationsBySObjectType = new Map{ - Schema.Log__c.SObjectType => logHandlerConfiguration + LoggerSObjectPostProcessor__mdt postProcessor = new LoggerSObjectPostProcessor__mdt( + PostProcessorType__c = 'Flow', + PostProcessorApiName__c = postProcessorFlowApiName + ); + Map> postProcessorsBySObjectType = new Map>{ + Schema.Log__c.SObjectType => new List{ postProcessor } }; Test.startTest(); // Use the mock configurations - LoggerSObjectHandler.configurationsBySObjectType = configurationsBySObjectType; + LoggerSObjectHandler.postProcessorsBySObjectType = postProcessorsBySObjectType; Log__c log = new Log__c(TransactionId__c = '1234'); insert log; diff --git a/extra-tests/LogHandler_Tests_Flow.cls-meta.xml b/extra-tests/LogHandler_Tests_Flow.cls-meta.xml index d75b0582f..482559c8b 100644 --- a/extra-tests/LogHandler_Tests_Flow.cls-meta.xml +++ b/extra-tests/LogHandler_Tests_Flow.cls-meta.xml @@ -1,4 +1,4 @@ - + 51.0 Active diff --git a/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml b/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml index 8929c194d..6f2d9bae2 100644 --- a/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml +++ b/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml @@ -1,4 +1,4 @@ - + 51.0 diff --git a/nebula-logger/main/log-management/classes/LogEntryHandler.cls b/nebula-logger/main/log-management/classes/LogEntryHandler.cls index 21cb900fb..13463d8e7 100644 --- a/nebula-logger/main/log-management/classes/LogEntryHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryHandler.cls @@ -16,11 +16,7 @@ public without sharing class LogEntryHandler extends LoggerSObjectHandler { } } - @testVisible - private Map oldLogEntriesById { - get { - return (Map) this.oldRecordsById; - } + public LogEntryHandler() { } /** @@ -56,8 +52,8 @@ public without sharing class LogEntryHandler extends LoggerSObjectHandler { } } - // Run any post-processors - this.executePostProcessors(this.logEntries, this.oldLogEntriesById); + // Run any post-processors configured in the LoggerSObjectPostProcessor__mdt custom metadata type + this.executePostProcessors(); } private void setCheckboxFields() { diff --git a/nebula-logger/main/log-management/classes/LogHandler.cls b/nebula-logger/main/log-management/classes/LogHandler.cls index c57fb6259..346208087 100644 --- a/nebula-logger/main/log-management/classes/LogHandler.cls +++ b/nebula-logger/main/log-management/classes/LogHandler.cls @@ -39,6 +39,9 @@ public without sharing class LogHandler extends LoggerSObjectHandler { } } + public LogHandler() { + } + /** * @description Returns SObject Type that the handler is responsible for processing * @return The instance of `SObjectType` @@ -72,8 +75,8 @@ public without sharing class LogHandler extends LoggerSObjectHandler { } } - // Run any post-processors - this.executePostProcessors(this.logs, this.oldLogsById); + // Run any post-processors configured in the LoggerSObjectPostProcessor__mdt custom metadata type + this.executePostProcessors(); } private void setOrgReleaseCycle() { diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index ed2466f69..75e76f87c 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -9,17 +9,29 @@ */ public abstract class LoggerSObjectHandler { @testVisible - private static Map configurationsBySObjectType = loadConfigurations(); + private static Map configurationsBySObjectType; + @testVisible + private static Map> postProcessorsBySObjectType; - private static Map loadConfigurations() { - // When using CMDT's getAll(), it does not return relationship fields for EntityDefinition fields... + static { + // When using CMDT's getAll(), it does not return relationship fields for EntityDefinition fields or child CMDT objects... // ... so instead query the LoggerSObjectHandlerConfiguration__mdt CMDT object List configurations = [ - SELECT Id, IsEnabled__c, PostProcessorApexClassName__c, PostProcessorFlowApiName__c, SObjectType__r.QualifiedApiName + SELECT + Id, + IsEnabled__c, + SObjectType__r.QualifiedApiName, + ( + SELECT Id, PostProcessorType__c, PostProcessorApiName__c + FROM LoggerSObjectPostProcessors__r + WHERE IsEnabled__c = TRUE + ORDER BY ExecutionOrder__c NULLS LAST, DeveloperName + ) FROM LoggerSObjectHandlerConfiguration__mdt ]; - Map configsBySObjectType = new Map(); + configurationsBySObjectType = new Map(); + postProcessorsBySObjectType = new Map>(); for (LoggerSObjectHandlerConfiguration__mdt config : configurations) { // CMDT entity-definition relationship fields are weird, so skip some headaches by copying the Qualified API name config.SObjectType__c = config.SObjectType__r.QualifiedApiName; @@ -27,24 +39,31 @@ public abstract class LoggerSObjectHandler { // Schema.getGlobalDescribe() is the worst, so don't use it SObjectType sobjectType = ((SObject) Type.forName(config.SObjectType__c).newInstance()).getSObjectType(); - configsBySObjectType.put(sobjectType, config); + configurationsBySObjectType.put(sobjectType, config); + postProcessorsBySObjectType.put(sobjectType, config?.LoggerSObjectPostProcessors__r); + } + + if (Test.isRunningTest() == true) { + // Test shouldn't rely on the actual CMDT rules in the org - clear the loaded values, and defaults will be used + configurationsBySObjectType.clear(); + postProcessorsBySObjectType.clear(); } - return configsBySObjectType; } + @testVisible + protected TriggerOperation triggerOperationType; @testVisible protected List records; @testVisible protected Map oldRecordsById; - @testVisible - protected TriggerOperation triggerOperationType; - private LoggerSObjectHandlerConfiguration__mdt configuration; + private LoggerSObjectHandlerConfiguration__mdt handlerConfiguration; + private List postProcessors; public LoggerSObjectHandler() { - this.configuration = getConfiguration(this.getSObjectType()); + this.setConfigurations(); - if (this.configuration.IsEnabled__c == true) { + if (this.handlerConfiguration.IsEnabled__c == true) { this.records = Trigger.new; this.oldRecordsById = Trigger.oldMap; this.triggerOperationType = Trigger.operationType; @@ -58,41 +77,45 @@ public abstract class LoggerSObjectHandler { public abstract SObjectType getSObjectType(); protected Boolean isEnabled() { - return this.configuration.IsEnabled__c; + return this.handlerConfiguration.IsEnabled__c; } - protected void executePostProcessors(List loggerRecords, Map oldLoggerRecordsById) { - if (loggerRecords == null) { + protected void executePostProcessors() { + if (this.records == null || this.postProcessors == null || this.postProcessors.isEmpty()) { return; } - this.executePostProcessorApexClass(); - this.executePostProcessorFlow(); + for (LoggerSObjectPostProcessor__mdt postProcessorConfiguration : this.postProcessors) { + switch on postProcessorConfiguration.PostProcessorType__c { + when 'Apex' { + this.executePostProcessorApexClass(postProcessorConfiguration.PostProcessorApiName__c); + } + when 'Flow' { + this.executePostProcessorFlow(postProcessorConfiguration.PostProcessorApiName__c); + } + } + } } - private LoggerSObjectHandlerConfiguration__mdt getConfiguration(SObjectType sobjectType) { - LoggerSObjectHandlerConfiguration__mdt configuration = configurationsBySObjectType.get(sobjectType); + private void setConfigurations() { + this.handlerConfiguration = configurationsBySObjectType.get(this.getSObjectType()); + this.postProcessors = postProcessorsBySObjectType.get(this.getSObjectType()); - if (configuration == null) { - configuration = new LoggerSObjectHandlerConfiguration__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); + if (this.handlerConfiguration == null) { + // If no config exists in the org, then load some in-memory defaults + this.handlerConfiguration = new LoggerSObjectHandlerConfiguration__mdt(IsEnabled__c = true, SObjectType__c = this.getSObjectType().getDescribe().getName()); - configurationsBySObjectType.put(sobjectType, configuration); + configurationsBySObjectType.put(this.getSObjectType(), this.handlerConfiguration); } - - return configuration; } - private void executePostProcessorApexClass() { - if (String.isBlank(this.configuration.PostProcessorApexClassName__c) || Type.forName(this.configuration.PostProcessorApexClassName__c) == null) { - return; - } - - LoggerSObjectPostProcessor apexPostProcessor = (LoggerSObjectPostProcessor) Type.forName(this.configuration.PostProcessorApexClassName__c).newInstance(); + private void executePostProcessorApexClass(String apexClassName) { + LoggerSObjectPostProcessor apexPostProcessor = (LoggerSObjectPostProcessor) Type.forName(apexClassName).newInstance(); apexPostProcessor.execute(this.triggerOperationType, this.records, this.oldRecordsById); } - private void executePostProcessorFlow() { - if (String.isBlank(this.configuration.PostProcessorFlowApiName__c)) { + private void executePostProcessorFlow(String flowApiName) { + if (String.isBlank(flowApiName)) { return; } @@ -101,7 +124,7 @@ public abstract class LoggerSObjectHandler { flowInputs.put('records', this.records); flowInputs.put('oldRecords', this.oldRecordsById?.values()); - Flow.Interview flowPostProcessor = Flow.Interview.createInterview(this.configuration.PostProcessorFlowApiName__c, flowInputs); + Flow.Interview flowPostProcessor = Flow.Interview.createInterview(flowApiName, flowInputs); flowPostProcessor.start(); } } diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls-meta.xml b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls-meta.xml index d75b0582f..482559c8b 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls-meta.xml +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls-meta.xml @@ -1,4 +1,4 @@ - + 51.0 Active diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls-meta.xml b/nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls-meta.xml index d75b0582f..482559c8b 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls-meta.xml +++ b/nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls-meta.xml @@ -1,4 +1,4 @@ - + 51.0 Active diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml index d9bca69b5..82c740058 100644 --- a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml @@ -16,32 +16,13 @@ - - Required - SObjectType__c - Edit IsEnabled__c - - - - - true - true - true - - - - Edit - PostProcessorApexClassName__c - - - - Edit - PostProcessorFlowApiName__c + Required + SObjectType__c @@ -83,6 +64,17 @@ + + MasterLabel + IsEnabled__c + DeveloperName + PostProcessorType__c + PostProcessorApiName__c + ExecutionOrder__c + LoggerSObjectPostProcessor__mdt.LoggerSObjectHandlerConfiguration__c + ExecutionOrder__c + Asc + false false false diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectPostProcessor__mdt-Logger Post Processor Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectPostProcessor__mdt-Logger Post Processor Layout.layout-meta.xml new file mode 100644 index 000000000..245ca1196 --- /dev/null +++ b/nebula-logger/main/log-management/layouts/LoggerSObjectPostProcessor__mdt-Logger Post Processor Layout.layout-meta.xml @@ -0,0 +1,101 @@ + + + + false + true + true + + + + Required + MasterLabel + + + Required + DeveloperName + + + + + Edit + IsEnabled__c + + + Required + LoggerSObjectHandlerConfiguration__c + + + Edit + ExecutionOrder__c + + + + + + true + true + true + + + + Required + PostProcessorType__c + + + + + Required + PostProcessorApiName__c + + + + + + false + true + true + + + + Required + NamespacePrefix + + + Readonly + CreatedById + + + + + Edit + IsProtected + + + Readonly + LastModifiedById + + + + + + true + true + false + + + + + + + false + false + false + false + false + + 00h3F0000048voA + 4 + 0 + Default + + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/LoggerSObjectHandlerConfiguration__mdt.object-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/LoggerSObjectHandlerConfiguration__mdt.object-meta.xml index 7f7199aed..c5ca81420 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/LoggerSObjectHandlerConfiguration__mdt.object-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/LoggerSObjectHandlerConfiguration__mdt.object-meta.xml @@ -1,7 +1,6 @@ - Used to configure additional Apex classes that should be executed by Logger after creating or updating records in Log__c or LogEntry__c + Used to configure the Apex trigger handler classes that run on the objects LogEntryEvent__e, Log__c and LogEntry__c Logger SObject Handler Configurations Public diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/IsEnabled__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/IsEnabled__c.field-meta.xml index 2825706a3..2aa194e96 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/IsEnabled__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/IsEnabled__c.field-meta.xml @@ -1,11 +1,13 @@ - + IsEnabled__c true - Controls if the SObject's trigger handler class should execute. This is useful for temporary disabling the logger's trigger handlers, but should typically be enabled. + Controls if the SObject's trigger handler class should execute. This is useful for temporary disabling the logger's trigger handlers, but should typically be enabled. false SubscriberControlled - Controls if the SObject's trigger handler class should execute. This is useful for temporary disabling the logger's trigger handlers, but should typically be enabled. + Controls if the SObject's trigger handler class should execute. This is useful for temporary disabling the logger's trigger handlers, but should typically be enabled. Checkbox diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml deleted file mode 100644 index 5ae97f50c..000000000 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorApexClassName__c.field-meta.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - PostProcessorApexClassName__c - The name of an Apex class that implements the interface LoggerSObjectPostProcessor - false - SubscriberControlled - The name of an Apex class that implements the interface LoggerSObjectPostProcessor - - 255 - false - Text - false - diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml deleted file mode 100644 index 9bf44a13f..000000000 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/PostProcessorFlowApiName__c.field-meta.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - PostProcessorFlowApiName__c - The API name of a Flow that suppports these inputs: - - triggerOperationType: text variable - - records: record collection variable - - oldRecords: record collection variable - false - SubscriberControlled - - 255 - false - Text - false - diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/SObjectType__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/SObjectType__c.field-meta.xml index 4195305a3..2bcd98bfb 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/SObjectType__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/SObjectType__c.field-meta.xml @@ -1,4 +1,4 @@ - + SObjectType__c false diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml index b74ff52dd..f5ac4c12a 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml @@ -3,10 +3,8 @@ All MasterLabel DeveloperName - SObjectType__c IsEnabled__c - PostProcessorApexClassName__c - PostProcessorFlowApiName__c + SObjectType__c Everything diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml deleted file mode 100644 index 47fc8ee2b..000000000 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - Post_processing_is_not_supported - true - AND( - SObjectType__r.DeveloperName != 'Log', - SObjectType__r.DeveloperName != 'LogEntry', - OR( - NOT(ISBLANK(PostProcessorApexClassName__c)), - NOT(ISBLANK(PostProcessorFlowApiName__c)) - ) -) - SObjectType__c - Post-processing is not supported for this SObject - diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/LoggerSObjectPostProcessor__mdt.object-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/LoggerSObjectPostProcessor__mdt.object-meta.xml new file mode 100644 index 000000000..5571fa57e --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/LoggerSObjectPostProcessor__mdt.object-meta.xml @@ -0,0 +1,7 @@ + + + Used to configure additional Apex classes and Flows that should be executed for all DML statements on Log__c and LogEntry__c + + Logger SObject Post Processors + Public + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/ExecutionOrder__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/ExecutionOrder__c.field-meta.xml new file mode 100644 index 000000000..4d3a66e91 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/ExecutionOrder__c.field-meta.xml @@ -0,0 +1,12 @@ + + + ExecutionOrder__c + false + SubscriberControlled + + 3 + false + 0 + Number + false + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/IsEnabled__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/IsEnabled__c.field-meta.xml new file mode 100644 index 000000000..7c3dca299 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/IsEnabled__c.field-meta.xml @@ -0,0 +1,9 @@ + + + IsEnabled__c + true + false + SubscriberControlled + + Checkbox + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/LoggerSObjectHandlerConfiguration__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/LoggerSObjectHandlerConfiguration__c.field-meta.xml new file mode 100644 index 000000000..29fc92a96 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/LoggerSObjectHandlerConfiguration__c.field-meta.xml @@ -0,0 +1,12 @@ + + + LoggerSObjectHandlerConfiguration__c + false + SubscriberControlled + + LoggerSObjectHandlerConfiguration__mdt + LoggerSObjectPostProcessors + true + MetadataRelationship + false + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorApiName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorApiName__c.field-meta.xml new file mode 100644 index 000000000..8de5206f5 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorApiName__c.field-meta.xml @@ -0,0 +1,23 @@ + + + PostProcessorApiName__c + The API name of the metadata to run, based on the Post-Processor Type + - Apex: The name of an Apex class that implements the interface LoggerSObjectPostProcessor + - Flow: The API name of a Flow that supports these inputs: + - triggerOperationType: text variable + - records: record collection variable + - oldRecords: record collection variable + false + SubscriberControlled + The API name of the metadata to run, based on the Post-Processor Type + - Apex: The name of an Apex class that implements the interface LoggerSObjectPostProcessor + - Flow: The API name of a Flow that supports these inputs: + - triggerOperationType: text variable + - records: record collection variable + - oldRecords: record collection variable + + 255 + true + Text + false + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorType__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorType__c.field-meta.xml new file mode 100644 index 000000000..2232e61f0 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorType__c.field-meta.xml @@ -0,0 +1,25 @@ + + + PostProcessorType__c + false + SubscriberControlled + + true + Picklist + + true + + false + + Apex + true + + + + Flow + false + + + + + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/listViews/All.listView-meta.xml new file mode 100644 index 000000000..9c0e8eaee --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/listViews/All.listView-meta.xml @@ -0,0 +1,13 @@ + + + All + MasterLabel + DeveloperName + IsEnabled__c + LoggerSObjectHandlerConfiguration__c + PostProcessorType__c + PostProcessorApiName__c + ExecutionOrder__c + Everything + + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml new file mode 100644 index 000000000..ded8fd809 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml @@ -0,0 +1,11 @@ + + + Post_processing_is_not_supported + true + AND( + LoggerSObjectHandlerConfiguration__r.SObjectType__r.DeveloperName != 'Log', + LoggerSObjectHandlerConfiguration__r.SObjectType__r.DeveloperName != 'LogEntry' +) + LoggerSObjectHandlerConfiguration__c + Post-processors are not supported for this SObject Handler + diff --git a/nebula-logger/main/log-management/profiles/Admin.profile-meta.xml b/nebula-logger/main/log-management/profiles/Admin.profile-meta.xml index df4f7afcf..e0a173c3b 100644 --- a/nebula-logger/main/log-management/profiles/Admin.profile-meta.xml +++ b/nebula-logger/main/log-management/profiles/Admin.profile-meta.xml @@ -97,6 +97,14 @@ Logger true + + LoggerSObjectHandler + true + + + LoggerSObjectPostProcessor + true + Logger_Tests true @@ -1400,6 +1408,21 @@ Log__c.WasLoggedByCurrentUser__c true + + false + LoggerSObjectHandlerConfiguration__mdt.IsEnabled__c + false + + + false + LoggerSObjectPostProcessor__mdt.ExecutionOrder__c + false + + + false + LoggerSObjectPostProcessor__mdt.IsEnabled__c + false + LogEntry__c-Log Entry Layout @@ -1409,6 +1432,12 @@ Log__c-Log Layout + + LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout + + + LoggerSObjectPostProcessor__mdt-Logger Post Processor Layout + true true @@ -1436,6 +1465,10 @@ Log__c true + + LogMassDelete + true + LogEntry__c DefaultOn diff --git a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls index 7104042da..b4fb800e2 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls @@ -291,11 +291,12 @@ private class LogEntryHandler_Tests { static void it_should_run_apex_post_processor_when_configured() { String expectedMessage = 'Some String'; - LoggerSObjectHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); - logHandlerConfiguration.PostProcessorApexClassName__c = LogEntryPostProcessorTest.class.getName(); - - Map configurationsBySObjectType = new Map{ - Schema.LogEntry__c.SObjectType => logHandlerConfiguration + LoggerSObjectPostProcessor__mdt postProcessor = new LoggerSObjectPostProcessor__mdt( + PostProcessorType__c = 'Apex', + PostProcessorApiName__c = LogEntryPostProcessorTest.class.getName() + ); + Map> postProcessorsBySObjectType = new Map>{ + Schema.LogEntry__c.SObjectType => new List{ postProcessor } }; Log__c log = [SELECT Id FROM Log__c LIMIT 1]; @@ -303,7 +304,7 @@ private class LogEntryHandler_Tests { Test.startTest(); // Use the mock configurations - LoggerSObjectHandler.configurationsBySObjectType = configurationsBySObjectType; + LoggerSObjectHandler.postProcessorsBySObjectType = postProcessorsBySObjectType; LogEntry__c logEntry = new LogEntry__c(Log__c = log.Id, Message__c = 'qwerty'); insert logEntry; diff --git a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls index b44b9ae49..53dc442ee 100644 --- a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls @@ -28,6 +28,11 @@ private class LogHandler_Tests { return new LoggerSObjectHandlerConfiguration__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); } + private static LoggerSObjectHandlerConfiguration__mdt getMockPostProcessor() { + Schema.SObjectType sobjectType = Schema.Log__c.SObjectType; + return new LoggerSObjectHandlerConfiguration__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); + } + @testSetup static void setupData() { Map logStatusByName = new Map(); @@ -485,19 +490,18 @@ private class LogHandler_Tests { static void it_should_run_apex_post_processor_when_configured() { String expectedProfileName = 'Some String'; - LoggerSObjectHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); - logHandlerConfiguration.PostProcessorApexClassName__c = LogPostProcessorTest.class.getName(); - - Map configurationsBySObjectType = new Map{ - Schema.Log__c.SObjectType => logHandlerConfiguration + LoggerSObjectPostProcessor__mdt postProcessor = new LoggerSObjectPostProcessor__mdt( + PostProcessorType__c = 'Apex', + PostProcessorApiName__c = LogPostProcessorTest.class.getName() + ); + Map> postProcessorsBySObjectType = new Map>{ + Schema.Log__c.SObjectType => new List{ postProcessor } }; Test.startTest(); // Use the mock configurations - LoggerSObjectHandler.configurationsBySObjectType = configurationsBySObjectType; - - System.debug('LoggerSObjectHandler.configurationsBySObjectType==' + LoggerSObjectHandler.configurationsBySObjectType); + LoggerSObjectHandler.postProcessorsBySObjectType = postProcessorsBySObjectType; Log__c log = new Log__c(LoggedBy__c = UserInfo.getUserId(), TransactionId__c = '1234'); insert log; From 1ff13f31bc3e60a719c2e563a25c5d7fba757f40 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Fri, 11 Jun 2021 11:12:14 -0700 Subject: [PATCH 34/82] Renamed 'post processors' to 'plugins' instead, added all 4 trigger SObject collections --- docs/index.md | 2 +- .../LoggerSObjectHandlerPlugin.md | 15 ++++ .../LoggerSObjectPostProcessor.md | 15 ---- extra-tests/LogHandler_Tests_Flow.cls | 14 ++-- .../classes/LogEntryHandler.cls | 4 +- .../log-management/classes/LogHandler.cls | 4 +- .../classes/LoggerSObjectHandler.cls | 69 ++++++++++--------- ...sor.cls => LoggerSObjectHandlerPlugin.cls} | 12 +++- ...> LoggerSObjectHandlerPlugin.cls-meta.xml} | 0 ...tHandler.LogEntryEventHandler.md-meta.xml} | 0 ...ObjectHandler.LogEntryHandler.md-meta.xml} | 0 ...ggerSObjectHandler.LogHandler.md-meta.xml} | 0 ...ect Handler Plugin Layout.layout-meta.xml} | 6 +- ...er SObject Handler Layout.layout-meta.xml} | 8 +-- ...SObjectHandlerPlugin__mdt.object-meta.xml} | 4 +- .../fields/ExecutionOrder__c.field-meta.xml | 0 .../fields/IsEnabled__c.field-meta.xml | 0 .../fields/PluginApiName__c.field-meta.xml} | 8 +-- .../fields/PluginType__c.field-meta.xml} | 4 +- .../fields/SObjectHandler__c.field-meta.xml} | 8 +-- .../listViews/All.listView-meta.xml | 6 +- ..._are_not_supported.validationRule-meta.xml | 11 +++ ...LoggerSObjectHandler__mdt.object-meta.xml} | 0 .../fields/IsEnabled__c.field-meta.xml | 0 .../fields/SObjectType__c.field-meta.xml | 0 .../listViews/All.listView-meta.xml | 0 ...g_is_not_supported.validationRule-meta.xml | 11 --- .../profiles/Admin.profile-meta.xml | 12 ++-- .../classes/LogEntryEventHandler_Tests.cls | 8 +-- .../classes/LogEntryHandler_Tests.cls | 36 ++++++---- .../classes/LogHandler_Tests.cls | 40 ++++++----- 31 files changed, 160 insertions(+), 137 deletions(-) create mode 100644 docs/log-management/LoggerSObjectHandlerPlugin.md delete mode 100644 docs/log-management/LoggerSObjectPostProcessor.md rename nebula-logger/main/log-management/classes/{LoggerSObjectPostProcessor.cls => LoggerSObjectHandlerPlugin.cls} (67%) rename nebula-logger/main/log-management/classes/{LoggerSObjectPostProcessor.cls-meta.xml => LoggerSObjectHandlerPlugin.cls-meta.xml} (100%) rename nebula-logger/main/log-management/customMetadata/{LoggerSObjectHandlerConfiguration.LogEntryEventHandler.md-meta.xml => LoggerSObjectHandler.LogEntryEventHandler.md-meta.xml} (100%) rename nebula-logger/main/log-management/customMetadata/{LoggerSObjectHandlerConfiguration.LogEntryHandler.md-meta.xml => LoggerSObjectHandler.LogEntryHandler.md-meta.xml} (100%) rename nebula-logger/main/log-management/customMetadata/{LoggerSObjectHandlerConfiguration.LogHandler.md-meta.xml => LoggerSObjectHandler.LogHandler.md-meta.xml} (100%) rename nebula-logger/main/log-management/layouts/{LoggerSObjectPostProcessor__mdt-Logger Post Processor Layout.layout-meta.xml => LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml} (95%) rename nebula-logger/main/log-management/layouts/{LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml => LoggerSObjectHandler__mdt-Logger SObject Handler Layout.layout-meta.xml} (93%) rename nebula-logger/main/log-management/objects/{LoggerSObjectPostProcessor__mdt/LoggerSObjectPostProcessor__mdt.object-meta.xml => LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml} (73%) rename nebula-logger/main/log-management/objects/{LoggerSObjectPostProcessor__mdt => LoggerSObjectHandlerPlugin__mdt}/fields/ExecutionOrder__c.field-meta.xml (100%) rename nebula-logger/main/log-management/objects/{LoggerSObjectPostProcessor__mdt => LoggerSObjectHandlerPlugin__mdt}/fields/IsEnabled__c.field-meta.xml (100%) rename nebula-logger/main/log-management/objects/{LoggerSObjectPostProcessor__mdt/fields/PostProcessorApiName__c.field-meta.xml => LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml} (87%) rename nebula-logger/main/log-management/objects/{LoggerSObjectPostProcessor__mdt/fields/PostProcessorType__c.field-meta.xml => LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml} (89%) rename nebula-logger/main/log-management/objects/{LoggerSObjectPostProcessor__mdt/fields/LoggerSObjectHandlerConfiguration__c.field-meta.xml => LoggerSObjectHandlerPlugin__mdt/fields/SObjectHandler__c.field-meta.xml} (57%) rename nebula-logger/main/log-management/objects/{LoggerSObjectPostProcessor__mdt => LoggerSObjectHandlerPlugin__mdt}/listViews/All.listView-meta.xml (70%) create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/validationRules/Plugins_are_not_supported.validationRule-meta.xml rename nebula-logger/main/log-management/objects/{LoggerSObjectHandlerConfiguration__mdt/LoggerSObjectHandlerConfiguration__mdt.object-meta.xml => LoggerSObjectHandler__mdt/LoggerSObjectHandler__mdt.object-meta.xml} (100%) rename nebula-logger/main/log-management/objects/{LoggerSObjectHandlerConfiguration__mdt => LoggerSObjectHandler__mdt}/fields/IsEnabled__c.field-meta.xml (100%) rename nebula-logger/main/log-management/objects/{LoggerSObjectHandlerConfiguration__mdt => LoggerSObjectHandler__mdt}/fields/SObjectType__c.field-meta.xml (100%) rename nebula-logger/main/log-management/objects/{LoggerSObjectHandlerConfiguration__mdt => LoggerSObjectHandler__mdt}/listViews/All.listView-meta.xml (100%) delete mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml diff --git a/docs/index.md b/docs/index.md index f48c450a3..a1713b9b8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -60,7 +60,7 @@ Manages mass deleting `Log__c` records that have been selected by a user on a `L Abstract class used by trigger handlers for shared logic -### [LoggerSObjectPostProcessor](log-management/LoggerSObjectPostProcessor) +### [LoggerSObjectHandlerPlugin](log-management/LoggerSObjectHandlerPlugin) Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` diff --git a/docs/log-management/LoggerSObjectHandlerPlugin.md b/docs/log-management/LoggerSObjectHandlerPlugin.md new file mode 100644 index 000000000..833306673 --- /dev/null +++ b/docs/log-management/LoggerSObjectHandlerPlugin.md @@ -0,0 +1,15 @@ +--- +layout: default +--- + +## LoggerSObjectHandlerPlugin interface + +Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` + +--- + +### Methods + +#### `execute(TriggerOperation triggerOperationType,List triggerNew,Map triggerNewMap,List triggerOld,Map triggerOldMap)` → `void` + +--- diff --git a/docs/log-management/LoggerSObjectPostProcessor.md b/docs/log-management/LoggerSObjectPostProcessor.md deleted file mode 100644 index f55c8292d..000000000 --- a/docs/log-management/LoggerSObjectPostProcessor.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -layout: default ---- - -## LoggerSObjectPostProcessor interface - -Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` - ---- - -### Methods - -#### `execute(TriggerOperation triggerOperationType, List loggerRecords, Map oldLoggerRecordsById)` → `void` - ---- diff --git a/extra-tests/LogHandler_Tests_Flow.cls b/extra-tests/LogHandler_Tests_Flow.cls index 876e19582..a4fa6ce6a 100644 --- a/extra-tests/LogHandler_Tests_Flow.cls +++ b/extra-tests/LogHandler_Tests_Flow.cls @@ -10,22 +10,22 @@ private class LogHandler_Tests_Flow { // Assumption: the Flow LogHandler_Tests_Flow makes an update to the current user's FirstName // The specific action within the Flow isn't that important - we just want to make sure... // ...that that Flow is dynamically executed - String postProcessorFlowApiName = 'LogHandler_Tests_Flow'; + String pluginFlowApiName = 'LogHandler_Tests_Flow'; String expectedUserFirstName = 'Logger-Flow-Test'; System.assertNotEquals(expectedUserFirstName, UserInfo.getFirstName()); - LoggerSObjectPostProcessor__mdt postProcessor = new LoggerSObjectPostProcessor__mdt( - PostProcessorType__c = 'Flow', - PostProcessorApiName__c = postProcessorFlowApiName + LoggerSObjectHandlerPlugin__mdt plugin = new LoggerSObjectHandlerPlugin__mdt( + PluginType__c = 'Flow', + PluginApiName__c = pluginFlowApiName ); - Map> postProcessorsBySObjectType = new Map>{ - Schema.Log__c.SObjectType => new List{ postProcessor } + Map> pluginsBySObjectType = new Map>{ + Schema.Log__c.SObjectType => new List{ plugin } }; Test.startTest(); // Use the mock configurations - LoggerSObjectHandler.postProcessorsBySObjectType = postProcessorsBySObjectType; + LoggerSObjectHandler.pluginsBySObjectType = pluginsBySObjectType; Log__c log = new Log__c(TransactionId__c = '1234'); insert log; diff --git a/nebula-logger/main/log-management/classes/LogEntryHandler.cls b/nebula-logger/main/log-management/classes/LogEntryHandler.cls index 13463d8e7..73172d872 100644 --- a/nebula-logger/main/log-management/classes/LogEntryHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryHandler.cls @@ -52,8 +52,8 @@ public without sharing class LogEntryHandler extends LoggerSObjectHandler { } } - // Run any post-processors configured in the LoggerSObjectPostProcessor__mdt custom metadata type - this.executePostProcessors(); + // Run any post-processors configured in the LoggerSObjectHandlerPlugin__mdt custom metadata type + this.executePlugins(); } private void setCheckboxFields() { diff --git a/nebula-logger/main/log-management/classes/LogHandler.cls b/nebula-logger/main/log-management/classes/LogHandler.cls index 346208087..eb88d2814 100644 --- a/nebula-logger/main/log-management/classes/LogHandler.cls +++ b/nebula-logger/main/log-management/classes/LogHandler.cls @@ -75,8 +75,8 @@ public without sharing class LogHandler extends LoggerSObjectHandler { } } - // Run any post-processors configured in the LoggerSObjectPostProcessor__mdt custom metadata type - this.executePostProcessors(); + // Run any post-processors configured in the LoggerSObjectHandlerPlugin__mdt custom metadata type + this.executePlugins(); } private void setOrgReleaseCycle() { diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index 75e76f87c..2e465832a 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -9,30 +9,30 @@ */ public abstract class LoggerSObjectHandler { @testVisible - private static Map configurationsBySObjectType; + private static Map configurationsBySObjectType; @testVisible - private static Map> postProcessorsBySObjectType; + private static Map> pluginsBySObjectType; static { // When using CMDT's getAll(), it does not return relationship fields for EntityDefinition fields or child CMDT objects... - // ... so instead query the LoggerSObjectHandlerConfiguration__mdt CMDT object - List configurations = [ + // ... so instead query the LoggerSObjectHandler__mdt CMDT object + List configurations = [ SELECT Id, IsEnabled__c, SObjectType__r.QualifiedApiName, ( - SELECT Id, PostProcessorType__c, PostProcessorApiName__c - FROM LoggerSObjectPostProcessors__r + SELECT Id, PluginType__c, PluginApiName__c + FROM LoggerSObjectHandlerPlugins__r WHERE IsEnabled__c = TRUE ORDER BY ExecutionOrder__c NULLS LAST, DeveloperName ) - FROM LoggerSObjectHandlerConfiguration__mdt + FROM LoggerSObjectHandler__mdt ]; - configurationsBySObjectType = new Map(); - postProcessorsBySObjectType = new Map>(); - for (LoggerSObjectHandlerConfiguration__mdt config : configurations) { + configurationsBySObjectType = new Map(); + pluginsBySObjectType = new Map>(); + for (LoggerSObjectHandler__mdt config : configurations) { // CMDT entity-definition relationship fields are weird, so skip some headaches by copying the Qualified API name config.SObjectType__c = config.SObjectType__r.QualifiedApiName; @@ -40,13 +40,13 @@ public abstract class LoggerSObjectHandler { SObjectType sobjectType = ((SObject) Type.forName(config.SObjectType__c).newInstance()).getSObjectType(); configurationsBySObjectType.put(sobjectType, config); - postProcessorsBySObjectType.put(sobjectType, config?.LoggerSObjectPostProcessors__r); + pluginsBySObjectType.put(sobjectType, config?.LoggerSObjectHandlerPlugins__r); } if (Test.isRunningTest() == true) { // Test shouldn't rely on the actual CMDT rules in the org - clear the loaded values, and defaults will be used configurationsBySObjectType.clear(); - postProcessorsBySObjectType.clear(); + pluginsBySObjectType.clear(); } } @@ -55,16 +55,22 @@ public abstract class LoggerSObjectHandler { @testVisible protected List records; @testVisible + protected Map recordsById; + @testVisible + protected List oldRecords; + @testVisible protected Map oldRecordsById; - private LoggerSObjectHandlerConfiguration__mdt handlerConfiguration; - private List postProcessors; + private LoggerSObjectHandler__mdt handlerConfiguration; + private List plugins; public LoggerSObjectHandler() { this.setConfigurations(); if (this.handlerConfiguration.IsEnabled__c == true) { this.records = Trigger.new; + this.recordsById = Trigger.newMap; + this.oldRecords = Trigger.old; this.oldRecordsById = Trigger.oldMap; this.triggerOperationType = Trigger.operationType; } @@ -80,18 +86,18 @@ public abstract class LoggerSObjectHandler { return this.handlerConfiguration.IsEnabled__c; } - protected void executePostProcessors() { - if (this.records == null || this.postProcessors == null || this.postProcessors.isEmpty()) { + protected void executePlugins() { + if (this.records == null || this.plugins == null || this.plugins.isEmpty()) { return; } - for (LoggerSObjectPostProcessor__mdt postProcessorConfiguration : this.postProcessors) { - switch on postProcessorConfiguration.PostProcessorType__c { + for (LoggerSObjectHandlerPlugin__mdt pluginConfiguration : this.plugins) { + switch on pluginConfiguration.PluginType__c { when 'Apex' { - this.executePostProcessorApexClass(postProcessorConfiguration.PostProcessorApiName__c); + this.executePluginApexClass(pluginConfiguration.PluginApiName__c); } when 'Flow' { - this.executePostProcessorFlow(postProcessorConfiguration.PostProcessorApiName__c); + this.executePluginFlow(pluginConfiguration.PluginApiName__c); } } } @@ -99,32 +105,31 @@ public abstract class LoggerSObjectHandler { private void setConfigurations() { this.handlerConfiguration = configurationsBySObjectType.get(this.getSObjectType()); - this.postProcessors = postProcessorsBySObjectType.get(this.getSObjectType()); + this.plugins = pluginsBySObjectType.get(this.getSObjectType()); if (this.handlerConfiguration == null) { // If no config exists in the org, then load some in-memory defaults - this.handlerConfiguration = new LoggerSObjectHandlerConfiguration__mdt(IsEnabled__c = true, SObjectType__c = this.getSObjectType().getDescribe().getName()); + this.handlerConfiguration = new LoggerSObjectHandler__mdt( + IsEnabled__c = true, + SObjectType__c = this.getSObjectType().getDescribe().getName() + ); configurationsBySObjectType.put(this.getSObjectType(), this.handlerConfiguration); } } - private void executePostProcessorApexClass(String apexClassName) { - LoggerSObjectPostProcessor apexPostProcessor = (LoggerSObjectPostProcessor) Type.forName(apexClassName).newInstance(); - apexPostProcessor.execute(this.triggerOperationType, this.records, this.oldRecordsById); + private void executePluginApexClass(String apexClassName) { + LoggerSObjectHandlerPlugin apexPlugin = (LoggerSObjectHandlerPlugin) Type.forName(apexClassName).newInstance(); + apexPlugin.execute(this.triggerOperationType, this.records, this.recordsById, this.oldRecords, this.oldRecordsById); } - private void executePostProcessorFlow(String flowApiName) { - if (String.isBlank(flowApiName)) { - return; - } - + private void executePluginFlow(String flowApiName) { Map flowInputs = new Map(); flowInputs.put('triggerOperationType', this.triggerOperationType?.name()); flowInputs.put('records', this.records); flowInputs.put('oldRecords', this.oldRecordsById?.values()); - Flow.Interview flowPostProcessor = Flow.Interview.createInterview(flowApiName, flowInputs); - flowPostProcessor.start(); + Flow.Interview flowPlugin = Flow.Interview.createInterview(flowApiName, flowInputs); + flowPlugin.start(); } } diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls similarity index 67% rename from nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls rename to nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls index 5e4130d85..0bbaaa7e9 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls @@ -7,6 +7,12 @@ * @group Log Management * @description Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` */ - global interface LoggerSObjectPostProcessor { - void execute(TriggerOperation triggerOperationType, List loggerRecords, Map oldLoggerRecordsById); -} \ No newline at end of file +global interface LoggerSObjectHandlerPlugin { + void execute( + TriggerOperation triggerOperationType, + List triggerNew, + Map triggerNewMap, + List triggerOld, + Map triggerOldMap + ); +} diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls-meta.xml b/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls-meta.xml similarity index 100% rename from nebula-logger/main/log-management/classes/LoggerSObjectPostProcessor.cls-meta.xml rename to nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls-meta.xml diff --git a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryEventHandler.md-meta.xml b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandler.LogEntryEventHandler.md-meta.xml similarity index 100% rename from nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryEventHandler.md-meta.xml rename to nebula-logger/main/log-management/customMetadata/LoggerSObjectHandler.LogEntryEventHandler.md-meta.xml diff --git a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryHandler.md-meta.xml b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandler.LogEntryHandler.md-meta.xml similarity index 100% rename from nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogEntryHandler.md-meta.xml rename to nebula-logger/main/log-management/customMetadata/LoggerSObjectHandler.LogEntryHandler.md-meta.xml diff --git a/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogHandler.md-meta.xml b/nebula-logger/main/log-management/customMetadata/LoggerSObjectHandler.LogHandler.md-meta.xml similarity index 100% rename from nebula-logger/main/log-management/customMetadata/LoggerSObjectHandlerConfiguration.LogHandler.md-meta.xml rename to nebula-logger/main/log-management/customMetadata/LoggerSObjectHandler.LogHandler.md-meta.xml diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectPostProcessor__mdt-Logger Post Processor Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml similarity index 95% rename from nebula-logger/main/log-management/layouts/LoggerSObjectPostProcessor__mdt-Logger Post Processor Layout.layout-meta.xml rename to nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml index 245ca1196..2d957bfd4 100644 --- a/nebula-logger/main/log-management/layouts/LoggerSObjectPostProcessor__mdt-Logger Post Processor Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml @@ -22,7 +22,7 @@ Required - LoggerSObjectHandlerConfiguration__c + SObjectHandler__c Edit @@ -39,13 +39,13 @@ Required - PostProcessorType__c + PluginType__c Required - PostProcessorApiName__c + PluginApiName__c diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectHandler__mdt-Logger SObject Handler Layout.layout-meta.xml similarity index 93% rename from nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml rename to nebula-logger/main/log-management/layouts/LoggerSObjectHandler__mdt-Logger SObject Handler Layout.layout-meta.xml index 82c740058..c0affbfbd 100644 --- a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerSObjectHandler__mdt-Logger SObject Handler Layout.layout-meta.xml @@ -66,12 +66,12 @@ MasterLabel - IsEnabled__c DeveloperName - PostProcessorType__c - PostProcessorApiName__c + IsEnabled__c + PluginType__c + PluginApiName__c ExecutionOrder__c - LoggerSObjectPostProcessor__mdt.LoggerSObjectHandlerConfiguration__c + LoggerSObjectHandlerPlugin__mdt.SObjectHandler__c ExecutionOrder__c Asc diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/LoggerSObjectPostProcessor__mdt.object-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml similarity index 73% rename from nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/LoggerSObjectPostProcessor__mdt.object-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml index 5571fa57e..6473c03b9 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/LoggerSObjectPostProcessor__mdt.object-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml @@ -1,7 +1,7 @@ Used to configure additional Apex classes and Flows that should be executed for all DML statements on Log__c and LogEntry__c - - Logger SObject Post Processors + + Logger SObject Handler Plugins Public diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/ExecutionOrder__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/ExecutionOrder__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/ExecutionOrder__c.field-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/ExecutionOrder__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/IsEnabled__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/IsEnabled__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/IsEnabled__c.field-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/IsEnabled__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorApiName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml similarity index 87% rename from nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorApiName__c.field-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml index 8de5206f5..b266e11b7 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorApiName__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml @@ -1,8 +1,8 @@ - PostProcessorApiName__c + PluginApiName__c The API name of the metadata to run, based on the Post-Processor Type - - Apex: The name of an Apex class that implements the interface LoggerSObjectPostProcessor + - Apex: The name of an Apex class that implements the interface LoggerSObjectHandlerPlugin - Flow: The API name of a Flow that supports these inputs: - triggerOperationType: text variable - records: record collection variable @@ -10,12 +10,12 @@ false SubscriberControlled The API name of the metadata to run, based on the Post-Processor Type - - Apex: The name of an Apex class that implements the interface LoggerSObjectPostProcessor + - Apex: The name of an Apex class that implements the interface LoggerSObjectHandlerPlugin - Flow: The API name of a Flow that supports these inputs: - triggerOperationType: text variable - records: record collection variable - oldRecords: record collection variable - + 255 true Text diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorType__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml similarity index 89% rename from nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorType__c.field-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml index 2232e61f0..470355af0 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/PostProcessorType__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml @@ -1,9 +1,9 @@ - PostProcessorType__c + PluginType__c false SubscriberControlled - + true Picklist diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/LoggerSObjectHandlerConfiguration__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/SObjectHandler__c.field-meta.xml similarity index 57% rename from nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/LoggerSObjectHandlerConfiguration__c.field-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/SObjectHandler__c.field-meta.xml index 29fc92a96..a2425f815 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/fields/LoggerSObjectHandlerConfiguration__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/SObjectHandler__c.field-meta.xml @@ -1,11 +1,11 @@ - LoggerSObjectHandlerConfiguration__c + SObjectHandler__c false SubscriberControlled - - LoggerSObjectHandlerConfiguration__mdt - LoggerSObjectPostProcessors + + LoggerSObjectHandler__mdt + LoggerSObjectHandlerPlugins true MetadataRelationship false diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/All.listView-meta.xml similarity index 70% rename from nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/listViews/All.listView-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/All.listView-meta.xml index 9c0e8eaee..06c4ba48b 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/listViews/All.listView-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/All.listView-meta.xml @@ -4,9 +4,9 @@ MasterLabel DeveloperName IsEnabled__c - LoggerSObjectHandlerConfiguration__c - PostProcessorType__c - PostProcessorApiName__c + SObjectHandler__c + PluginType__c + PluginApiName__c ExecutionOrder__c Everything diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/validationRules/Plugins_are_not_supported.validationRule-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/validationRules/Plugins_are_not_supported.validationRule-meta.xml new file mode 100644 index 000000000..43ba9e255 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/validationRules/Plugins_are_not_supported.validationRule-meta.xml @@ -0,0 +1,11 @@ + + + Plugins_are_not_supported + true + AND( + SObjectHandler__r.SObjectType__r.DeveloperName != 'Log', + SObjectHandler__r.SObjectType__r.DeveloperName != 'LogEntry' +) + SObjectHandler__c + Plugins are not supported for this SObject Handler + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/LoggerSObjectHandlerConfiguration__mdt.object-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandler__mdt/LoggerSObjectHandler__mdt.object-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/LoggerSObjectHandlerConfiguration__mdt.object-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandler__mdt/LoggerSObjectHandler__mdt.object-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/IsEnabled__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandler__mdt/fields/IsEnabled__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/IsEnabled__c.field-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandler__mdt/fields/IsEnabled__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/SObjectType__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandler__mdt/fields/SObjectType__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/fields/SObjectType__c.field-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandler__mdt/fields/SObjectType__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandler__mdt/listViews/All.listView-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerConfiguration__mdt/listViews/All.listView-meta.xml rename to nebula-logger/main/log-management/objects/LoggerSObjectHandler__mdt/listViews/All.listView-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml deleted file mode 100644 index ded8fd809..000000000 --- a/nebula-logger/main/log-management/objects/LoggerSObjectPostProcessor__mdt/validationRules/Post_processing_is_not_supported.validationRule-meta.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - Post_processing_is_not_supported - true - AND( - LoggerSObjectHandlerConfiguration__r.SObjectType__r.DeveloperName != 'Log', - LoggerSObjectHandlerConfiguration__r.SObjectType__r.DeveloperName != 'LogEntry' -) - LoggerSObjectHandlerConfiguration__c - Post-processors are not supported for this SObject Handler - diff --git a/nebula-logger/main/log-management/profiles/Admin.profile-meta.xml b/nebula-logger/main/log-management/profiles/Admin.profile-meta.xml index e0a173c3b..0b758b580 100644 --- a/nebula-logger/main/log-management/profiles/Admin.profile-meta.xml +++ b/nebula-logger/main/log-management/profiles/Admin.profile-meta.xml @@ -102,7 +102,7 @@ true - LoggerSObjectPostProcessor + LoggerSObjectHandlerPlugin true @@ -1410,17 +1410,17 @@ false - LoggerSObjectHandlerConfiguration__mdt.IsEnabled__c + LoggerSObjectHandler__mdt.IsEnabled__c false false - LoggerSObjectPostProcessor__mdt.ExecutionOrder__c + LoggerSObjectHandlerPlugin__mdt.ExecutionOrder__c false false - LoggerSObjectPostProcessor__mdt.IsEnabled__c + LoggerSObjectHandlerPlugin__mdt.IsEnabled__c false @@ -1433,10 +1433,10 @@ Log__c-Log Layout - LoggerSObjectHandlerConfiguration__mdt-Logger Handler Configuration Layout + LoggerSObjectHandler__mdt-Logger SObject Handler Layout - LoggerSObjectPostProcessor__mdt-Logger Post Processor Layout + LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout true diff --git a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls index 5b0a2b145..47ee58ac0 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls @@ -154,9 +154,9 @@ private class LogEntryEventHandler_Tests { } } - private static LoggerSObjectHandlerConfiguration__mdt getMockConfiguration() { + private static LoggerSObjectHandler__mdt getMockConfiguration() { Schema.SObjectType sobjectType = Schema.LogEntryEvent__e.SObjectType; - return new LoggerSObjectHandlerConfiguration__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); + return new LoggerSObjectHandler__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); } static void validateLogFields(LogEntryEvent__e logEntryEvent, Log__c log) { @@ -276,10 +276,10 @@ private class LogEntryEventHandler_Tests { @isTest static void it_should_not_run_handler_when_disabled_via_configuration() { - LoggerSObjectHandlerConfiguration__mdt logEntryEventHandlerConfiguration = getMockConfiguration(); + LoggerSObjectHandler__mdt logEntryEventHandlerConfiguration = getMockConfiguration(); logEntryEventHandlerConfiguration.IsEnabled__c = false; - Map configurationsBySObjectType = new Map{ + Map configurationsBySObjectType = new Map{ Schema.LogEntryEvent__e.SObjectType => logEntryEventHandlerConfiguration }; diff --git a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls index b4fb800e2..b28d40f04 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls @@ -5,21 +5,27 @@ @isTest private class LogEntryHandler_Tests { - public class LogEntryPostProcessorTest implements LoggerSObjectPostProcessor { - public void execute(TriggerOperation triggerOperationType, List logs, Map oldLogsById) { + public class LogEntryPluginTest implements LoggerSObjectHandlerPlugin { + public void execute( + TriggerOperation triggerOperationType, + List triggerNew, + Map triggerNewMap, + List triggerOld, + Map triggerOldMap + ) { if (triggerOperationType == TriggerOperation.BEFORE_INSERT) { - for (LogEntry__c logEntry : (List) logs) { + for (LogEntry__c logEntry : (List) triggerNew) { // The specific field changed doesn't really matter - we just want to ensure that whatever... - // ...logic implement in the instance of LoggerSObjectPostProcessor is executed + // ...logic implement in the instance of LoggerSObjectHandlerPlugin is executed logEntry.Message__c = 'Some String'; } } } } - private static LoggerSObjectHandlerConfiguration__mdt getMockConfiguration() { + private static LoggerSObjectHandler__mdt getMockConfiguration() { Schema.SObjectType sobjectType = Schema.LogEntry__c.SObjectType; - return new LoggerSObjectHandlerConfiguration__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); + return new LoggerSObjectHandler__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); } @testSetup @@ -47,7 +53,7 @@ private class LogEntryHandler_Tests { // Clear any CMDT records that have been loaded from the database LoggerSObjectHandler.configurationsBySObjectType.clear(); - LoggerSObjectHandlerConfiguration__mdt configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.LogEntry__c.SObjectType); + LoggerSObjectHandler__mdt configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.LogEntry__c.SObjectType); System.assertEquals(null, configuration); insert logEntry; @@ -71,10 +77,10 @@ private class LogEntryHandler_Tests { static void it_should_not_run_handler_when_disabled_via_configuration() { String currentUserJson = JSON.serialize(new User(Id = UserInfo.getUserId())); - LoggerSObjectHandlerConfiguration__mdt logEntryHandlerConfiguration = getMockConfiguration(); + LoggerSObjectHandler__mdt logEntryHandlerConfiguration = getMockConfiguration(); logEntryHandlerConfiguration.IsEnabled__c = false; - Map configurationsBySObjectType = new Map{ + Map configurationsBySObjectType = new Map{ Schema.LogEntry__c.SObjectType => logEntryHandlerConfiguration }; @@ -291,12 +297,12 @@ private class LogEntryHandler_Tests { static void it_should_run_apex_post_processor_when_configured() { String expectedMessage = 'Some String'; - LoggerSObjectPostProcessor__mdt postProcessor = new LoggerSObjectPostProcessor__mdt( - PostProcessorType__c = 'Apex', - PostProcessorApiName__c = LogEntryPostProcessorTest.class.getName() + LoggerSObjectHandlerPlugin__mdt plugin = new LoggerSObjectHandlerPlugin__mdt( + PluginType__c = 'Apex', + PluginApiName__c = LogEntryPluginTest.class.getName() ); - Map> postProcessorsBySObjectType = new Map>{ - Schema.LogEntry__c.SObjectType => new List{ postProcessor } + Map> pluginsBySObjectType = new Map>{ + Schema.LogEntry__c.SObjectType => new List{ plugin } }; Log__c log = [SELECT Id FROM Log__c LIMIT 1]; @@ -304,7 +310,7 @@ private class LogEntryHandler_Tests { Test.startTest(); // Use the mock configurations - LoggerSObjectHandler.postProcessorsBySObjectType = postProcessorsBySObjectType; + LoggerSObjectHandler.pluginsBySObjectType = pluginsBySObjectType; LogEntry__c logEntry = new LogEntry__c(Log__c = log.Id, Message__c = 'qwerty'); insert logEntry; diff --git a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls index 53dc442ee..acfbfee2f 100644 --- a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls @@ -11,26 +11,32 @@ private class LogHandler_Tests { private static final String FIRST_STATUS = Schema.Log__c.Status__c.getDescribe().getPicklistValues().get(0).getValue(); private static final String SECOND_STATUS = Schema.Log__c.Status__c.getDescribe().getPicklistValues().get(1).getValue(); - public class LogPostProcessorTest implements LoggerSObjectPostProcessor { - public void execute(TriggerOperation triggerOperationType, List logs, Map oldLogsById) { + public class LogPluginTest implements LoggerSObjectHandlerPlugin { + public void execute( + TriggerOperation triggerOperationType, + List triggerNew, + Map triggerNewMap, + List triggerOld, + Map triggerOldMap + ) { if (triggerOperationType == TriggerOperation.BEFORE_INSERT) { - for (Log__c log : (List) logs) { + for (Log__c log : (List) triggerNew) { // The specific field changed doesn't really matter - we just want to ensure that whatever... - // ...logic implement in the instance of LoggerSObjectPostProcessor is executed + // ...logic implement in the instance of LoggerSObjectHandlerPlugin is executed log.ProfileName__c = 'Some String'; } } } } - private static LoggerSObjectHandlerConfiguration__mdt getMockConfiguration() { + private static LoggerSObjectHandler__mdt getMockConfiguration() { Schema.SObjectType sobjectType = Schema.Log__c.SObjectType; - return new LoggerSObjectHandlerConfiguration__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); + return new LoggerSObjectHandler__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); } - private static LoggerSObjectHandlerConfiguration__mdt getMockPostProcessor() { + private static LoggerSObjectHandler__mdt getMockPlugin() { Schema.SObjectType sobjectType = Schema.Log__c.SObjectType; - return new LoggerSObjectHandlerConfiguration__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); + return new LoggerSObjectHandler__mdt(IsEnabled__c = true, SObjectType__c = sobjectType.getDescribe().getName()); } @testSetup @@ -60,7 +66,7 @@ private class LogHandler_Tests { // Clear any CMDT records that have been loaded from the database LoggerSObjectHandler.configurationsBySObjectType.clear(); - LoggerSObjectHandlerConfiguration__mdt configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.Log__c.SObjectType); + LoggerSObjectHandler__mdt configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.Log__c.SObjectType); System.assertEquals(null, configuration); Log__c log = new Log__c(LoggedBy__c = UserInfo.getUserId(), Status__c = closedLogStatus.MasterLabel, TransactionId__c = '1234'); @@ -82,10 +88,10 @@ private class LogHandler_Tests { @isTest static void it_should_not_run_handler_when_disabled_via_configuration() { - LoggerSObjectHandlerConfiguration__mdt logHandlerConfiguration = getMockConfiguration(); + LoggerSObjectHandler__mdt logHandlerConfiguration = getMockConfiguration(); logHandlerConfiguration.IsEnabled__c = false; - Map configurationsBySObjectType = new Map{ + Map configurationsBySObjectType = new Map{ Schema.Log__c.SObjectType => logHandlerConfiguration }; @@ -490,18 +496,18 @@ private class LogHandler_Tests { static void it_should_run_apex_post_processor_when_configured() { String expectedProfileName = 'Some String'; - LoggerSObjectPostProcessor__mdt postProcessor = new LoggerSObjectPostProcessor__mdt( - PostProcessorType__c = 'Apex', - PostProcessorApiName__c = LogPostProcessorTest.class.getName() + LoggerSObjectHandlerPlugin__mdt plugin = new LoggerSObjectHandlerPlugin__mdt( + PluginType__c = 'Apex', + PluginApiName__c = LogPluginTest.class.getName() ); - Map> postProcessorsBySObjectType = new Map>{ - Schema.Log__c.SObjectType => new List{ postProcessor } + Map> pluginsBySObjectType = new Map>{ + Schema.Log__c.SObjectType => new List{ plugin } }; Test.startTest(); // Use the mock configurations - LoggerSObjectHandler.postProcessorsBySObjectType = postProcessorsBySObjectType; + LoggerSObjectHandler.pluginsBySObjectType = pluginsBySObjectType; Log__c log = new Log__c(LoggedBy__c = UserInfo.getUserId(), TransactionId__c = '1234'); insert log; From 0e6e1e19cca50ee9ef62987b336c38d2d2360ff2 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Fri, 11 Jun 2021 11:47:49 -0700 Subject: [PATCH 35/82] Fixed a few more old refs to 'post-processor' to use 'plugin' instead --- extra-tests/LogHandler_Tests_Flow.cls | 2 +- .../flows/LogHandler_Tests_Flow.flow-meta.xml | 2 +- .../main/log-management/classes/LogEntryHandler.cls | 2 +- .../main/log-management/classes/LogHandler.cls | 2 +- .../log-management/classes/LoggerSObjectHandler.cls | 12 ++++++------ ...ger SObject Handler Plugin Layout.layout-meta.xml | 2 +- .../fields/PluginApiName__c.field-meta.xml | 4 ++-- .../classes/LogEntryEventHandler_Tests.cls | 4 ++-- .../log-management/classes/LogEntryHandler_Tests.cls | 12 ++++++------ .../log-management/classes/LogHandler_Tests.cls | 12 ++++++------ packages/managed-package/sfdx-project.json | 4 ++-- sfdx-project.json | 5 +++-- 12 files changed, 32 insertions(+), 31 deletions(-) diff --git a/extra-tests/LogHandler_Tests_Flow.cls b/extra-tests/LogHandler_Tests_Flow.cls index a4fa6ce6a..dec886e68 100644 --- a/extra-tests/LogHandler_Tests_Flow.cls +++ b/extra-tests/LogHandler_Tests_Flow.cls @@ -6,7 +6,7 @@ @isTest private class LogHandler_Tests_Flow { @isTest - static void it_should_run_flow_post_processor_when_configured() { + static void it_should_run_flow_plugin_when_configured() { // Assumption: the Flow LogHandler_Tests_Flow makes an update to the current user's FirstName // The specific action within the Flow isn't that important - we just want to make sure... // ...that that Flow is dynamically executed diff --git a/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml b/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml index 6f2d9bae2..de2aca961 100644 --- a/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml +++ b/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml @@ -17,7 +17,7 @@ Save_current_user - An additional Flow used test dynamically running Flow post-processors from LoggerSObjectHandler + An additional Flow used test dynamically running Flow plugins from LoggerSObjectHandler LogHandler_Tests_Flow {!$Flow.CurrentDateTime} diff --git a/nebula-logger/main/log-management/classes/LogEntryHandler.cls b/nebula-logger/main/log-management/classes/LogEntryHandler.cls index 73172d872..c667ff1e9 100644 --- a/nebula-logger/main/log-management/classes/LogEntryHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryHandler.cls @@ -52,7 +52,7 @@ public without sharing class LogEntryHandler extends LoggerSObjectHandler { } } - // Run any post-processors configured in the LoggerSObjectHandlerPlugin__mdt custom metadata type + // Run any plugins configured in the LoggerSObjectHandlerPlugin__mdt custom metadata type this.executePlugins(); } diff --git a/nebula-logger/main/log-management/classes/LogHandler.cls b/nebula-logger/main/log-management/classes/LogHandler.cls index eb88d2814..2bfa1fbce 100644 --- a/nebula-logger/main/log-management/classes/LogHandler.cls +++ b/nebula-logger/main/log-management/classes/LogHandler.cls @@ -75,7 +75,7 @@ public without sharing class LogHandler extends LoggerSObjectHandler { } } - // Run any post-processors configured in the LoggerSObjectHandlerPlugin__mdt custom metadata type + // Run any plugins configured in the LoggerSObjectHandlerPlugin__mdt custom metadata type this.executePlugins(); } diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index 2e465832a..342eca107 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -9,7 +9,7 @@ */ public abstract class LoggerSObjectHandler { @testVisible - private static Map configurationsBySObjectType; + private static Map configurationBySObjectType; @testVisible private static Map> pluginsBySObjectType; @@ -30,7 +30,7 @@ public abstract class LoggerSObjectHandler { FROM LoggerSObjectHandler__mdt ]; - configurationsBySObjectType = new Map(); + configurationBySObjectType = new Map(); pluginsBySObjectType = new Map>(); for (LoggerSObjectHandler__mdt config : configurations) { // CMDT entity-definition relationship fields are weird, so skip some headaches by copying the Qualified API name @@ -39,13 +39,13 @@ public abstract class LoggerSObjectHandler { // Schema.getGlobalDescribe() is the worst, so don't use it SObjectType sobjectType = ((SObject) Type.forName(config.SObjectType__c).newInstance()).getSObjectType(); - configurationsBySObjectType.put(sobjectType, config); + configurationBySObjectType.put(sobjectType, config); pluginsBySObjectType.put(sobjectType, config?.LoggerSObjectHandlerPlugins__r); } if (Test.isRunningTest() == true) { // Test shouldn't rely on the actual CMDT rules in the org - clear the loaded values, and defaults will be used - configurationsBySObjectType.clear(); + configurationBySObjectType.clear(); pluginsBySObjectType.clear(); } } @@ -104,7 +104,7 @@ public abstract class LoggerSObjectHandler { } private void setConfigurations() { - this.handlerConfiguration = configurationsBySObjectType.get(this.getSObjectType()); + this.handlerConfiguration = configurationBySObjectType.get(this.getSObjectType()); this.plugins = pluginsBySObjectType.get(this.getSObjectType()); if (this.handlerConfiguration == null) { @@ -114,7 +114,7 @@ public abstract class LoggerSObjectHandler { SObjectType__c = this.getSObjectType().getDescribe().getName() ); - configurationsBySObjectType.put(this.getSObjectType(), this.handlerConfiguration); + configurationBySObjectType.put(this.getSObjectType(), this.handlerConfiguration); } } diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml index 2d957bfd4..195a8cdad 100644 --- a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml @@ -35,7 +35,7 @@ true true true - + Required diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml index b266e11b7..6b11a8b3f 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml @@ -1,7 +1,7 @@ PluginApiName__c - The API name of the metadata to run, based on the Post-Processor Type + The API name of the metadata to run, based on the Plugin Type - Apex: The name of an Apex class that implements the interface LoggerSObjectHandlerPlugin - Flow: The API name of a Flow that supports these inputs: - triggerOperationType: text variable @@ -9,7 +9,7 @@ - oldRecords: record collection variable false SubscriberControlled - The API name of the metadata to run, based on the Post-Processor Type + The API name of the metadata to run, based on the Plugin Type - Apex: The name of an Apex class that implements the interface LoggerSObjectHandlerPlugin - Flow: The API name of a Flow that supports these inputs: - triggerOperationType: text variable diff --git a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls index 47ee58ac0..26f3025c4 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryEventHandler_Tests.cls @@ -279,14 +279,14 @@ private class LogEntryEventHandler_Tests { LoggerSObjectHandler__mdt logEntryEventHandlerConfiguration = getMockConfiguration(); logEntryEventHandlerConfiguration.IsEnabled__c = false; - Map configurationsBySObjectType = new Map{ + Map configurationBySObjectType = new Map{ Schema.LogEntryEvent__e.SObjectType => logEntryEventHandlerConfiguration }; Test.startTest(); // Use the mock configurations - LoggerSObjectHandler.configurationsBySObjectType = configurationsBySObjectType; + LoggerSObjectHandler.configurationBySObjectType = configurationBySObjectType; LogEntryEvent__e logEntryEvent = new LogEntryEvent__e( EpochTimestamp__c = System.now().getTime(), diff --git a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls index b28d40f04..3083eaf23 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls @@ -52,14 +52,14 @@ private class LogEntryHandler_Tests { Test.startTest(); // Clear any CMDT records that have been loaded from the database - LoggerSObjectHandler.configurationsBySObjectType.clear(); - LoggerSObjectHandler__mdt configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.LogEntry__c.SObjectType); + LoggerSObjectHandler.configurationBySObjectType.clear(); + LoggerSObjectHandler__mdt configuration = LoggerSObjectHandler.configurationBySObjectType.get(Schema.LogEntry__c.SObjectType); System.assertEquals(null, configuration); insert logEntry; // Verify that a default config has been loaded w/ IsEnabled__c = true - configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.LogEntry__c.SObjectType); + configuration = LoggerSObjectHandler.configurationBySObjectType.get(Schema.LogEntry__c.SObjectType); System.assertNotEquals(null, configuration); System.assertEquals(null, configuration.Id); System.assertEquals(true, configuration.IsEnabled__c); @@ -80,7 +80,7 @@ private class LogEntryHandler_Tests { LoggerSObjectHandler__mdt logEntryHandlerConfiguration = getMockConfiguration(); logEntryHandlerConfiguration.IsEnabled__c = false; - Map configurationsBySObjectType = new Map{ + Map configurationBySObjectType = new Map{ Schema.LogEntry__c.SObjectType => logEntryHandlerConfiguration }; @@ -90,7 +90,7 @@ private class LogEntryHandler_Tests { Test.startTest(); // Use the mock configurations - LoggerSObjectHandler.configurationsBySObjectType = configurationsBySObjectType; + LoggerSObjectHandler.configurationBySObjectType = configurationBySObjectType; insert logEntry; @@ -294,7 +294,7 @@ private class LogEntryHandler_Tests { } @isTest - static void it_should_run_apex_post_processor_when_configured() { + static void it_should_run_apex_plugin_when_configured() { String expectedMessage = 'Some String'; LoggerSObjectHandlerPlugin__mdt plugin = new LoggerSObjectHandlerPlugin__mdt( diff --git a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls index acfbfee2f..e2c9a43c0 100644 --- a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls @@ -65,15 +65,15 @@ private class LogHandler_Tests { Test.startTest(); // Clear any CMDT records that have been loaded from the database - LoggerSObjectHandler.configurationsBySObjectType.clear(); - LoggerSObjectHandler__mdt configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.Log__c.SObjectType); + LoggerSObjectHandler.configurationBySObjectType.clear(); + LoggerSObjectHandler__mdt configuration = LoggerSObjectHandler.configurationBySObjectType.get(Schema.Log__c.SObjectType); System.assertEquals(null, configuration); Log__c log = new Log__c(LoggedBy__c = UserInfo.getUserId(), Status__c = closedLogStatus.MasterLabel, TransactionId__c = '1234'); insert log; // Verify that a default config has been loaded w/ IsEnabled__c = true - configuration = LoggerSObjectHandler.configurationsBySObjectType.get(Schema.Log__c.SObjectType); + configuration = LoggerSObjectHandler.configurationBySObjectType.get(Schema.Log__c.SObjectType); System.assertNotEquals(null, configuration); System.assertEquals(null, configuration.Id); System.assertEquals(true, configuration.IsEnabled__c); @@ -91,7 +91,7 @@ private class LogHandler_Tests { LoggerSObjectHandler__mdt logHandlerConfiguration = getMockConfiguration(); logHandlerConfiguration.IsEnabled__c = false; - Map configurationsBySObjectType = new Map{ + Map configurationBySObjectType = new Map{ Schema.Log__c.SObjectType => logHandlerConfiguration }; @@ -100,7 +100,7 @@ private class LogHandler_Tests { Test.startTest(); // Use the mock configurations - LoggerSObjectHandler.configurationsBySObjectType = configurationsBySObjectType; + LoggerSObjectHandler.configurationBySObjectType = configurationBySObjectType; Log__c log = new Log__c(LoggedBy__c = UserInfo.getUserId(), Status__c = closedLogStatus.MasterLabel, TransactionId__c = '1234'); insert log; @@ -493,7 +493,7 @@ private class LogHandler_Tests { } @isTest - static void it_should_run_apex_post_processor_when_configured() { + static void it_should_run_apex_plugin_when_configured() { String expectedProfileName = 'Some String'; LoggerSObjectHandlerPlugin__mdt plugin = new LoggerSObjectHandlerPlugin__mdt( diff --git a/packages/managed-package/sfdx-project.json b/packages/managed-package/sfdx-project.json index 12373201c..f0a9fb441 100644 --- a/packages/managed-package/sfdx-project.json +++ b/packages/managed-package/sfdx-project.json @@ -9,7 +9,7 @@ "default": true, "definitionFile": "config/project-scratch-def.json", "postInstallScript": "LoggerInstallHandler", - "versionName": "Logger SObject Post-Processors", + "versionName": "Logger SObject Handler Plugins", "versionNumber": "4.5.0.0", "ancestorVersion": "4.4.0.2", "versionDescription": "Easily add your own automations for Log__c and LogEntry__c objects using Apex or Flow", @@ -22,6 +22,6 @@ "Nebula Logger - Managed Package@4.2.0-0-more-fields-and-methods": "04t5Y000000Xg4wQAC", "Nebula Logger - Managed Package@4.3.0-3-logger-console-app": "04t5Y000000YLDLQA4", "Nebula Logger - Managed Package@4.4.0-2-config-default-save-method": "04t5Y0000027FFgQAM", - "Nebula Logger - Managed Package@4.5.0-0-logger-sobject-post-processors": "04t5Y0000027FKbQAM" + "Nebula Logger - Managed Package@4.5.0-0-logger-sobject-handler-plugins": "04t5Y0000027FKbQAM" } } diff --git a/sfdx-project.json b/sfdx-project.json index cd74bb38f..0c93e1e5c 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -8,7 +8,7 @@ "path": "nebula-logger", "default": true, "definitionFile": "config/project-scratch-def-with-experience-cloud.json", - "versionName": "Logger SObject Post-Processors", + "versionName": "Logger SObject Handler Plugins", "versionNumber": "4.5.0.0", "versionDescription": "Easily add your own automations for Log__c and LogEntry__c objects using Apex or Flow", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases" @@ -22,6 +22,7 @@ "Nebula Logger - Unlocked Package@4.4.4-0-timestamp-bugfix": "04t5Y0000027FIQQA2", "Nebula Logger - Unlocked Package@4.4.5-0-log-batch-purger-bugfixes": "04t5Y0000027FIVQA2", "Nebula Logger - Unlocked Package@4.4.6-0-new-save-method-synchronous_dml": "04t5Y0000027FJdQAM", - "Nebula Logger - Unlocked Package@4.5.0-0-logger-sobject-post-processors": "04t5Y0000027FKWQA2" + "Nebula Logger - Unlocked Package@4.5.0-0-logger-sobject-handler-plugins": "04t5Y0000027FKWQA2", + "Nebula Logger - Unlocked Package@4.5.0-0": "04t5Y0000027FKqQAM" } } From 8bf8a1a6270efa066148c50c96df6a16dc078098 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Fri, 11 Jun 2021 15:43:04 -0700 Subject: [PATCH 36/82] Created Slack plugin prototype Basics are working - I smooshed the 3+ year old Slack code together into the new plugin interface --- .forceignore | 3 + README.md | 22 ++- nebula-logger-plugins/Slack/README.md | 15 ++ .../Slack/classes/SlackLoggerPlugin.cls | 187 ++++++++++++++++++ .../classes/SlackLoggerPlugin.cls-meta.xml | 5 + ...HandlerPlugin.SlackIntegration.md-meta.xml | 21 ++ .../SendSlackNotification__c.field-meta.xml | 11 ++ .../SlackNotificationDate__c.field-meta.xml | 13 ++ .../LoggerAdmin.permissionset-meta.xml | 14 ++ .../LoggerLogViewer.permissionset-meta.xml | 14 ++ .../Slack.remoteSite-meta.xml | 6 + sfdx-project.json | 16 ++ 12 files changed, 319 insertions(+), 8 deletions(-) create mode 100644 nebula-logger-plugins/Slack/README.md create mode 100644 nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls create mode 100644 nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls-meta.xml create mode 100644 nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackIntegration.md-meta.xml create mode 100644 nebula-logger-plugins/Slack/objects/Log__c/fields/SendSlackNotification__c.field-meta.xml create mode 100644 nebula-logger-plugins/Slack/objects/Log__c/fields/SlackNotificationDate__c.field-meta.xml create mode 100644 nebula-logger-plugins/Slack/permissionsets/LoggerAdmin.permissionset-meta.xml create mode 100644 nebula-logger-plugins/Slack/permissionsets/LoggerLogViewer.permissionset-meta.xml create mode 100644 nebula-logger-plugins/Slack/remoteSiteSettings/Slack.remoteSite-meta.xml diff --git a/.forceignore b/.forceignore index efc018d11..5556f53e9 100644 --- a/.forceignore +++ b/.forceignore @@ -2,6 +2,9 @@ # More information: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm # +# Directory/package-specific README files +**/README.md + # LWC configuration files **/jsconfig.json **/.eslintrc.json diff --git a/README.md b/README.md index c902f50eb..ff753a390 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Designed for Salesforce admins, developers & architects. A robust logger for Apex, Flow, Process Builder & Integrations. -[![Install Unlocked Package](./content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FKWQA2) +[![Install Unlocked Package](./content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FKqQAM) [![Install Managed Package](./content/btn-install-managed-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FKbQAM) [![Deploy Unpackaged Metadata](./content/btn-deploy-unpackaged-metadata.png)](https://githubsfdeploy.herokuapp.com/?owner=jongpie&repo=NebulaLogger&ref=main) [![View Documentation](./content/btn-view-documentation.png)](https://jongpie.github.io/NebulaLogger/) @@ -339,19 +339,25 @@ The class `LogMessage` provides the ability to generate string messages on deman For more details, check out the `LogMessage` class [documentation](https://jongpie.github.io/NebulaLogger/logger-engine/LogMessage). -### Adding Custom Post-Processors for Log\_\_c and LogEntry\_\_c +### Adding Custom Plugins for Log\_\_c and LogEntry\_\_c -If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you can leverage Apex or Flow to define "post-processors" - the logger system will then automatically run the post-processors after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on) +If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you can leverage Apex or Flow to define "plugins" - the logger system will then automatically run the plugins after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on) -- Flow post-processors: your Flow should be built with these input parameters: +- Flow plugins: your Flow should be built with these input parameters: 1. `triggerOperationType` - The name of the current trigger operation (such as BEFORE_INSERT, BEFORE_UPDATE, etc.) 2. `records` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) 3. `oldRecords` - The list of logger records as they exist in the datatabase - this is only populated when running in the context of `Trigger.isUpdate` -- Apex post-processors: your Apex class should implement `LoggerSObjectPostProcessor`. For example: +- Apex plugins: your Apex class should implement `LoggerSObjectHandlerPlugin`. For example: ```java - public class ExamplePostProcessor implements LoggerSObjectPostProcessor { - public void execute(Trigger.operationType triggerOperationType, List logs, Map oldLoggerRecordsById) { + public class ExamplePlugin implements LoggerSObjectHandlerPlugin { + public void execute( + TriggerOperation triggerOperationType, + List triggerNew, + Map triggerNewMap, + List triggerOld, + Map triggerOldMap + ) { switch on triggerOperationType { when BEFORE_INSERT { for (Log__c log : logs) { @@ -364,7 +370,7 @@ If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, ``` -Once you've created your Apex or Flow post-processor(s), you will also need to configure the custom metadata type `LoggerSObjectHandlerConfiguration__mdt` to specify the name(s) of Apex class and Flow to run. +Once you've created your Apex or Flow plugin(s), you will also need to configure the custom metadata type `LoggerSObjectHandler__mdt` to specify the name(s) of Apex class and Flow to run. ![Logger Handler Configuration](./content/logger-handler-configuration.png) diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md new file mode 100644 index 000000000..a0969f028 --- /dev/null +++ b/nebula-logger-plugins/Slack/README.md @@ -0,0 +1,15 @@ +# Slack plugin for Nebula Logger + +Adds a Slack integration for Nebula Logger. Any logs with 1+ ERROR or WARN log entries will automatically be posted to your Slack channel. + +[![Install Unlocked Package](./../../content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=TODO-add-package-ID) + +--- + +Installation Steps + +1. Ensure that you have the unlocked package version of Nebula Logger installed in your org +2. Install/deploy Slack plugin package for Logger +3. Create a new app in you Slack workspace +4. Add Slack as an Auth Provider in your org +5. Add a named credential called 'Slack' in your org diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls new file mode 100644 index 000000000..7c90d65c5 --- /dev/null +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -0,0 +1,187 @@ +//------------------------------------------------------------------------------------------------// +// 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. // +//------------------------------------------------------------------------------------------------// + +public without sharing class SlackLoggerPlugin implements LoggerSObjectHandlerPlugin, Queueable, Database.AllowsCallouts { //, Database.Batchable { + private List logs; + + public SlackLoggerPlugin() { + } + + private SlackLoggerPlugin(List unsentLogs) { + this.logs = unsentLogs; + } + + public void execute( + TriggerOperation triggerOperationType, + List triggerNew, + Map triggerNewMap, + List triggerOld, + Map triggerOldMap + ) { + switch on triggerOperationType { + when BEFORE_INSERT, BEFORE_UPDATE { + for (Log__c log : (List) triggerNew) { + if (log.TotalERRORLogEntries__c > 0 || log.TotalWARNLogEntries__c > 0) { + log.SendSlackNotification__c = true; + } + } + } + when AFTER_INSERT, AFTER_UPDATE { + List logsToSend = new List(); + for (Log__c log : (List) triggerNew) { + if (log.SendSlackNotification__c == true) { + logsToSend.add(log); + } + } + // Since plugins are called from trigger handlers, and triggers can't make callouts... + // ...run this class as a queueable (async) job + if (logsToSend.isEmpty() == false) { + System.enqueueJob(new SlackLoggerPlugin(logsToSend)); + } + } + } + } + + public void execute(System.QueueableContext queueableContext) { + // Requery the logs, in case any other fields have changed + this.logs = [ + SELECT Id, Name, LoggedBy__c, LoggedBy__r.Name, TotalLogEntries__c, TotalERRORLogEntries__c, TotalWARNLogEntries__c, TransactionId__c + FROM Log__c + WHERE Id IN :this.logs AND SendSlackNotification__c = TRUE AND SlackNotificationDate__c = NULL + ]; + + List sentLogs = new List(); + List unsentLogs = new List(); + for (Log__c log : this.logs) { + // log = log.clone(true); + if (Limits.getCallouts() == Limits.getLimitCallouts()) { + // // If there are too many logs to send in the same transaction... + // // ...add them to the unsentLogs list, which will be queued as a separate job + // unsentLogs.add(log); + } else { + NotificationDto notification = new NotificationDto(); + notification.text = 'Salesforce Log Alert'; + notification.attachments = new List(); + notification.attachments.add(this.convertLog(log)); + + HttpRequest request = new HttpRequest(); + request.setEndpoint('callout:Slack'); + request.setMethod('POST'); + request.setHeader('Content-Type', 'application/json'); + String notificationJson = JSON.serialize(notification); + // 'Short' is a reserved word in Apex, but used in Slack's API, so the conversion happens in JSON + notificationJson = notificationJson.replace('"isShort"', '"short"'); + request.setBody(notificationJson); + +System.debug('request==' + request); +System.debug('request.getEndpoint()==' + request.getEndpoint()); +System.debug('request.getBody()==' + request.getBody()); + HttpResponse response = new Http().send(request); + + System.debug('response.getStatusCode()==' + response.getStatusCode()); + System.debug('response.getStatus()==' + response.getStatus()); + System.debug('response.getBody()==' + response.getBody()); + + log.SlackNotificationDate__c = System.now(); + sentLogs.add(log); + } + } + update sentLogs; + + // If any logs couldn't be sent due to governor limits, start a new instance of the job + if (unsentLogs.isEmpty() == false) { + System.enqueueJob(new SlackLoggerPlugin(unsentLogs)); + } + } + + private LogDto convertLog(Log__c log) { + LogDto notification = new LogDto(); + notification.author_link = Url.getSalesforceBaseUrl().toExternalForm() + '/' + log.LoggedBy__c; + notification.author_name = log.LoggedBy__r.Name; + notification.color = log.TotalERRORLogEntries__c >= 1 ? '#FF7373' : '#7CD197'; // Red if there are exceptions, otherwise green + notification.fields = new List(); + notification.text = 'Transaction ID: ' + log.TransactionId__c; + notification.title = log.Name; + notification.title_link = Url.getSalesforceBaseUrl().toExternalForm() + '/' + log.Id; + + FieldDto orgNameField = new FieldDto(); + orgNameField.isShort = false; + orgNameField.title = 'Org Name'; + orgNameField.value = UserInfo.getOrganizationName(); + notification.fields.add(orgNameField); + + FieldDto orgIdField = new FieldDto(); + orgIdField.isShort = true; + orgIdField.title = 'Org ID'; + orgIdField.value = '`' + UserInfo.getOrganizationId() + '`'; + notification.fields.add(orgIdField); + + // FieldDto orgIsProductionField = new FieldDto(); + // orgIsProductionField.isShort = true; + // orgIsProductionField.title = 'Production'; + // orgIsProductionField.value = '`' + !ORG.IsSandbox + '`'; + // notification.fields.add(orgIsProductionField); + + FieldDto totalDebugEntriesField = new FieldDto(); + totalDebugEntriesField.isShort = true; + totalDebugEntriesField.title = '# of Entries'; + totalDebugEntriesField.value = String.valueOf(log.TotalLogEntries__c); + notification.fields.add(totalDebugEntriesField); + + FieldDto totalExceptionEntriesField = new FieldDto(); + totalExceptionEntriesField.isShort = true; + totalExceptionEntriesField.title = '# of Exception Entries'; + totalExceptionEntriesField.value = String.valueOf(log.TotalERRORLogEntries__c); + notification.fields.add(totalExceptionEntriesField); + + List topicNames = new List(); + for (TopicAssignment topicAssignment : log.TopicAssignments) { + topicNames.add(topicAssignment.Topic.Name); + } + topicNames.sort(); + + if (topicNames.isEmpty()) + return notification; + + FieldDto topicsField = new FieldDto(); + topicsField.isShort = false; + topicsField.title = 'Topics'; + topicsField.value = String.join(topicNames, ', '); + notification.fields.add(topicsField); + + return notification; + } + + private class NotificationDto { + public List attachments; + public String text; + } + + private class LogDto { + public List actions; + public String author_name; + public String author_link; + public String author_icon; + public String color; + public String fallback; + public List fields; + public String pretext; + public String text; + public String title; + public String title_link; + } + + private class ActionDto { + public String text; + public String type; + public String url; + } + + private class FieldDto { + public Boolean isShort; + public String title; + public String value; + } +} diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls-meta.xml b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls-meta.xml new file mode 100644 index 000000000..482559c8b --- /dev/null +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls-meta.xml @@ -0,0 +1,5 @@ + + + 51.0 + Active + diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackIntegration.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackIntegration.md-meta.xml new file mode 100644 index 000000000..272235da6 --- /dev/null +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackIntegration.md-meta.xml @@ -0,0 +1,21 @@ + + + + false + + PluginApiName__c + SlackLoggerPlugin + + + PluginType__c + Apex + + + SObjectHandler__c + LogHandler + + diff --git a/nebula-logger-plugins/Slack/objects/Log__c/fields/SendSlackNotification__c.field-meta.xml b/nebula-logger-plugins/Slack/objects/Log__c/fields/SendSlackNotification__c.field-meta.xml new file mode 100644 index 000000000..04d7a579b --- /dev/null +++ b/nebula-logger-plugins/Slack/objects/Log__c/fields/SendSlackNotification__c.field-meta.xml @@ -0,0 +1,11 @@ + + + SendSlackNotification__c + false + false + + false + false + false + Checkbox + diff --git a/nebula-logger-plugins/Slack/objects/Log__c/fields/SlackNotificationDate__c.field-meta.xml b/nebula-logger-plugins/Slack/objects/Log__c/fields/SlackNotificationDate__c.field-meta.xml new file mode 100644 index 000000000..01da4256f --- /dev/null +++ b/nebula-logger-plugins/Slack/objects/Log__c/fields/SlackNotificationDate__c.field-meta.xml @@ -0,0 +1,13 @@ + + + SlackNotificationDate__c + The date/time that the log was sent to Slack + false + The date/time that the log was sent to Slack + + false + true + true + false + DateTime + diff --git a/nebula-logger-plugins/Slack/permissionsets/LoggerAdmin.permissionset-meta.xml b/nebula-logger-plugins/Slack/permissionsets/LoggerAdmin.permissionset-meta.xml new file mode 100644 index 000000000..a866655e2 --- /dev/null +++ b/nebula-logger-plugins/Slack/permissionsets/LoggerAdmin.permissionset-meta.xml @@ -0,0 +1,14 @@ + + + + true + Log__c.SendSlackNotification__c + true + + + true + Log__c.SlackNotificationDate__c + true + + + diff --git a/nebula-logger-plugins/Slack/permissionsets/LoggerLogViewer.permissionset-meta.xml b/nebula-logger-plugins/Slack/permissionsets/LoggerLogViewer.permissionset-meta.xml new file mode 100644 index 000000000..058e922b8 --- /dev/null +++ b/nebula-logger-plugins/Slack/permissionsets/LoggerLogViewer.permissionset-meta.xml @@ -0,0 +1,14 @@ + + + + false + Log__c.SendSlackNotification__c + true + + + false + Log__c.SlackNotificationDate__c + true + + + diff --git a/nebula-logger-plugins/Slack/remoteSiteSettings/Slack.remoteSite-meta.xml b/nebula-logger-plugins/Slack/remoteSiteSettings/Slack.remoteSite-meta.xml new file mode 100644 index 000000000..590b20e07 --- /dev/null +++ b/nebula-logger-plugins/Slack/remoteSiteSettings/Slack.remoteSite-meta.xml @@ -0,0 +1,6 @@ + + + false + true + https://hooks.slack.com + diff --git a/sfdx-project.json b/sfdx-project.json index 0c93e1e5c..491b9447a 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -12,6 +12,22 @@ "versionNumber": "4.5.0.0", "versionDescription": "Easily add your own automations for Log__c and LogEntry__c objects using Apex or Flow", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases" + }, + { + "package": "Nebula Logger - Slack Plugin", + "path": "nebula-logger-plugins/Slack", + "default": false, + "dependencies": [ + { + "package": "Nebula Logger - Unlocked Package", + "versionNumber": "4.5.0.LATEST" + } + ], + "versionNumber": "1.0.0.0" + }, + { + "path": "extra-tests", + "default": false } ], "packageAliases": { From dc1a1793ca0bd503c532de62eed521fc44c287e2 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Fri, 11 Jun 2021 16:15:18 -0700 Subject: [PATCH 37/82] Some code cleanup in SlackLoggerPlugin --- .../Slack/classes/SlackLoggerPlugin.cls | 153 ++++++++++++------ 1 file changed, 100 insertions(+), 53 deletions(-) diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index 7c90d65c5..4ca706942 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -3,7 +3,7 @@ // See LICENSE file or go to https://github.com/jongpie/NebulaLogger for full license details. // //------------------------------------------------------------------------------------------------// -public without sharing class SlackLoggerPlugin implements LoggerSObjectHandlerPlugin, Queueable, Database.AllowsCallouts { //, Database.Batchable { +public without sharing class SlackLoggerPlugin implements LoggerSObjectHandlerPlugin, Queueable, Database.AllowsCallouts { private List logs; public SlackLoggerPlugin() { @@ -22,44 +22,30 @@ public without sharing class SlackLoggerPlugin implements LoggerSObjectHandlerPl ) { switch on triggerOperationType { when BEFORE_INSERT, BEFORE_UPDATE { - for (Log__c log : (List) triggerNew) { - if (log.TotalERRORLogEntries__c > 0 || log.TotalWARNLogEntries__c > 0) { - log.SendSlackNotification__c = true; - } - } + this.flagLogsForSlackNotification((List) triggerNew); } when AFTER_INSERT, AFTER_UPDATE { - List logsToSend = new List(); - for (Log__c log : (List) triggerNew) { - if (log.SendSlackNotification__c == true) { - logsToSend.add(log); - } - } - // Since plugins are called from trigger handlers, and triggers can't make callouts... - // ...run this class as a queueable (async) job - if (logsToSend.isEmpty() == false) { - System.enqueueJob(new SlackLoggerPlugin(logsToSend)); - } + this.sendAsyncSlackNotifications((List) triggerNew); } } } public void execute(System.QueueableContext queueableContext) { - // Requery the logs, in case any other fields have changed - this.logs = [ - SELECT Id, Name, LoggedBy__c, LoggedBy__r.Name, TotalLogEntries__c, TotalERRORLogEntries__c, TotalWARNLogEntries__c, TransactionId__c - FROM Log__c - WHERE Id IN :this.logs AND SendSlackNotification__c = TRUE AND SlackNotificationDate__c = NULL - ]; + // Requery the logs, in case any field values have changed + this.requeryLogs(); + + if (this.logs.isEmpty() == true) { + return; + } List sentLogs = new List(); List unsentLogs = new List(); for (Log__c log : this.logs) { // log = log.clone(true); if (Limits.getCallouts() == Limits.getLimitCallouts()) { - // // If there are too many logs to send in the same transaction... - // // ...add them to the unsentLogs list, which will be queued as a separate job - // unsentLogs.add(log); + // If there are too many logs to send in the same transaction... + // ...add them to the unsentLogs list, which will be queued as a separate job + unsentLogs.add(log); } else { NotificationDto notification = new NotificationDto(); notification.text = 'Salesforce Log Alert'; @@ -70,19 +56,14 @@ public without sharing class SlackLoggerPlugin implements LoggerSObjectHandlerPl request.setEndpoint('callout:Slack'); request.setMethod('POST'); request.setHeader('Content-Type', 'application/json'); - String notificationJson = JSON.serialize(notification); + // 'Short' is a reserved word in Apex, but used in Slack's API, so the conversion happens in JSON - notificationJson = notificationJson.replace('"isShort"', '"short"'); + String notificationJson = JSON.serialize(notification).replace('"isShort"', '"short"'); request.setBody(notificationJson); -System.debug('request==' + request); -System.debug('request.getEndpoint()==' + request.getEndpoint()); -System.debug('request.getBody()==' + request.getBody()); HttpResponse response = new Http().send(request); - System.debug('response.getStatusCode()==' + response.getStatusCode()); System.debug('response.getStatus()==' + response.getStatus()); - System.debug('response.getBody()==' + response.getBody()); log.SlackNotificationDate__c = System.now(); sentLogs.add(log); @@ -96,11 +77,51 @@ System.debug('request.getBody()==' + request.getBody()); } } + private void flagLogsForSlackNotification(List logs) { + for (Log__c log : logs) { + if (log.TotalERRORLogEntries__c > 0 || log.TotalWARNLogEntries__c > 0) { + log.SendSlackNotification__c = true; + } + } + } + + private void sendAsyncSlackNotifications(List logs) { + List logsToSend = new List(); + for (Log__c log : logs) { + if (log.SendSlackNotification__c == true) { + logsToSend.add(log); + } + } + + // Since plugins are called from trigger handlers, and triggers can't make callouts... + // ...run this class as a queueable (async) job + if (logsToSend.isEmpty() == false) { + System.enqueueJob(new SlackLoggerPlugin(logsToSend)); + } + } + + private void requeryLogs() { + this.logs = [ + SELECT + Id, + Name, + LoggedBy__c, + LoggedBy__r.Name, + TotalLogEntries__c, + TotalERRORLogEntries__c, + TotalWARNLogEntries__c, + TransactionId__c, + (SELECT Id, Message__c FROM LogEntries__r WHERE LoggingLevelOrdinal__c >= :LoggingLevel.WARN.ordinal() ORDER BY Timestamp__c) + FROM Log__c + WHERE Id IN :this.logs AND SendSlackNotification__c = TRUE AND SlackNotificationDate__c = NULL + ]; + } + private LogDto convertLog(Log__c log) { LogDto notification = new LogDto(); notification.author_link = Url.getSalesforceBaseUrl().toExternalForm() + '/' + log.LoggedBy__c; notification.author_name = log.LoggedBy__r.Name; - notification.color = log.TotalERRORLogEntries__c >= 1 ? '#FF7373' : '#7CD197'; // Red if there are exceptions, otherwise green + notification.color = this.getNotificationColor(log); notification.fields = new List(); notification.text = 'Transaction ID: ' + log.TransactionId__c; notification.title = log.Name; @@ -124,17 +145,29 @@ System.debug('request.getBody()==' + request.getBody()); // orgIsProductionField.value = '`' + !ORG.IsSandbox + '`'; // notification.fields.add(orgIsProductionField); - FieldDto totalDebugEntriesField = new FieldDto(); - totalDebugEntriesField.isShort = true; - totalDebugEntriesField.title = '# of Entries'; - totalDebugEntriesField.value = String.valueOf(log.TotalLogEntries__c); - notification.fields.add(totalDebugEntriesField); - - FieldDto totalExceptionEntriesField = new FieldDto(); - totalExceptionEntriesField.isShort = true; - totalExceptionEntriesField.title = '# of Exception Entries'; - totalExceptionEntriesField.value = String.valueOf(log.TotalERRORLogEntries__c); - notification.fields.add(totalExceptionEntriesField); + FieldDto totalEntriesField = new FieldDto(); + totalEntriesField.isShort = true; + totalEntriesField.title = '# of Total Entries'; + totalEntriesField.value = String.valueOf(log.TotalLogEntries__c); + notification.fields.add(totalEntriesField); + + FieldDto totalERROREntriesField = new FieldDto(); + totalERROREntriesField.isShort = true; + totalERROREntriesField.title = '# of ERROR Entries'; + totalERROREntriesField.value = String.valueOf(log.TotalERRORLogEntries__c); + notification.fields.add(totalERROREntriesField); + + FieldDto totalWARNEntriesField = new FieldDto(); + totalWARNEntriesField.isShort = true; + totalWARNEntriesField.title = '# of WARN Entries'; + totalWARNEntriesField.value = String.valueOf(log.TotalWARNLogEntries__c); + notification.fields.add(totalWARNEntriesField); + + FieldDto logEntryField = new FieldDto(); + logEntryField.isShort = false; + logEntryField.title = 'Log Entry Message'; + logEntryField.value = '`' + log.LogEntries__r.get(0).Message__c + '`'; + notification.fields.add(logEntryField); List topicNames = new List(); for (TopicAssignment topicAssignment : log.TopicAssignments) { @@ -142,18 +175,32 @@ System.debug('request.getBody()==' + request.getBody()); } topicNames.sort(); - if (topicNames.isEmpty()) - return notification; - - FieldDto topicsField = new FieldDto(); - topicsField.isShort = false; - topicsField.title = 'Topics'; - topicsField.value = String.join(topicNames, ', '); - notification.fields.add(topicsField); + if (topicNames.isEmpty() == false) { + FieldDto topicsField = new FieldDto(); + topicsField.isShort = false; + topicsField.title = 'Topics'; + topicsField.value = '`' + String.join(topicNames, '`, `') + '`'; + notification.fields.add(topicsField); + } return notification; } + private String getNotificationColor(Log__c log) { + String color; + + if (log.TotalERRORLogEntries__c >= 1) { + color = '#FF7373'; + } else if (log.TotalWARNLogEntries__c >= 1) { + color = '#FFC873'; + } else { + color = '#7CD197'; + } + + return color; + } + + // Private DTO classes that match Slack's API private class NotificationDto { public List attachments; public String text; From 58707f9198e593c717ce310e53db57d1b2507ce1 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Fri, 11 Jun 2021 22:01:17 -0700 Subject: [PATCH 38/82] Hello there, LoggerSObjectHandlerPluginParameter__mdt --- nebula-logger-plugins/Slack/README.md | 20 +++- .../Slack/classes/SlackLoggerPlugin.cls | 51 +++++++--- ...ndlerPlugin.SlackLoggerPlugin.md-meta.xml} | 0 ...rPluginParameter.SlackApiToken.md-meta.xml | 13 +++ ...luginParameter.SlackAuthMethod.md-meta.xml | 17 ++++ ...rPluginParameter.SlackEndpoint.md-meta.xml | 17 ++++ .../AllLogsSentToSlack.listView-meta.xml | 21 ++++ .../SlackParameters.listView-meta.xml | 17 ++++ .../classes/LoggerSObjectHandler.cls | 8 +- .../classes/LoggerSObjectHandlerPlugin.cls | 41 +++++++- ...er Plugin Parameter Layout.layout-meta.xml | 95 +++++++++++++++++++ ...ject Handler Plugin Layout.layout-meta.xml | 20 +++- ...andlerPluginParameter__mdt.object-meta.xml | 7 ++ .../fields/DataType__c.field-meta.xml | 80 ++++++++++++++++ .../fields/IsEnabled__c.field-meta.xml | 9 ++ .../SObjectHandlerPlugin__c.field-meta.xml | 13 +++ .../fields/Value__c.field-meta.xml | 10 ++ .../listViews/All.listView-meta.xml | 12 +++ .../classes/LogEntryHandler_Tests.cls | 4 +- .../classes/LogHandler_Tests.cls | 4 +- sfdx-project.json | 2 +- 21 files changed, 432 insertions(+), 29 deletions(-) rename nebula-logger-plugins/Slack/customMetadata/{LoggerSObjectHandlerPlugin.SlackIntegration.md-meta.xml => LoggerSObjectHandlerPlugin.SlackLoggerPlugin.md-meta.xml} (100%) create mode 100644 nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackApiToken.md-meta.xml create mode 100644 nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml create mode 100644 nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml create mode 100644 nebula-logger-plugins/Slack/objects/Log__c/listViews/AllLogsSentToSlack.listView-meta.xml create mode 100644 nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackParameters.listView-meta.xml create mode 100644 nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/IsEnabled__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/SObjectHandlerPlugin__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Value__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index a0969f028..014f0d9c9 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -6,10 +6,28 @@ Adds a Slack integration for Nebula Logger. Any logs with 1+ ERROR or WARN log e --- -Installation Steps +## Installation Steps 1. Ensure that you have the unlocked package version of Nebula Logger installed in your org 2. Install/deploy Slack plugin package for Logger 3. Create a new app in you Slack workspace 4. Add Slack as an Auth Provider in your org 5. Add a named credential called 'Slack' in your org + +--- + +## Setup Steps + +Choose auth method: 'API_TOKEN' or 'NAMED_CREDENTIALS' + +### 'API_TOKEN' Steps + +1. Create remote site setting +2. Create/update logger plugin parameter + +### 'NAMED_CREDENTIALS' Steps + +1. Create Slack app +2. Create Auth Provider +3. Create Named Credential +4. Create/update logger plugin parameter diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index 4ca706942..56bded93a 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -3,7 +3,14 @@ // See LICENSE file or go to https://github.com/jongpie/NebulaLogger for full license details. // //------------------------------------------------------------------------------------------------// -public without sharing class SlackLoggerPlugin implements LoggerSObjectHandlerPlugin, Queueable, Database.AllowsCallouts { +public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugin implements Queueable, Database.AllowsCallouts { + // Constants used for loading configuration & parameters from custom metadata type objects + private static final String AUTH_METHOD_API_TOKEN = 'API_TOKEN'; + private static final String PARAM_API_TOKEN = 'SlackApiToken'; + private static final String PARAM_AUTH_METHOD = 'SlackAuthMethod'; + private static final String PARAM_ENDPOINT = 'SlackEndpoint'; + private static final String SLACK_CONFIGURATION_NAME = 'Slack'; + private List logs; public SlackLoggerPlugin() { @@ -13,7 +20,7 @@ public without sharing class SlackLoggerPlugin implements LoggerSObjectHandlerPl this.logs = unsentLogs; } - public void execute( + public override void execute( TriggerOperation triggerOperationType, List triggerNew, Map triggerNewMap, @@ -47,16 +54,16 @@ public without sharing class SlackLoggerPlugin implements LoggerSObjectHandlerPl // ...add them to the unsentLogs list, which will be queued as a separate job unsentLogs.add(log); } else { + HttpRequest request = this.createHttpRequest(); + System.debug('request.getEndpoint()==' + request.getEndpoint()); + System.debug('request.getMethod()==' + request.getMethod()); + System.debug('request.getBody()==' + request.getBody()); + NotificationDto notification = new NotificationDto(); notification.text = 'Salesforce Log Alert'; notification.attachments = new List(); notification.attachments.add(this.convertLog(log)); - HttpRequest request = new HttpRequest(); - request.setEndpoint('callout:Slack'); - request.setMethod('POST'); - request.setHeader('Content-Type', 'application/json'); - // 'Short' is a reserved word in Apex, but used in Slack's API, so the conversion happens in JSON String notificationJson = JSON.serialize(notification).replace('"isShort"', '"short"'); request.setBody(notificationJson); @@ -106,7 +113,7 @@ public without sharing class SlackLoggerPlugin implements LoggerSObjectHandlerPl Id, Name, LoggedBy__c, - LoggedBy__r.Name, + LoggedBy__r.Username, TotalLogEntries__c, TotalERRORLogEntries__c, TotalWARNLogEntries__c, @@ -117,10 +124,30 @@ public without sharing class SlackLoggerPlugin implements LoggerSObjectHandlerPl ]; } + private HttpRequest createHttpRequest() { + String authMethod = this.getParameterValue(PARAM_AUTH_METHOD); + System.debug('authMethod==' + authMethod); + String endpoint = this.getParameterValue(PARAM_ENDPOINT); + System.debug('endpoint==' + endpoint); + String apiToken = this.getParameterValue(PARAM_API_TOKEN); + System.debug('apiToken==' + apiToken); + + if (authMethod == AUTH_METHOD_API_TOKEN && String.isNotBlank(apiToken)) { + endpoint += apiToken; + } + + HttpRequest request = new HttpRequest(); + request.setEndpoint(endpoint); + request.setMethod('POST'); + request.setHeader('Content-Type', 'application/json'); + + return request; + } + private LogDto convertLog(Log__c log) { LogDto notification = new LogDto(); notification.author_link = Url.getSalesforceBaseUrl().toExternalForm() + '/' + log.LoggedBy__c; - notification.author_name = log.LoggedBy__r.Name; + notification.author_name = log.LoggedBy__r.Username; notification.color = this.getNotificationColor(log); notification.fields = new List(); notification.text = 'Transaction ID: ' + log.TransactionId__c; @@ -190,11 +217,11 @@ public without sharing class SlackLoggerPlugin implements LoggerSObjectHandlerPl String color; if (log.TotalERRORLogEntries__c >= 1) { - color = '#FF7373'; + color = '#FF7373'; // Red } else if (log.TotalWARNLogEntries__c >= 1) { - color = '#FFC873'; + color = '#FFC873'; // Organge } else { - color = '#7CD197'; + color = '#7CD197'; // Green } return color; diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackIntegration.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackLoggerPlugin.md-meta.xml similarity index 100% rename from nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackIntegration.md-meta.xml rename to nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackLoggerPlugin.md-meta.xml diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackApiToken.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackApiToken.md-meta.xml new file mode 100644 index 000000000..2ed6a4844 --- /dev/null +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackApiToken.md-meta.xml @@ -0,0 +1,13 @@ + + + + false + + DataType__c + String + + + SObjectHandlerPlugin__c + SlackLoggerPlugin + + diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml new file mode 100644 index 000000000..2bfcf2ac5 --- /dev/null +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml @@ -0,0 +1,17 @@ + + + + false + + DataType__c + String + + + SObjectHandlerPlugin__c + SlackLoggerPlugin + + + Value__c + API_TOKEN + + diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml new file mode 100644 index 000000000..b7f0ac3c7 --- /dev/null +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml @@ -0,0 +1,17 @@ + + + + false + + DataType__c + String + + + SObjectHandlerPlugin__c + SlackLoggerPlugin + + + Value__c + https://hooks.slack.com/services/ + + diff --git a/nebula-logger-plugins/Slack/objects/Log__c/listViews/AllLogsSentToSlack.listView-meta.xml b/nebula-logger-plugins/Slack/objects/Log__c/listViews/AllLogsSentToSlack.listView-meta.xml new file mode 100644 index 000000000..4de6cecc2 --- /dev/null +++ b/nebula-logger-plugins/Slack/objects/Log__c/listViews/AllLogsSentToSlack.listView-meta.xml @@ -0,0 +1,21 @@ + + + AllLogsSentToSlack + NAME + LoggedByUsernameLink__c + StartTime__c + OWNER.ALIAS + Priority__c + Status__c + TransactionId__c + TotalLimitsCpuTimeUsed__c + TotalLogEntries__c + TotalERRORLogEntries__c + TotalWARNLogEntries__c + Everything + + SlackNotificationDate__c + notEqual + + + diff --git a/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackParameters.listView-meta.xml b/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackParameters.listView-meta.xml new file mode 100644 index 000000000..8e0e235fd --- /dev/null +++ b/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackParameters.listView-meta.xml @@ -0,0 +1,17 @@ + + + SlackParameters + MasterLabel + DeveloperName + SObjectHandlerPlugin__c + IsEnabled__c + DataType__c + Value__c + Everything + + SObjectHandlerPlugin__c + contains + Slack + + + diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index 342eca107..b991dabf6 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -94,10 +94,10 @@ public abstract class LoggerSObjectHandler { for (LoggerSObjectHandlerPlugin__mdt pluginConfiguration : this.plugins) { switch on pluginConfiguration.PluginType__c { when 'Apex' { - this.executePluginApexClass(pluginConfiguration.PluginApiName__c); + this.executeApexPlugin(pluginConfiguration.PluginApiName__c); } when 'Flow' { - this.executePluginFlow(pluginConfiguration.PluginApiName__c); + this.executeFlowPlugin(pluginConfiguration.PluginApiName__c); } } } @@ -118,12 +118,12 @@ public abstract class LoggerSObjectHandler { } } - private void executePluginApexClass(String apexClassName) { + private void executeApexPlugin(String apexClassName) { LoggerSObjectHandlerPlugin apexPlugin = (LoggerSObjectHandlerPlugin) Type.forName(apexClassName).newInstance(); apexPlugin.execute(this.triggerOperationType, this.records, this.recordsById, this.oldRecords, this.oldRecordsById); } - private void executePluginFlow(String flowApiName) { + private void executeFlowPlugin(String flowApiName) { Map flowInputs = new Map(); flowInputs.put('triggerOperationType', this.triggerOperationType?.name()); flowInputs.put('records', this.records); diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls index 0bbaaa7e9..bf968633f 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls @@ -7,12 +7,49 @@ * @group Log Management * @description Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` */ -global interface LoggerSObjectHandlerPlugin { - void execute( +global abstract class LoggerSObjectHandlerPlugin { + global abstract void execute( TriggerOperation triggerOperationType, List triggerNew, Map triggerNewMap, List triggerOld, Map triggerOldMap ); + + global virtual LoggerSObjectHandlerPlugin__mdt getConfiguration() { + // By default, check to see if there is a plugin named after the current Apex class name + // Implementations of LoggerSObjectHandlerPlugin can override this behavior if desired + String currentClassName = String.valueOf(this).substring(0, String.valueOf(this).indexOf(':')); + return LoggerSObjectHandlerPlugin__mdt.getInstance(currentClassName); + } + + // protected LoggerSObjectHandlerPlugin__mdt getConfiguration(String configurationDeveloperName) { + // // To include the child object LoggerSObjectHandlerPluginParameter__mdt, we have to query the object... + // // ...instead of using getAll() + + // // TODO Consider caching the query results... maybe... + // return [ + // SELECT + // Id, + // MasterLabel, + // DeveloperName, + // (SELECT Id, MasterLabel, DeveloperName, DataType__c, Value__c FROM LoggerSObjectHandlerPluginParameters__r WHERE IsEnabled__c = TRUE) + // FROM LoggerSObjectHandlerPlugin__mdt + // WHERE IsEnabled__c = TRUE AND DeveloperName = :configurationDeveloperName + // ]; + // } + + protected String getParameterValue(String parameterDeveloperName) { + return this.getParameter(parameterDeveloperName)?.Value__c; + } + + private LoggerSObjectHandlerPluginParameter__mdt getParameter(String parameterDeveloperName) { + LoggerSObjectHandlerPluginParameter__mdt parameter = LoggerSObjectHandlerPluginParameter__mdt.getInstance(parameterDeveloperName); + + if (parameter == null || parameter.IsEnabled__c == false) { + return null; + } + + return parameter; + } } diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml new file mode 100644 index 000000000..ab7ccd173 --- /dev/null +++ b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml @@ -0,0 +1,95 @@ + + + + false + true + true + + + + Required + MasterLabel + + + Required + DeveloperName + + + + + Edit + IsEnabled__c + + + Required + SObjectHandlerPlugin__c + + + + + + true + true + true + + + + Required + DataType__c + + + Edit + Value__c + + + + + + false + false + true + + + + Required + NamespacePrefix + + + Readonly + CreatedById + + + + + Edit + IsProtected + + + Readonly + LastModifiedById + + + + + + true + true + false + + + + + + + false + false + false + false + false + + 00h11000004BsIW + 4 + 0 + Default + + diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml index 195a8cdad..a15240bdf 100644 --- a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml @@ -1,4 +1,4 @@ - + false @@ -82,18 +82,28 @@ true false - - - + + + + + MasterLabel + DeveloperName + IsEnabled__c + DataType__c + Value__c + LoggerSObjectHandlerPluginParameter__mdt.SObjectHandlerPlugin__c + DeveloperName + Asc + false false false false false - 00h3F0000048voA + 00h11000004Bf4m 4 0 Default diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml new file mode 100644 index 000000000..38e4449b9 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml @@ -0,0 +1,7 @@ + + + Used to store additional key-value pair parameters that can be used by Logger plugins + + Logger SObject Handler Plugin Parameters + Public + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml new file mode 100644 index 000000000..8778dbdd2 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml @@ -0,0 +1,80 @@ + + + DataType__c + false + SubscriberControlled + + true + Picklist + + true + + false + + Blob + true + + + + Boolean + false + + + + Date + false + + + + Datetime + false + + + + Decimal + false + + + + Double + false + + + + Id + false + + + + Integer + false + + + + Long + false + + + + Object + false + + + + SObject + false + + + + String + false + + + + Time + false + + + + + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/IsEnabled__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/IsEnabled__c.field-meta.xml new file mode 100644 index 000000000..48d6876ba --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/IsEnabled__c.field-meta.xml @@ -0,0 +1,9 @@ + + + IsEnabled__c + true + false + SubscriberControlled + + Checkbox + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/SObjectHandlerPlugin__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/SObjectHandlerPlugin__c.field-meta.xml new file mode 100644 index 000000000..916810520 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/SObjectHandlerPlugin__c.field-meta.xml @@ -0,0 +1,13 @@ + + + SObjectHandlerPlugin__c + false + DeveloperControlled + + LoggerSObjectHandlerPlugin__mdt + Logger SObject Handler Plugin Parameters + LoggerSObjectHandlerPluginParameters + true + MetadataRelationship + false + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Value__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Value__c.field-meta.xml new file mode 100644 index 000000000..631301062 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Value__c.field-meta.xml @@ -0,0 +1,10 @@ + + + Value__c + false + SubscriberControlled + + 131072 + LongTextArea + 3 + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml new file mode 100644 index 000000000..72aefe375 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml @@ -0,0 +1,12 @@ + + + All + MasterLabel + DeveloperName + SObjectHandlerPlugin__c + IsEnabled__c + DataType__c + Value__c + Everything + + diff --git a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls index 3083eaf23..e0bc1b6b1 100644 --- a/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogEntryHandler_Tests.cls @@ -5,8 +5,8 @@ @isTest private class LogEntryHandler_Tests { - public class LogEntryPluginTest implements LoggerSObjectHandlerPlugin { - public void execute( + public class LogEntryPluginTest extends LoggerSObjectHandlerPlugin { + public override void execute( TriggerOperation triggerOperationType, List triggerNew, Map triggerNewMap, diff --git a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls index e2c9a43c0..3aee61aa4 100644 --- a/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls +++ b/nebula-logger/tests/log-management/classes/LogHandler_Tests.cls @@ -11,8 +11,8 @@ private class LogHandler_Tests { private static final String FIRST_STATUS = Schema.Log__c.Status__c.getDescribe().getPicklistValues().get(0).getValue(); private static final String SECOND_STATUS = Schema.Log__c.Status__c.getDescribe().getPicklistValues().get(1).getValue(); - public class LogPluginTest implements LoggerSObjectHandlerPlugin { - public void execute( + public class LogPluginTest extends LoggerSObjectHandlerPlugin { + public override void execute( TriggerOperation triggerOperationType, List triggerNew, Map triggerNewMap, diff --git a/sfdx-project.json b/sfdx-project.json index 491b9447a..aa76100fd 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -23,7 +23,7 @@ "versionNumber": "4.5.0.LATEST" } ], - "versionNumber": "1.0.0.0" + "versionNumber": "0.9.0.0" }, { "path": "extra-tests", From a3d63ebc301a721276ee59d103b50c2b383e06bd Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Fri, 11 Jun 2021 22:48:45 -0700 Subject: [PATCH 39/82] Added description fields to plugin & param CMDT objects + new list views --- .../Slack/classes/SlackLoggerPlugin.cls | 5 ++++- ...HandlerPlugin.SlackLoggerPlugin.md-meta.xml | 14 ++++++++------ ...PluginParameter.SlackAuthMethod.md-meta.xml | 7 +++++++ ...eter.SlackLoggingLevelThreshold.md-meta.xml | 17 +++++++++++++++++ .../SendSlackNotification__c.field-meta.xml | 4 ++-- .../SlackParameters.listView-meta.xml | 1 + ...ler Plugin Parameter Layout.layout-meta.xml | 6 +++++- ...bject Handler Plugin Layout.layout-meta.xml | 4 ++++ ...gEntryLoggingLevelOrdinal__c.field-meta.xml | 14 ++++++++++++++ .../fields/Description__c.field-meta.xml | 11 +++++++++++ .../listViews/All.listView-meta.xml | 1 + .../listViews/AllDisabled.listView-meta.xml | 17 +++++++++++++++++ .../listViews/AllEnabled.listView-meta.xml | 17 +++++++++++++++++ .../fields/Description__c.field-meta.xml | 11 +++++++++++ .../listViews/All.listView-meta.xml | 3 ++- .../listViews/AllDisabled.listView-meta.xml | 18 ++++++++++++++++++ .../listViews/AllEnabled.listView-meta.xml | 18 ++++++++++++++++++ .../LoggerAdmin.permissionset-meta.xml | 5 +++++ .../LoggerEndUser.permissionset-meta.xml | 5 +++++ .../LoggerLogViewer.permissionset-meta.xml | 5 +++++ .../profiles/Admin.profile-meta.xml | 5 +++++ 21 files changed, 177 insertions(+), 11 deletions(-) create mode 100644 nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml create mode 100644 nebula-logger/main/log-management/objects/Log__c/fields/MaxLogEntryLoggingLevelOrdinal__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Description__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllDisabled.listView-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllEnabled.listView-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/Description__c.field-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllDisabled.listView-meta.xml create mode 100644 nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllEnabled.listView-meta.xml diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index 56bded93a..f7c66ec34 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -9,6 +9,7 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi private static final String PARAM_API_TOKEN = 'SlackApiToken'; private static final String PARAM_AUTH_METHOD = 'SlackAuthMethod'; private static final String PARAM_ENDPOINT = 'SlackEndpoint'; + private static final String PARAM_LOGGING_LEVEL_THRESHOLD = 'SlackLoggingLevelThreshold'; private static final String SLACK_CONFIGURATION_NAME = 'Slack'; private List logs; @@ -85,8 +86,9 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi } private void flagLogsForSlackNotification(List logs) { + LoggingLevel thresholdLoggingLevel = Logger.getLoggingLevel(PARAM_LOGGING_LEVEL_THRESHOLD); for (Log__c log : logs) { - if (log.TotalERRORLogEntries__c > 0 || log.TotalWARNLogEntries__c > 0) { + if (log.MaxLogEntryLoggingLevelOrdinal__c >= thresholdLoggingLevel.ordinal()) { log.SendSlackNotification__c = true; } } @@ -114,6 +116,7 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi Name, LoggedBy__c, LoggedBy__r.Username, + MaxLogEntryLoggingLevelOrdinal__c, TotalLogEntries__c, TotalERRORLogEntries__c, TotalWARNLogEntries__c, diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackLoggerPlugin.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackLoggerPlugin.md-meta.xml index 272235da6..730b51524 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackLoggerPlugin.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackLoggerPlugin.md-meta.xml @@ -1,11 +1,13 @@ - - + + false + + Description__c + Adds a Slack integration for Nebula Logger. + +Any logs with MaxLogEntryLoggingLevelOrdinal__c >= the parameter 'SlackLoggingLevelThreshold' will send a notification to Slack + PluginApiName__c SlackLoggerPlugin diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml index 2bfcf2ac5..631b0d3ef 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml @@ -6,6 +6,13 @@ DataType__c String + + Description__c + Possible values: + +API_TOKEN +NAMED_CREDENTIALS + SObjectHandlerPlugin__c SlackLoggerPlugin diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml new file mode 100644 index 000000000..c472c2a9b --- /dev/null +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml @@ -0,0 +1,17 @@ + + + + false + + DataType__c + Integer + + + SObjectHandlerPlugin__c + SlackLoggerPlugin + + + Value__c + WARN + + diff --git a/nebula-logger-plugins/Slack/objects/Log__c/fields/SendSlackNotification__c.field-meta.xml b/nebula-logger-plugins/Slack/objects/Log__c/fields/SendSlackNotification__c.field-meta.xml index 04d7a579b..feee1b2e2 100644 --- a/nebula-logger-plugins/Slack/objects/Log__c/fields/SendSlackNotification__c.field-meta.xml +++ b/nebula-logger-plugins/Slack/objects/Log__c/fields/SendSlackNotification__c.field-meta.xml @@ -4,8 +4,8 @@ false false - false - false + true + true false Checkbox diff --git a/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackParameters.listView-meta.xml b/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackParameters.listView-meta.xml index 8e0e235fd..d89651ce2 100644 --- a/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackParameters.listView-meta.xml +++ b/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackParameters.listView-meta.xml @@ -7,6 +7,7 @@ IsEnabled__c DataType__c Value__c + Description__c Everything SObjectHandlerPlugin__c diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml index ab7ccd173..95e64184c 100644 --- a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml @@ -14,6 +14,10 @@ Required DeveloperName + + Edit + Description__c + @@ -46,7 +50,7 @@ false - false + true true diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml index a15240bdf..25a24dc2d 100644 --- a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml @@ -14,6 +14,10 @@ Required DeveloperName + + Edit + Description__c + diff --git a/nebula-logger/main/log-management/objects/Log__c/fields/MaxLogEntryLoggingLevelOrdinal__c.field-meta.xml b/nebula-logger/main/log-management/objects/Log__c/fields/MaxLogEntryLoggingLevelOrdinal__c.field-meta.xml new file mode 100644 index 000000000..17fcb990c --- /dev/null +++ b/nebula-logger/main/log-management/objects/Log__c/fields/MaxLogEntryLoggingLevelOrdinal__c.field-meta.xml @@ -0,0 +1,14 @@ + + + MaxLogEntryLoggingLevelOrdinal__c + The highest logging level ordinal of any related log entries + false + The highest logging level ordinal of any related log entries + + LogEntry__c.LoggingLevelOrdinal__c + LogEntry__c.Log__c + max + false + false + Summary + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Description__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Description__c.field-meta.xml new file mode 100644 index 000000000..3f025aa9d --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Description__c.field-meta.xml @@ -0,0 +1,11 @@ + + + Description__c + Used purely for documentation purposes to store any important details about this parameter + false + SubscriberControlled + Used purely for documentation purposes to store any important details about this parameter + + false + TextArea + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml index 72aefe375..26bd68504 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml @@ -7,6 +7,7 @@ IsEnabled__c DataType__c Value__c + Description__c Everything diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllDisabled.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllDisabled.listView-meta.xml new file mode 100644 index 000000000..b6391d189 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllDisabled.listView-meta.xml @@ -0,0 +1,17 @@ + + + AllDisabled + MasterLabel + DeveloperName + SObjectHandlerPlugin__c + DataType__c + Value__c + Description__c + Everything + + IsEnabled__c + equals + 0 + + + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllEnabled.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllEnabled.listView-meta.xml new file mode 100644 index 000000000..51aad8a69 --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllEnabled.listView-meta.xml @@ -0,0 +1,17 @@ + + + AllEnabled + MasterLabel + DeveloperName + SObjectHandlerPlugin__c + DataType__c + Value__c + Description__c + Everything + + IsEnabled__c + equals + 1 + + + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/Description__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/Description__c.field-meta.xml new file mode 100644 index 000000000..7180167bd --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/Description__c.field-meta.xml @@ -0,0 +1,11 @@ + + + Description__c + Used purely for documentation purposes to store any important details about this plugin + false + SubscriberControlled + Used purely for documentation purposes to store any important details about this plugin + + false + TextArea + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/All.listView-meta.xml index 06c4ba48b..efec1f187 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/All.listView-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/All.listView-meta.xml @@ -1,4 +1,4 @@ - + All MasterLabel @@ -8,6 +8,7 @@ PluginType__c PluginApiName__c ExecutionOrder__c + Description__c Everything diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllDisabled.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllDisabled.listView-meta.xml new file mode 100644 index 000000000..6638affcc --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllDisabled.listView-meta.xml @@ -0,0 +1,18 @@ + + + AllDisabled + MasterLabel + DeveloperName + SObjectHandler__c + PluginType__c + PluginApiName__c + ExecutionOrder__c + Description__c + Everything + + IsEnabled__c + equals + 0 + + + diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllEnabled.listView-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllEnabled.listView-meta.xml new file mode 100644 index 000000000..3c0256e2d --- /dev/null +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllEnabled.listView-meta.xml @@ -0,0 +1,18 @@ + + + AllEnabled + MasterLabel + DeveloperName + SObjectHandler__c + PluginType__c + PluginApiName__c + ExecutionOrder__c + Description__c + Everything + + IsEnabled__c + equals + 1 + + + diff --git a/nebula-logger/main/log-management/permissionsets/LoggerAdmin.permissionset-meta.xml b/nebula-logger/main/log-management/permissionsets/LoggerAdmin.permissionset-meta.xml index 73dc83470..941ff8ddf 100644 --- a/nebula-logger/main/log-management/permissionsets/LoggerAdmin.permissionset-meta.xml +++ b/nebula-logger/main/log-management/permissionsets/LoggerAdmin.permissionset-meta.xml @@ -584,6 +584,11 @@ Log__c.LogoutUrl__c true + + false + Log__c.MaxLogEntryLoggingLevelOrdinal__c + true + false Log__c.NetworkId__c diff --git a/nebula-logger/main/log-management/permissionsets/LoggerEndUser.permissionset-meta.xml b/nebula-logger/main/log-management/permissionsets/LoggerEndUser.permissionset-meta.xml index f487a98e6..4d097b02a 100644 --- a/nebula-logger/main/log-management/permissionsets/LoggerEndUser.permissionset-meta.xml +++ b/nebula-logger/main/log-management/permissionsets/LoggerEndUser.permissionset-meta.xml @@ -562,6 +562,11 @@ Log__c.LogoutUrl__c true + + false + Log__c.MaxLogEntryLoggingLevelOrdinal__c + true + false Log__c.NetworkId__c diff --git a/nebula-logger/main/log-management/permissionsets/LoggerLogViewer.permissionset-meta.xml b/nebula-logger/main/log-management/permissionsets/LoggerLogViewer.permissionset-meta.xml index 7057662c5..b09a3fe0b 100644 --- a/nebula-logger/main/log-management/permissionsets/LoggerLogViewer.permissionset-meta.xml +++ b/nebula-logger/main/log-management/permissionsets/LoggerLogViewer.permissionset-meta.xml @@ -548,6 +548,11 @@ Log__c.LogoutUrl__c true + + false + Log__c.MaxLogEntryLoggingLevelOrdinal__c + true + false Log__c.NetworkId__c diff --git a/nebula-logger/main/log-management/profiles/Admin.profile-meta.xml b/nebula-logger/main/log-management/profiles/Admin.profile-meta.xml index 0b758b580..01a9639c9 100644 --- a/nebula-logger/main/log-management/profiles/Admin.profile-meta.xml +++ b/nebula-logger/main/log-management/profiles/Admin.profile-meta.xml @@ -1158,6 +1158,11 @@ Log__c.LogoutUrl__c true + + false + Log__c.MaxLogEntryLoggingLevelOrdinal__c + true + false Log__c.NetworkId__c From 85f43285aa1ad2f411d7f95c5ac70a5fb03e7450 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Fri, 11 Jun 2021 23:13:54 -0700 Subject: [PATCH 40/82] WIP: SlackLoggerPlugin_Tests (currently failing) --- .../Slack/classes/SlackLoggerPlugin.cls | 14 +-- .../Slack/classes/SlackLoggerPlugin_Tests.cls | 95 +++++++++++++++++++ .../SlackLoggerPlugin_Tests.cls-meta.xml | 5 + 3 files changed, 108 insertions(+), 6 deletions(-) create mode 100644 nebula-logger-plugins/Slack/classes/SlackLoggerPlugin_Tests.cls create mode 100644 nebula-logger-plugins/Slack/classes/SlackLoggerPlugin_Tests.cls-meta.xml diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index f7c66ec34..4b88323ec 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -28,12 +28,14 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi List triggerOld, Map triggerOldMap ) { + this.logs = (List) triggerNew; + switch on triggerOperationType { when BEFORE_INSERT, BEFORE_UPDATE { - this.flagLogsForSlackNotification((List) triggerNew); + this.flagLogsForSlackNotification(); } when AFTER_INSERT, AFTER_UPDATE { - this.sendAsyncSlackNotifications((List) triggerNew); + this.sendAsyncSlackNotifications(); } } } @@ -85,18 +87,18 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi } } - private void flagLogsForSlackNotification(List logs) { + private void flagLogsForSlackNotification() { LoggingLevel thresholdLoggingLevel = Logger.getLoggingLevel(PARAM_LOGGING_LEVEL_THRESHOLD); - for (Log__c log : logs) { + for (Log__c log : this.logs) { if (log.MaxLogEntryLoggingLevelOrdinal__c >= thresholdLoggingLevel.ordinal()) { log.SendSlackNotification__c = true; } } } - private void sendAsyncSlackNotifications(List logs) { + private void sendAsyncSlackNotifications() { List logsToSend = new List(); - for (Log__c log : logs) { + for (Log__c log : this.logs) { if (log.SendSlackNotification__c == true) { logsToSend.add(log); } diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin_Tests.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin_Tests.cls new file mode 100644 index 000000000..68248c986 --- /dev/null +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin_Tests.cls @@ -0,0 +1,95 @@ +//------------------------------------------------------------------------------------------------// +// 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. // +//------------------------------------------------------------------------------------------------// + +@isTest +private class SlackLoggerPlugin_Tests { + public class SuccessCalloutMock implements HttpCalloutMock { + public HttpResponse respond(HttpRequest request) { + HttpResponse response = new HttpResponse(); + response.setBody(request.getBody()); + response.setStatusCode(200); + return response; + } + } + + public class FailureCalloutMock implements HttpCalloutMock { + public HttpResponse respond(HttpRequest request) { + HttpResponse response = new HttpResponse(); + response.setBody(request.getBody()); + response.setStatusCode(400); + return response; + } + } + + static void verifyLogEntryCountEquals(Integer expectedCount) { + List existingLogEntries = [SELECT Id FROM LogEntry__c]; + System.assertEquals(expectedCount, existingLogEntries.size()); + } + + @isTest + static void it_should_push_a_debug_log_entry_and_update_push_date() { + verifyLogEntryCountEquals(0); + + Log__c log = new Log__c(SendSlackNotification__c = false, TransactionId__c = '1234'); + insert log; + + LoggingLevel logEntryLoggingLevel = LoggingLevel.DEBUG; + LogEntry__c logEntry = new LogEntry__c( + Log__c = log.Id, + LoggingLevel__c = logEntryLoggingLevel.name(), + LoggingLevelOrdinal__c = logEntryLoggingLevel.ordinal() + ); + insert logEntry; + + verifyLogEntryCountEquals(1); + + log = [SELECT Id, MaxLogEntryLoggingLevelOrdinal__c, SendSlackNotification__c, SlackNotificationDate__c FROM Log__c]; + System.assertEquals(false, log.SendSlackNotification__c); + System.assertEquals(null, log.SlackNotificationDate__c); + + Test.startTest(); + Test.setMock(HttpCalloutMock.class, new SuccessCalloutMock()); + + new SlackLoggerPlugin().execute(TriggerOperation.BEFORE_UPDATE, new List{ log }, null, null, null); + System.assertEquals(true, log.SendSlackNotification__c); + + new SlackLoggerPlugin().execute(TriggerOperation.AFTER_UPDATE, new List{ log }, null, null, null); + // log = [SELECT Id, MaxLogEntryLoggingLevelOrdinal__c, SendSlackNotification__c, SlackNotificationDate__c FROM Log__c]; + System.assertEquals(true, log.SendSlackNotification__c); + System.assertNotEquals(null, log.SlackNotificationDate__c); + System.assertEquals(System.today(), log.SlackNotificationDate__c.date()); + + Test.stopTest(); + } + + // @isTest + // static void it_should_not_push_a_log_entry_when_configured_level_not_met() { + // verifyLogEntryCountEquals(0); + // Logger.warn('testing Slack integration'); + // Logger.saveLog(); + // Test.getEventBus().deliver(); + // verifyLogEntryCountEquals(1); + + // // To make sure that Slack push is not triggered, we need to update a field on the parent Log__c + // Log__c log = [SELECT Id, SendSlackNotification__c FROM Log__c]; + // log.SendSlackNotification__c = false; + // update log; + + // LogEntry__c logEntry = [SELECT Id, Log__r.SendSlackNotification__c, Log__r.SlackNotificationDate__c FROM LogEntry__c]; + // System.assertEquals(false, logEntry.Log__r.SendSlackNotification__c); + // System.assertEquals(null, logEntry.Log__r.SlackNotificationDate__c); + + // Test.startTest(); + // Test.setMock(HttpCalloutMock.class, new SuccessCalloutMock()); + + // Database.executeBatch(new SlackLoggerPlugin()); + + // Test.stopTest(); + + // logEntry = [SELECT Id, Log__r.SendSlackNotification__c, Log__r.SlackNotificationDate__c FROM LogEntry__c]; + // System.assertEquals(false, logEntry.Log__r.SendSlackNotification__c); + // System.assertEquals(null, logEntry.Log__r.SlackNotificationDate__c); + // } +} diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin_Tests.cls-meta.xml b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin_Tests.cls-meta.xml new file mode 100644 index 000000000..d75b0582f --- /dev/null +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin_Tests.cls-meta.xml @@ -0,0 +1,5 @@ + + + 51.0 + Active + From 88af654da65e54467e9e7a5be8fd5942a5ddddd5 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Fri, 11 Jun 2021 23:18:21 -0700 Subject: [PATCH 41/82] Renamed Slack parameter list view --- ...tView-meta.xml => SlackLoggerPlugin.listView-meta.xml} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/{SlackParameters.listView-meta.xml => SlackLoggerPlugin.listView-meta.xml} (73%) diff --git a/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackParameters.listView-meta.xml b/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackLoggerPlugin.listView-meta.xml similarity index 73% rename from nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackParameters.listView-meta.xml rename to nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackLoggerPlugin.listView-meta.xml index d89651ce2..16e7b979f 100644 --- a/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackParameters.listView-meta.xml +++ b/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackLoggerPlugin.listView-meta.xml @@ -1,6 +1,6 @@ - SlackParameters + SlackLoggerPlugin MasterLabel DeveloperName SObjectHandlerPlugin__c @@ -11,8 +11,8 @@ Everything SObjectHandlerPlugin__c - contains - Slack + equals + SlackLoggerPlugin - + From a3bf731ea3c164e9e2a68b0bb187f72a57739b1e Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Fri, 11 Jun 2021 23:21:35 -0700 Subject: [PATCH 42/82] Added description to Slack remote site setting --- .../Slack/remoteSiteSettings/Slack.remoteSite-meta.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/nebula-logger-plugins/Slack/remoteSiteSettings/Slack.remoteSite-meta.xml b/nebula-logger-plugins/Slack/remoteSiteSettings/Slack.remoteSite-meta.xml index 590b20e07..3c9a47fda 100644 --- a/nebula-logger-plugins/Slack/remoteSiteSettings/Slack.remoteSite-meta.xml +++ b/nebula-logger-plugins/Slack/remoteSiteSettings/Slack.remoteSite-meta.xml @@ -1,5 +1,6 @@ + Used to send notifications to Slack false true https://hooks.slack.com From 2df4727e68d451ba4ce6fdda65ee6ef5e4a837bc Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 00:52:22 -0700 Subject: [PATCH 43/82] Made more changes to the format of Slack notification --- .../Slack/classes/SlackLoggerPlugin.cls | 104 +++++++++++++----- sfdx-project.json | 9 +- 2 files changed, 78 insertions(+), 35 deletions(-) diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index 4b88323ec..8404813a5 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -116,14 +116,32 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi SELECT Id, Name, + ApiVersion__c, LoggedBy__c, LoggedBy__r.Username, + OwnerId, + TYPEOF Owner + WHEN User THEN Username + ELSE Name + END, MaxLogEntryLoggingLevelOrdinal__c, + OrganizationId__c, + OrganizationEnvironmentType__c, + OrganizationInstanceName__c, + OrganizationName__c, + Priority__c, + StartTime__c, + TimeZoneId__c, TotalLogEntries__c, TotalERRORLogEntries__c, TotalWARNLogEntries__c, TransactionId__c, - (SELECT Id, Message__c FROM LogEntries__r WHERE LoggingLevelOrdinal__c >= :LoggingLevel.WARN.ordinal() ORDER BY Timestamp__c) + ( + SELECT Id, LoggingLevel__c, Message__c + FROM LogEntries__r + WHERE LoggingLevelOrdinal__c >= :LoggingLevel.WARN.ordinal() + ORDER BY Timestamp__c DESC + ) FROM Log__c WHERE Id IN :this.logs AND SendSlackNotification__c = TRUE AND SlackNotificationDate__c = NULL ]; @@ -155,52 +173,78 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi notification.author_name = log.LoggedBy__r.Username; notification.color = this.getNotificationColor(log); notification.fields = new List(); - notification.text = 'Transaction ID: ' + log.TransactionId__c; + notification.text = Schema.Log__c.TotalLogEntries__c.getDescribe().getLabel() + ': `' + String.valueOf(log.TotalLogEntries__c) + '`'; notification.title = log.Name; notification.title_link = Url.getSalesforceBaseUrl().toExternalForm() + '/' + log.Id; - FieldDto orgNameField = new FieldDto(); - orgNameField.isShort = false; - orgNameField.title = 'Org Name'; - orgNameField.value = UserInfo.getOrganizationName(); - notification.fields.add(orgNameField); + FieldDto startTimeField = new FieldDto(); + startTimeField.isShort = true; + startTimeField.title = Schema.Log__c.StartTime__c.getDescribe().getLabel(); + startTimeField.value = '`' + log.StartTime__c.format() + ' ' + log.TimeZoneId__c + '`'; + notification.fields.add(startTimeField); - FieldDto orgIdField = new FieldDto(); - orgIdField.isShort = true; - orgIdField.title = 'Org ID'; - orgIdField.value = '`' + UserInfo.getOrganizationId() + '`'; - notification.fields.add(orgIdField); - - // FieldDto orgIsProductionField = new FieldDto(); - // orgIsProductionField.isShort = true; - // orgIsProductionField.title = 'Production'; - // orgIsProductionField.value = '`' + !ORG.IsSandbox + '`'; - // notification.fields.add(orgIsProductionField); - - FieldDto totalEntriesField = new FieldDto(); - totalEntriesField.isShort = true; - totalEntriesField.title = '# of Total Entries'; - totalEntriesField.value = String.valueOf(log.TotalLogEntries__c); - notification.fields.add(totalEntriesField); + FieldDto transactionIdField = new FieldDto(); + transactionIdField.isShort = true; + transactionIdField.title = Schema.Log__c.TransactionId__c.getDescribe().getLabel(); + transactionIdField.value = '`' + log.TransactionId__c + '`'; + notification.fields.add(transactionIdField); FieldDto totalERROREntriesField = new FieldDto(); totalERROREntriesField.isShort = true; - totalERROREntriesField.title = '# of ERROR Entries'; - totalERROREntriesField.value = String.valueOf(log.TotalERRORLogEntries__c); + totalERROREntriesField.title = Schema.Log__c.TotalERRORLogEntries__c.getDescribe().getLabel(); + totalERROREntriesField.value = '`' + String.valueOf(log.TotalERRORLogEntries__c) + '`'; notification.fields.add(totalERROREntriesField); FieldDto totalWARNEntriesField = new FieldDto(); totalWARNEntriesField.isShort = true; - totalWARNEntriesField.title = '# of WARN Entries'; - totalWARNEntriesField.value = String.valueOf(log.TotalWARNLogEntries__c); + totalWARNEntriesField.title = Schema.Log__c.TotalWARNLogEntries__c.getDescribe().getLabel(); + totalWARNEntriesField.value = '`' + String.valueOf(log.TotalWARNLogEntries__c) + '`'; notification.fields.add(totalWARNEntriesField); + LogEntry__c lastLogEntry = log.LogEntries__r.get(0); FieldDto logEntryField = new FieldDto(); logEntryField.isShort = false; - logEntryField.title = 'Log Entry Message'; - logEntryField.value = '`' + log.LogEntries__r.get(0).Message__c + '`'; + logEntryField.title = 'Last Log Entry Message'; + logEntryField.value = lastLogEntry.LoggingLevel__c + ': `' + lastLogEntry.Message__c + '`'; notification.fields.add(logEntryField); + String logOwnerType = log.OwnerId.getSObjectType().getDescribe().getName(); + FieldDto logOwnerNameField = new FieldDto(); + logOwnerNameField.isShort = true; + logOwnerNameField.title = 'Log Owner'; + logOwnerNameField.value = logOwnerType == 'Group' ? '`Queue: ' + log.Owner.Name + '`' : '`User: ' + log.Owner.Username + '`'; + notification.fields.add(logOwnerNameField); + + FieldDto priorityField = new FieldDto(); + priorityField.isShort = true; + priorityField.title = Schema.Log__c.Priority__c.getDescribe().getLabel(); + priorityField.value = '`' + log.Priority__c + '`'; + notification.fields.add(priorityField); + + FieldDto orgIdField = new FieldDto(); + orgIdField.isShort = true; + orgIdField.title = 'Org ID'; + orgIdField.value = '`' + log.OrganizationId__c + '`'; + notification.fields.add(orgIdField); + + FieldDto orgNameField = new FieldDto(); + orgNameField.isShort = true; + orgNameField.title = 'Org Name'; + orgNameField.value = '`' + log.OrganizationName__c + '`'; + notification.fields.add(orgNameField); + + FieldDto orgTypeField = new FieldDto(); + orgTypeField.isShort = true; + orgTypeField.title = 'Org Type & Instance'; + orgTypeField.value = '`' + log.OrganizationEnvironmentType__c + ' - ' + log.OrganizationInstanceName__c + '`'; + notification.fields.add(orgTypeField); + + FieldDto orgApiVersion = new FieldDto(); + orgApiVersion.isShort = true; + orgApiVersion.title = Schema.Log__c.ApiVersion__c.getDescribe().getLabel(); + orgApiVersion.value = '`' + log.ApiVersion__c + '`'; + notification.fields.add(orgApiVersion); + List topicNames = new List(); for (TopicAssignment topicAssignment : log.TopicAssignments) { topicNames.add(topicAssignment.Topic.Name); diff --git a/sfdx-project.json b/sfdx-project.json index aa76100fd..03a347eb2 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -16,7 +16,6 @@ { "package": "Nebula Logger - Slack Plugin", "path": "nebula-logger-plugins/Slack", - "default": false, "dependencies": [ { "package": "Nebula Logger - Unlocked Package", @@ -26,8 +25,7 @@ "versionNumber": "0.9.0.0" }, { - "path": "extra-tests", - "default": false + "path": "extra-tests" } ], "packageAliases": { @@ -39,6 +37,7 @@ "Nebula Logger - Unlocked Package@4.4.5-0-log-batch-purger-bugfixes": "04t5Y0000027FIVQA2", "Nebula Logger - Unlocked Package@4.4.6-0-new-save-method-synchronous_dml": "04t5Y0000027FJdQAM", "Nebula Logger - Unlocked Package@4.5.0-0-logger-sobject-handler-plugins": "04t5Y0000027FKWQA2", - "Nebula Logger - Unlocked Package@4.5.0-0": "04t5Y0000027FKqQAM" + "Nebula Logger - Unlocked Package@4.5.0-0": "04t5Y0000027FKqQAM", + "Nebula Logger - Slack Plugin": "0Ho5Y000000TNKoSAO" } -} +} \ No newline at end of file From 75fb0741f8264cf448b6c8e47ee05e611629b105 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 21:06:23 -0700 Subject: [PATCH 44/82] Converted plugin framework to public for now - once stabilized, I'll convert to global/add to mgd pkg --- extra-tests/LogHandler_Tests_Flow.cls | 5 +- nebula-logger-plugins/Slack/README.md | 5 +- .../Slack/classes/SlackLoggerPlugin.cls | 43 +++++++----- .../classes/LoggerSObjectHandler.cls | 5 +- .../classes/LoggerSObjectHandlerPlugin.cls | 69 ++++++++++++------- ...er Plugin Parameter Layout.layout-meta.xml | 8 +-- ...ject Handler Plugin Layout.layout-meta.xml | 17 +++-- ...andlerPluginParameter__mdt.object-meta.xml | 2 +- .../fields/DataType__c.field-meta.xml | 5 -- .../fields/Description__c.field-meta.xml | 11 +-- ...rSObjectHandlerPlugin__mdt.object-meta.xml | 4 +- .../fields/Description__c.field-meta.xml | 11 +-- sfdx-project.json | 2 +- 13 files changed, 107 insertions(+), 80 deletions(-) diff --git a/extra-tests/LogHandler_Tests_Flow.cls b/extra-tests/LogHandler_Tests_Flow.cls index dec886e68..c72161203 100644 --- a/extra-tests/LogHandler_Tests_Flow.cls +++ b/extra-tests/LogHandler_Tests_Flow.cls @@ -14,10 +14,7 @@ private class LogHandler_Tests_Flow { String expectedUserFirstName = 'Logger-Flow-Test'; System.assertNotEquals(expectedUserFirstName, UserInfo.getFirstName()); - LoggerSObjectHandlerPlugin__mdt plugin = new LoggerSObjectHandlerPlugin__mdt( - PluginType__c = 'Flow', - PluginApiName__c = pluginFlowApiName - ); + LoggerSObjectHandlerPlugin__mdt plugin = new LoggerSObjectHandlerPlugin__mdt(PluginType__c = 'Flow', PluginApiName__c = pluginFlowApiName); Map> pluginsBySObjectType = new Map>{ Schema.Log__c.SObjectType => new List{ plugin } }; diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index 014f0d9c9..346ae6498 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -28,6 +28,5 @@ Choose auth method: 'API_TOKEN' or 'NAMED_CREDENTIALS' ### 'NAMED_CREDENTIALS' Steps 1. Create Slack app -2. Create Auth Provider -3. Create Named Credential -4. Create/update logger plugin parameter +2. Create Auth Provider & Named Credential - See [UnofficialSF.com's article](https://unofficialsf.com/authorizing-salesforce-access-to-slack/) on how to set this up for Slack +3. Create/update logger plugin parameter diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index 8404813a5..03325b1be 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -5,12 +5,15 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugin implements Queueable, Database.AllowsCallouts { // Constants used for loading configuration & parameters from custom metadata type objects - private static final String AUTH_METHOD_API_TOKEN = 'API_TOKEN'; private static final String PARAM_API_TOKEN = 'SlackApiToken'; private static final String PARAM_AUTH_METHOD = 'SlackAuthMethod'; private static final String PARAM_ENDPOINT = 'SlackEndpoint'; - private static final String PARAM_LOGGING_LEVEL_THRESHOLD = 'SlackLoggingLevelThreshold'; - private static final String SLACK_CONFIGURATION_NAME = 'Slack'; + private static final String PARAM_THRESHOLD_LOGGING_LEVEL_NAME = 'SlackLoggingLevelThreshold'; + + private enum SlackAuthMethod { + API_TOKEN, + NAMED_CREDENTIAL + } private List logs; @@ -41,7 +44,7 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi } public void execute(System.QueueableContext queueableContext) { - // Requery the logs, in case any field values have changed + // SInce this runs in an async context, requery the logs just in case any field values have changed this.requeryLogs(); if (this.logs.isEmpty() == true) { @@ -51,21 +54,16 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi List sentLogs = new List(); List unsentLogs = new List(); for (Log__c log : this.logs) { - // log = log.clone(true); if (Limits.getCallouts() == Limits.getLimitCallouts()) { // If there are too many logs to send in the same transaction... // ...add them to the unsentLogs list, which will be queued as a separate job unsentLogs.add(log); } else { - HttpRequest request = this.createHttpRequest(); - System.debug('request.getEndpoint()==' + request.getEndpoint()); - System.debug('request.getMethod()==' + request.getMethod()); - System.debug('request.getBody()==' + request.getBody()); + HttpRequest request = this.createSlackHttpRequest(); NotificationDto notification = new NotificationDto(); notification.text = 'Salesforce Log Alert'; - notification.attachments = new List(); - notification.attachments.add(this.convertLog(log)); + notification.attachments = new List{ this.convertLog(log) }; // 'Short' is a reserved word in Apex, but used in Slack's API, so the conversion happens in JSON String notificationJson = JSON.serialize(notification).replace('"isShort"', '"short"'); @@ -88,7 +86,13 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi } private void flagLogsForSlackNotification() { - LoggingLevel thresholdLoggingLevel = Logger.getLoggingLevel(PARAM_LOGGING_LEVEL_THRESHOLD); + String thresholdLoggingLevelName = this.getParameterAsString(PARAM_THRESHOLD_LOGGING_LEVEL_NAME); + + if (String.isBlank(thresholdLoggingLevelName)) { + return; + } + + LoggingLevel thresholdLoggingLevel = Logger.getLoggingLevel(thresholdLoggingLevelName); for (Log__c log : this.logs) { if (log.MaxLogEntryLoggingLevelOrdinal__c >= thresholdLoggingLevel.ordinal()) { log.SendSlackNotification__c = true; @@ -141,21 +145,22 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi FROM LogEntries__r WHERE LoggingLevelOrdinal__c >= :LoggingLevel.WARN.ordinal() ORDER BY Timestamp__c DESC + LIMIT 1 ) FROM Log__c WHERE Id IN :this.logs AND SendSlackNotification__c = TRUE AND SlackNotificationDate__c = NULL ]; } - private HttpRequest createHttpRequest() { - String authMethod = this.getParameterValue(PARAM_AUTH_METHOD); + private HttpRequest createSlackHttpRequest() { + String authMethod = this.getParameterAsString(PARAM_AUTH_METHOD); System.debug('authMethod==' + authMethod); - String endpoint = this.getParameterValue(PARAM_ENDPOINT); + String endpoint = this.getParameterAsString(PARAM_ENDPOINT); System.debug('endpoint==' + endpoint); - String apiToken = this.getParameterValue(PARAM_API_TOKEN); + String apiToken = this.getParameterAsString(PARAM_API_TOKEN); System.debug('apiToken==' + apiToken); - if (authMethod == AUTH_METHOD_API_TOKEN && String.isNotBlank(apiToken)) { + if (authMethod == SlackAuthMethod.API_TOKEN.name() && String.isNotBlank(apiToken)) { endpoint += apiToken; } @@ -205,7 +210,7 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi FieldDto logEntryField = new FieldDto(); logEntryField.isShort = false; logEntryField.title = 'Last Log Entry Message'; - logEntryField.value = lastLogEntry.LoggingLevel__c + ': `' + lastLogEntry.Message__c + '`'; + logEntryField.value = '`' + lastLogEntry.LoggingLevel__c + ': ' + lastLogEntry.Message__c + '`'; notification.fields.add(logEntryField); String logOwnerType = log.OwnerId.getSObjectType().getDescribe().getName(); @@ -268,7 +273,7 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi if (log.TotalERRORLogEntries__c >= 1) { color = '#FF7373'; // Red } else if (log.TotalWARNLogEntries__c >= 1) { - color = '#FFC873'; // Organge + color = '#FFC873'; // Orange } else { color = '#7CD197'; // Green } diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index b991dabf6..9ceac2cdb 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -109,10 +109,7 @@ public abstract class LoggerSObjectHandler { if (this.handlerConfiguration == null) { // If no config exists in the org, then load some in-memory defaults - this.handlerConfiguration = new LoggerSObjectHandler__mdt( - IsEnabled__c = true, - SObjectType__c = this.getSObjectType().getDescribe().getName() - ); + this.handlerConfiguration = new LoggerSObjectHandler__mdt(IsEnabled__c = true, SObjectType__c = this.getSObjectType().getDescribe().getName()); configurationBySObjectType.put(this.getSObjectType(), this.handlerConfiguration); } diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls index bf968633f..6985d306a 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls @@ -7,8 +7,9 @@ * @group Log Management * @description Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` */ -global abstract class LoggerSObjectHandlerPlugin { - global abstract void execute( +// TODO: convert to `global` once plugin framework is stable/solidified/ready for the managed package +public abstract class LoggerSObjectHandlerPlugin { + public abstract void execute( TriggerOperation triggerOperationType, List triggerNew, Map triggerNewMap, @@ -16,32 +17,54 @@ global abstract class LoggerSObjectHandlerPlugin { Map triggerOldMap ); - global virtual LoggerSObjectHandlerPlugin__mdt getConfiguration() { - // By default, check to see if there is a plugin named after the current Apex class name - // Implementations of LoggerSObjectHandlerPlugin can override this behavior if desired - String currentClassName = String.valueOf(this).substring(0, String.valueOf(this).indexOf(':')); - return LoggerSObjectHandlerPlugin__mdt.getInstance(currentClassName); + protected String getParameterAsString(String parameterDeveloperName) { + return this.getParameter(parameterDeveloperName)?.Value__c; } - // protected LoggerSObjectHandlerPlugin__mdt getConfiguration(String configurationDeveloperName) { - // // To include the child object LoggerSObjectHandlerPluginParameter__mdt, we have to query the object... - // // ...instead of using getAll() + // TODO: uncomment these as a future enhancement + // protected Blob getParameterAsBlob(String parameterDeveloperName) { + // return Blob.valueOf(this.getParameterAsString(parameterDeveloperName)); + // } - // // TODO Consider caching the query results... maybe... - // return [ - // SELECT - // Id, - // MasterLabel, - // DeveloperName, - // (SELECT Id, MasterLabel, DeveloperName, DataType__c, Value__c FROM LoggerSObjectHandlerPluginParameters__r WHERE IsEnabled__c = TRUE) - // FROM LoggerSObjectHandlerPlugin__mdt - // WHERE IsEnabled__c = TRUE AND DeveloperName = :configurationDeveloperName - // ]; + // protected Boolean getParameterAsBoolean(String parameterDeveloperName) { + // return Boolean.valueOf(this.getParameterAsString(parameterDeveloperName)); // } - protected String getParameterValue(String parameterDeveloperName) { - return this.getParameter(parameterDeveloperName)?.Value__c; - } + // protected Date getParameterAsDate(String parameterDeveloperName) { + // return Date.valueOf(this.getParameterAsString(parameterDeveloperName)); + // } + + // protected Datetime getParameterAsDatetime(String parameterDeveloperName) { + // return Datetime.valueOf(this.getParameterAsString(parameterDeveloperName)); + // } + + // protected Decimal getParameterAsDecimal(String parameterDeveloperName) { + // return Decimal.valueOf(this.getParameterAsString(parameterDeveloperName)); + // } + + // protected Double getParameterAsDouble(String parameterDeveloperName) { + // return Double.valueOf(this.getParameterAsString(parameterDeveloperName)); + // } + + // protected Id getParameterAsId(String parameterDeveloperName) { + // return Id.valueOf(this.getParameterAsString(parameterDeveloperName)); + // } + + // protected Integer getParameterAsInteger(String parameterDeveloperName) { + // return Integer.valueOf(this.getParameterAsString(parameterDeveloperName)); + // } + + // protected Long getParameterAsLong(String parameterDeveloperName) { + // return Long.valueOf(this.getParameterAsString(parameterDeveloperName)); + // } + + // protected Object getParameterAsObject(String parameterDeveloperName) { + // return (Object) this.getParameterAsString(parameterDeveloperName); + // } + + // protected SObject getParameterAsSObject(String parameterDeveloperName) { + // return (SObject) JSON.deserialize(this.getParameterAsString(parameterDeveloperName), SObject.class); + // } private LoggerSObjectHandlerPluginParameter__mdt getParameter(String parameterDeveloperName) { LoggerSObjectHandlerPluginParameter__mdt parameter = LoggerSObjectHandlerPluginParameter__mdt.getInstance(parameterDeveloperName); diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml index 95e64184c..149a7114c 100644 --- a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml @@ -14,10 +14,6 @@ Required DeveloperName - - Edit - Description__c - @@ -45,6 +41,10 @@ Edit Value__c + + Edit + Description__c + diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml index 25a24dc2d..ae333834e 100644 --- a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml +++ b/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml @@ -14,10 +14,6 @@ Required DeveloperName - - Edit - Description__c - @@ -54,6 +50,19 @@ + + true + false + false + + + + Edit + Description__c + + + + false true diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml index 38e4449b9..76423568b 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml @@ -3,5 +3,5 @@ Used to store additional key-value pair parameters that can be used by Logger plugins Logger SObject Handler Plugin Parameters - Public + Protected diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml index 8778dbdd2..7c041d4c9 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml @@ -70,11 +70,6 @@ false - - Time - false - - diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Description__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Description__c.field-meta.xml index 3f025aa9d..53ef07be5 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Description__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Description__c.field-meta.xml @@ -1,11 +1,12 @@ Description__c - Used purely for documentation purposes to store any important details about this parameter + Used purely for documentation purposes to store any important details about this plugin false - SubscriberControlled - Used purely for documentation purposes to store any important details about this parameter + DeveloperControlled + Used purely for documentation purposes to store any important details about this plugin - false - TextArea + 131072 + LongTextArea + 3 diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml index 6473c03b9..7259ce4af 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml @@ -1,7 +1,7 @@ - + Used to configure additional Apex classes and Flows that should be executed for all DML statements on Log__c and LogEntry__c Logger SObject Handler Plugins - Public + Protected diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/Description__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/Description__c.field-meta.xml index 7180167bd..163c5c139 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/Description__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/Description__c.field-meta.xml @@ -1,11 +1,12 @@ Description__c - Used purely for documentation purposes to store any important details about this plugin + Used purely for documentation purposes to store any important details about this parameter false - SubscriberControlled - Used purely for documentation purposes to store any important details about this plugin + DeveloperControlled + Used purely for documentation purposes to store any important details about this parameter - false - TextArea + 131072 + LongTextArea + 3 diff --git a/sfdx-project.json b/sfdx-project.json index 03a347eb2..d78ebe6ac 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -40,4 +40,4 @@ "Nebula Logger - Unlocked Package@4.5.0-0": "04t5Y0000027FKqQAM", "Nebula Logger - Slack Plugin": "0Ho5Y000000TNKoSAO" } -} \ No newline at end of file +} From cd8aadaf69cbb029d772afd9a41fcf496e8151e8 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 21:22:49 -0700 Subject: [PATCH 45/82] Added more plugin details in README.md --- README.md | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ff753a390..a487a817b 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,8 @@ You can choose to install the unlocked package, you can deploy the metadata from Future Releases - Faster release cycle: new patch versions are released (e.g., `v4.4.x`) for new enhancements & bugfixes that are merged to the `main` branch in GitHub - Slower release cycle: new minor versions are only released (e.g., `v4.x`) once new enhancements & bugfixes have been tested and code is stabilized + Faster release cycle: new patch versions are released (e.g., v4.4.x) for new enhancements & bugfixes that are merged to the main branch in GitHub + Slower release cycle: new minor versions are only released (e.g., v4.x) once new enhancements & bugfixes have been tested and code is stabilized Faster release cycle: new enhancements & bugfixes will be immediately available in GitHub @@ -82,6 +82,12 @@ You can choose to install the unlocked package, you can deploy the metadata from This functionality is not currently available in the managed package Provide List<String> topics in Apex or Flow to dynamically assign Salesforce Topics to Log__c and LogEntry__c records + + Logger Plugin Framework + Leverage Apex or Flow to build your own "plugins" for Logger - to add your own automation to the Log__c or LogEntry__c objects. The logger system will then automatically run your plugins after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on). + This functionality is not currently available in the managed package + Leverage Apex or Flow to build your own "plugins" for Logger - to add your own automation to the Log__c or LogEntry__c objects. The logger system will then automatically run your plugins after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on). + @@ -339,7 +345,11 @@ The class `LogMessage` provides the ability to generate string messages on deman For more details, check out the `LogMessage` class [documentation](https://jongpie.github.io/NebulaLogger/logger-engine/LogMessage). -### Adding Custom Plugins for Log\_\_c and LogEntry\_\_c +--- + +## New Beta Feature: Adding Custom Plugins for Log\_\_c and LogEntry\_\_c + +Note: the logger plugin framework is currently not available in the managed package. Once this feature has been stabilized, it'll be added to the managed package version as well. If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you can leverage Apex or Flow to define "plugins" - the logger system will then automatically run the plugins after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on) @@ -374,6 +384,17 @@ Once you've created your Apex or Flow plugin(s), you will also need to configure ![Logger Handler Configuration](./content/logger-handler-configuration.png) +### New Beta Plugin: Slack Integration + +The optional [Slack plugin](./nebula-logger-plugins/Slack/) leverages the Nebula Logger plugin framework to automatically send Slack notifications for logs that meet a certain (configurable) logging level. The plugin also serves as a functioning example of how to build your own plugin for Nebula Logger, such as how to: + +- Use Apex to apply custom logic to `Log__c` and `LogEntry__c` records +- Add custom fields and list views to Logger's objects +- Extend permission sets to include field-level security for your custom fields +- Leverage the new `LoggerSObjectHandlerPluginParameter__mdt` CMDT object to store configuration for your plugin + +Check out the [Slack plugin](./nebula-logger-plugins/Slack/) for more details on how to install & customize the plugin + ## Managing Logs To help development and support teams better manage logs (and any underlying code or config issues), some fields on `Log__c` are provided to track the owner, priority and status of a log. These fields are optional, but are helpful in critical environments (production, QA sandboxes, UAT sandboxes, etc.) for monitoring ongoing user activities. From 37344cba6ad28ac20d5816d3d7e16273ecb3eaee Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 21:27:42 -0700 Subject: [PATCH 46/82] More formatting changes in README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a487a817b..c7c17f8bc 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ After deploying Nebula Logger to your org, there are a few additional configurat --- -## Logger for Apex: Quick Start +### Logger for Apex: Quick Start For Apex developers, the `Logger` class has several methods that can be used to add entries with different logging levels. Each logging level's method has several overloads to support multiple parameters. @@ -135,7 +135,7 @@ This results in 1 `Log__c` record with several related `LogEntry__c` records. --- -## Logger for Flow & Process Builder: Quick Start +### Logger for Flow & Process Builder: Quick Start Within Flow & Process Builder, you can select 1 of the several Logging actions @@ -151,7 +151,7 @@ This results in a `Log__c` record with related `LogEntry__c` records. --- -## All Together: Apex & Flow in One Log +### All Together: Apex & Flow in One Log After incorporating Logger into your Flows & Apex code (including controllers, trigger framework, etc.), you'll have a unified transaction log of all your declarative & custom code automations. @@ -351,7 +351,7 @@ For more details, check out the `LogMessage` class [documentation](https://jongp Note: the logger plugin framework is currently not available in the managed package. Once this feature has been stabilized, it'll be added to the managed package version as well. -If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you can leverage Apex or Flow to define "plugins" - the logger system will then automatically run the plugins after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on) +If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you can leverage Apex or Flow to define "plugins" - the logger system will then automatically run the plugins after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on). - Flow plugins: your Flow should be built with these input parameters: 1. `triggerOperationType` - The name of the current trigger operation (such as BEFORE_INSERT, BEFORE_UPDATE, etc.) From e1a5592889d302b69d8cb6bdc97db7a4033e2680 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 21:49:31 -0700 Subject: [PATCH 47/82] Fixed Slack API token usage --- nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index 03325b1be..dd32bc787 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -160,15 +160,15 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi String apiToken = this.getParameterAsString(PARAM_API_TOKEN); System.debug('apiToken==' + apiToken); - if (authMethod == SlackAuthMethod.API_TOKEN.name() && String.isNotBlank(apiToken)) { - endpoint += apiToken; - } - HttpRequest request = new HttpRequest(); request.setEndpoint(endpoint); request.setMethod('POST'); request.setHeader('Content-Type', 'application/json'); + if (authMethod == SlackAuthMethod.API_TOKEN.name() && String.isNotBlank(apiToken)) { + request.setHeader('token', apiToken); + } + return request; } From e59df7102d88e5ce4c6182d4ed51c50b15215947 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 21:50:07 -0700 Subject: [PATCH 48/82] Added screenshot of Slack notification examples --- content/slack-plugin-notification.png | Bin 0 -> 115883 bytes nebula-logger-plugins/Slack/README.md | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 content/slack-plugin-notification.png diff --git a/content/slack-plugin-notification.png b/content/slack-plugin-notification.png new file mode 100644 index 0000000000000000000000000000000000000000..ed78e33f04e5b3123d4bfcb17b2a1cb7ffcd98fe GIT binary patch literal 115883 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 z�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

    $E%~#*N<3v)I1_hoo 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 literal 0 HcmV?d00001 diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index 346ae6498..13b9bc0b7 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -4,6 +4,8 @@ Adds a Slack integration for Nebula Logger. Any logs with 1+ ERROR or WARN log e [![Install Unlocked Package](./../../content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=TODO-add-package-ID) +![Slack plugin: notification](./../../content/slack-plugin-notification.png) + --- ## Installation Steps From c36236a9aca5ae609be79108d3732f78790b6ce0 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 21:51:17 -0700 Subject: [PATCH 49/82] Removed Slack plugin install btn for now --- nebula-logger-plugins/Slack/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index 13b9bc0b7..2ad99456e 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -2,8 +2,6 @@ Adds a Slack integration for Nebula Logger. Any logs with 1+ ERROR or WARN log entries will automatically be posted to your Slack channel. -[![Install Unlocked Package](./../../content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=TODO-add-package-ID) - ![Slack plugin: notification](./../../content/slack-plugin-notification.png) --- From 47799f4ad6743f7e69fbbda192b0ce6d302f68b8 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 21:58:42 -0700 Subject: [PATCH 50/82] Added "What's Included" section in Slack's README.me --- nebula-logger-plugins/Slack/README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index 2ad99456e..2e27a0480 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -1,11 +1,21 @@ # Slack plugin for Nebula Logger -Adds a Slack integration for Nebula Logger. Any logs with 1+ ERROR or WARN log entries will automatically be posted to your Slack channel. +Adds a Slack integration for Nebula Logger. Any logs with log entries that meet a certain (configurable) logging level will automatically be posted to your Slack channel. ![Slack plugin: notification](./../../content/slack-plugin-notification.png) --- +## What's Included + +This plugin includes some add-on metadata for Logger to support the Slack integration +1. Apex class `SlackLoggerPlugin` and corresponding tests in `SlackLoggerPlugin_Tests` +2. Plugin configuration details stored in Logger's CMDT objects `LoggerSObjectHandlerPlugin__mdt` and `LoggerSObjectHandlerPluginParameter__mdt` +3. Custom fields `Log__c.SendSlackNotification__c` and `Log__c.SlackNotificationDate__c` +4. Field-level security (FLS) updates for the permission sets `LoggerAdmin` and `LoggerLogViewer` to provide access to the custom Slack fields +5. Custom list views for the `Log__c` and `LoggerSObjectHandlerPluginParameter__mdt` objects +6. Remote site setting for Slack's API + ## Installation Steps 1. Ensure that you have the unlocked package version of Nebula Logger installed in your org From a057b3f37667b488108c5c17e158ede8bc65f7c3 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 21:59:49 -0700 Subject: [PATCH 51/82] Formatting cleanup in Slack README.md --- nebula-logger-plugins/Slack/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index 2e27a0480..0d096bad2 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -9,6 +9,7 @@ Adds a Slack integration for Nebula Logger. Any logs with log entries that meet ## What's Included This plugin includes some add-on metadata for Logger to support the Slack integration + 1. Apex class `SlackLoggerPlugin` and corresponding tests in `SlackLoggerPlugin_Tests` 2. Plugin configuration details stored in Logger's CMDT objects `LoggerSObjectHandlerPlugin__mdt` and `LoggerSObjectHandlerPluginParameter__mdt` 3. Custom fields `Log__c.SendSlackNotification__c` and `Log__c.SlackNotificationDate__c` @@ -16,6 +17,8 @@ This plugin includes some add-on metadata for Logger to support the Slack integr 5. Custom list views for the `Log__c` and `LoggerSObjectHandlerPluginParameter__mdt` objects 6. Remote site setting for Slack's API +--- + ## Installation Steps 1. Ensure that you have the unlocked package version of Nebula Logger installed in your org From 2d66eb358d6fb97d2dc9b4d1bfe3f57cf1246718 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 22:01:46 -0700 Subject: [PATCH 52/82] Added detail that notifications are created via a queueable job --- nebula-logger-plugins/Slack/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index 0d096bad2..881acbf34 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -1,6 +1,6 @@ # Slack plugin for Nebula Logger -Adds a Slack integration for Nebula Logger. Any logs with log entries that meet a certain (configurable) logging level will automatically be posted to your Slack channel. +Adds a Slack integration for Nebula Logger. Any logs with log entries that meet a certain (configurable) logging level will automatically be posted to your Slack channel via an asynchronous `Queueable` job. ![Slack plugin: notification](./../../content/slack-plugin-notification.png) From 1e408bab6f06e8cdceb23bb303416c265616c129 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 22:04:25 -0700 Subject: [PATCH 53/82] Changed plugin header title in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c7c17f8bc..5a84470dd 100644 --- a/README.md +++ b/README.md @@ -347,7 +347,7 @@ For more details, check out the `LogMessage` class [documentation](https://jongp --- -## New Beta Feature: Adding Custom Plugins for Log\_\_c and LogEntry\_\_c +## New Beta Feature: Custom Plugin Framework for Log\_\_c and LogEntry\_\_c objects Note: the logger plugin framework is currently not available in the managed package. Once this feature has been stabilized, it'll be added to the managed package version as well. From ed31f18587a80e6ac3ebeba24476ad7dbf692d81 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 22:11:28 -0700 Subject: [PATCH 54/82] More README header updates --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5a84470dd..f256c923a 100644 --- a/README.md +++ b/README.md @@ -347,7 +347,7 @@ For more details, check out the `LogMessage` class [documentation](https://jongp --- -## New Beta Feature: Custom Plugin Framework for Log\_\_c and LogEntry\_\_c objects +## Beta Feature: Custom Plugin Framework for Log\_\_c and LogEntry\_\_c objects Note: the logger plugin framework is currently not available in the managed package. Once this feature has been stabilized, it'll be added to the managed package version as well. @@ -384,7 +384,7 @@ Once you've created your Apex or Flow plugin(s), you will also need to configure ![Logger Handler Configuration](./content/logger-handler-configuration.png) -### New Beta Plugin: Slack Integration +### Beta Plugin: Slack Integration The optional [Slack plugin](./nebula-logger-plugins/Slack/) leverages the Nebula Logger plugin framework to automatically send Slack notifications for logs that meet a certain (configurable) logging level. The plugin also serves as a functioning example of how to build your own plugin for Nebula Logger, such as how to: From 45cd23057c694a8149c77ebfdafb8163cf479abb Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 22:20:22 -0700 Subject: [PATCH 55/82] Corrected ApexDocs for LoggerSObjectHandlerPlugin --- docs/index.md | 2 +- docs/log-management/LoggerSObjectHandlerPlugin.md | 4 ++-- .../log-management/classes/LoggerSObjectHandlerPlugin.cls | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/index.md b/docs/index.md index a1713b9b8..bd5ed4353 100644 --- a/docs/index.md +++ b/docs/index.md @@ -62,7 +62,7 @@ Abstract class used by trigger handlers for shared logic ### [LoggerSObjectHandlerPlugin](log-management/LoggerSObjectHandlerPlugin) -Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` +Abstract class used to define custom plugins to run when DML statements occur on `Log__c` or `LogEntry__c` ### [RelatedLogEntriesController](log-management/RelatedLogEntriesController) diff --git a/docs/log-management/LoggerSObjectHandlerPlugin.md b/docs/log-management/LoggerSObjectHandlerPlugin.md index 833306673..400f748af 100644 --- a/docs/log-management/LoggerSObjectHandlerPlugin.md +++ b/docs/log-management/LoggerSObjectHandlerPlugin.md @@ -2,9 +2,9 @@ layout: default --- -## LoggerSObjectHandlerPlugin interface +## LoggerSObjectHandlerPlugin class -Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` +Abstract class used to define custom plugins to run when DML statements occur on `Log__c` or `LogEntry__c` --- diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls index 6985d306a..7b69deeb5 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls @@ -5,7 +5,7 @@ /** * @group Log Management - * @description Interface used to define custom logic to run when DML statements occur on `Log__c` or `LogEntry__c` + * @description Abstract class used to define custom plugins to run when DML statements occur on `Log__c` or `LogEntry__c` */ // TODO: convert to `global` once plugin framework is stable/solidified/ready for the managed package public abstract class LoggerSObjectHandlerPlugin { From b09058966bed451f180c22e42e6c2a58a496cb72 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 23:22:12 -0700 Subject: [PATCH 56/82] More ApexDocs updates --- docs/index.md | 2 +- docs/log-management/LoggerSObjectHandler.md | 4 + .../LoggerSObjectHandlerPlugin.md | 14 +- .../Slack/classes/SlackLoggerPlugin.cls | 8 +- .../classes/LogEntryEventHandler.cls | 2 +- .../classes/LogEntryHandler.cls | 2 +- .../log-management/classes/LogHandler.cls | 2 +- .../classes/LoggerSObjectHandler.cls | 9 ++ .../classes/LoggerSObjectHandlerPlugin.cls | 141 +++++++++++++----- .../fields/DataType__c.field-meta.xml | 5 - 10 files changed, 136 insertions(+), 53 deletions(-) diff --git a/docs/index.md b/docs/index.md index bd5ed4353..eb5342026 100644 --- a/docs/index.md +++ b/docs/index.md @@ -62,7 +62,7 @@ Abstract class used by trigger handlers for shared logic ### [LoggerSObjectHandlerPlugin](log-management/LoggerSObjectHandlerPlugin) -Abstract class used to define custom plugins to run when DML statements occur on `Log__c` or `LogEntry__c` +Abstract class used to define custom plugins to execute when DML statements occur on `Log__c` or `LogEntry__c` ### [RelatedLogEntriesController](log-management/RelatedLogEntriesController) diff --git a/docs/log-management/LoggerSObjectHandler.md b/docs/log-management/LoggerSObjectHandler.md index 801400edd..b606199ff 100644 --- a/docs/log-management/LoggerSObjectHandler.md +++ b/docs/log-management/LoggerSObjectHandler.md @@ -16,6 +16,10 @@ Abstract class used by trigger handlers for shared logic ### Methods +#### `execute()` → `void` + +Runs the handler class's logic + #### `getSObjectType()` → `SObjectType` Returns the SObject Type that the handler is responsible for processing diff --git a/docs/log-management/LoggerSObjectHandlerPlugin.md b/docs/log-management/LoggerSObjectHandlerPlugin.md index 400f748af..0b526dc47 100644 --- a/docs/log-management/LoggerSObjectHandlerPlugin.md +++ b/docs/log-management/LoggerSObjectHandlerPlugin.md @@ -4,7 +4,7 @@ layout: default ## LoggerSObjectHandlerPlugin class -Abstract class used to define custom plugins to run when DML statements occur on `Log__c` or `LogEntry__c` +Abstract class used to define custom plugins to execute when DML statements occur on `Log__c` or `LogEntry__c` --- @@ -12,4 +12,16 @@ Abstract class used to define custom plugins to run when DML statements occur on #### `execute(TriggerOperation triggerOperationType,List triggerNew,Map triggerNewMap,List triggerOld,Map triggerOldMap)` → `void` +execute description + +##### Parameters + +| Param | Description | +| ---------------------- | ------------------------------------------------------------------------------------------ | +| `triggerOperationType` | The enum instance of `Trigger.operationType` at the time that the handler class is created | +| `triggerNew` | The value `Trigger.new` at the time that the handler class is created | +| `triggerNewMap` | The value `Trigger.newMap` at the time that the handler class is created | +| `triggerOld` | The value `Trigger.old` at the time that the handler class is created | +| `triggerOldMap` | The value `Trigger.oldMap` at the time that the handler class is created | + --- diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index dd32bc787..54ef65a6f 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -86,7 +86,7 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi } private void flagLogsForSlackNotification() { - String thresholdLoggingLevelName = this.getParameterAsString(PARAM_THRESHOLD_LOGGING_LEVEL_NAME); + String thresholdLoggingLevelName = this.getStringParameter(PARAM_THRESHOLD_LOGGING_LEVEL_NAME); if (String.isBlank(thresholdLoggingLevelName)) { return; @@ -153,11 +153,11 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi } private HttpRequest createSlackHttpRequest() { - String authMethod = this.getParameterAsString(PARAM_AUTH_METHOD); + String authMethod = this.getStringParameter(PARAM_AUTH_METHOD); System.debug('authMethod==' + authMethod); - String endpoint = this.getParameterAsString(PARAM_ENDPOINT); + String endpoint = this.getStringParameter(PARAM_ENDPOINT); System.debug('endpoint==' + endpoint); - String apiToken = this.getParameterAsString(PARAM_API_TOKEN); + String apiToken = this.getStringParameter(PARAM_API_TOKEN); System.debug('apiToken==' + apiToken); HttpRequest request = new HttpRequest(); diff --git a/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls b/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls index 01e988988..3055e73b2 100644 --- a/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls @@ -44,7 +44,7 @@ public without sharing class LogEntryEventHandler extends LoggerSObjectHandler { /** * @description Runs the trigger handler's logic for the `LogEntryEvent__e` platform event object */ - public void execute() { + public override void execute() { if (this.isEnabled() == false) { return; } diff --git a/nebula-logger/main/log-management/classes/LogEntryHandler.cls b/nebula-logger/main/log-management/classes/LogEntryHandler.cls index c667ff1e9..739986c03 100644 --- a/nebula-logger/main/log-management/classes/LogEntryHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryHandler.cls @@ -30,7 +30,7 @@ public without sharing class LogEntryHandler extends LoggerSObjectHandler { /** * @description Runs the trigger handler's logic for the `LogEntry__c` custom object */ - public void execute() { + public override void execute() { if (this.isEnabled() == false) { return; } diff --git a/nebula-logger/main/log-management/classes/LogHandler.cls b/nebula-logger/main/log-management/classes/LogHandler.cls index 2bfa1fbce..99ea01ef7 100644 --- a/nebula-logger/main/log-management/classes/LogHandler.cls +++ b/nebula-logger/main/log-management/classes/LogHandler.cls @@ -53,7 +53,7 @@ public without sharing class LogHandler extends LoggerSObjectHandler { /** * @description Runs the trigger handler's logic for the `Log__c` custom object */ - public void execute() { + public override void execute() { if (this.isEnabled() == false) { return; } diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index 9ceac2cdb..cabee0835 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -82,6 +82,15 @@ public abstract class LoggerSObjectHandler { */ public abstract SObjectType getSObjectType(); + /** + * @description Runs the handler class's logic + */ + public abstract void execute(); + + /** + * @description Indicates if the current SObject Handler is enabled, based on `LoggerSObjectHandler__mdt.IsEnabled__c` + * @return The `Boolean` value (`true` == enabled, `false` == disabled) + */ protected Boolean isEnabled() { return this.handlerConfiguration.IsEnabled__c; } diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls index 7b69deeb5..7d7afd240 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls @@ -5,10 +5,18 @@ /** * @group Log Management - * @description Abstract class used to define custom plugins to run when DML statements occur on `Log__c` or `LogEntry__c` + * @description Abstract class used to define custom plugins to execute when DML statements occur on `Log__c` or `LogEntry__c` */ -// TODO: convert to `global` once plugin framework is stable/solidified/ready for the managed package +// TODO: convert to `global` once plugin framework is stable/solidified/ready for the managed package (if possible) public abstract class LoggerSObjectHandlerPlugin { + /** + * @description execute description + * @param triggerOperationType The enum instance of `Trigger.operationType` at the time that the handler class is created + * @param triggerNew The value `Trigger.new` at the time that the handler class is created + * @param triggerNewMap The value `Trigger.newMap` at the time that the handler class is created + * @param triggerOld The value `Trigger.old` at the time that the handler class is created + * @param triggerOldMap The value `Trigger.oldMap` at the time that the handler class is created + */ public abstract void execute( TriggerOperation triggerOperationType, List triggerNew, @@ -17,56 +25,111 @@ public abstract class LoggerSObjectHandlerPlugin { Map triggerOldMap ); - protected String getParameterAsString(String parameterDeveloperName) { + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `String` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `String` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + */ + protected String getStringParameter(String parameterDeveloperName) { return this.getParameter(parameterDeveloperName)?.Value__c; } - // TODO: uncomment these as a future enhancement - // protected Blob getParameterAsBlob(String parameterDeveloperName) { - // return Blob.valueOf(this.getParameterAsString(parameterDeveloperName)); - // } - - // protected Boolean getParameterAsBoolean(String parameterDeveloperName) { - // return Boolean.valueOf(this.getParameterAsString(parameterDeveloperName)); - // } + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Boolean` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `Boolean` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + */ + protected Boolean getBooleanParameter(String parameterDeveloperName) { + return Boolean.valueOf(this.getStringParameter(parameterDeveloperName)); + } - // protected Date getParameterAsDate(String parameterDeveloperName) { - // return Date.valueOf(this.getParameterAsString(parameterDeveloperName)); - // } + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Date` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `Date` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + */ + protected Date getDateParameter(String parameterDeveloperName) { + return Date.valueOf(this.getStringParameter(parameterDeveloperName)); + } - // protected Datetime getParameterAsDatetime(String parameterDeveloperName) { - // return Datetime.valueOf(this.getParameterAsString(parameterDeveloperName)); - // } + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Datetime` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `Datetime` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + */ + protected Datetime getDatetimeParameter(String parameterDeveloperName) { + return Datetime.valueOf(this.getStringParameter(parameterDeveloperName)); + } - // protected Decimal getParameterAsDecimal(String parameterDeveloperName) { - // return Decimal.valueOf(this.getParameterAsString(parameterDeveloperName)); - // } + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Decimal` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `Decimal` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + */ + protected Decimal getDecimalParameter(String parameterDeveloperName) { + return Decimal.valueOf(this.getStringParameter(parameterDeveloperName)); + } - // protected Double getParameterAsDouble(String parameterDeveloperName) { - // return Double.valueOf(this.getParameterAsString(parameterDeveloperName)); - // } + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Double` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `Double` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + */ + protected Double getDoubleParameter(String parameterDeveloperName) { + return Double.valueOf(this.getStringParameter(parameterDeveloperName)); + } - // protected Id getParameterAsId(String parameterDeveloperName) { - // return Id.valueOf(this.getParameterAsString(parameterDeveloperName)); - // } + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Id` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `Id` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + */ + protected Id getIdParameter(String parameterDeveloperName) { + return Id.valueOf(this.getStringParameter(parameterDeveloperName)); + } - // protected Integer getParameterAsInteger(String parameterDeveloperName) { - // return Integer.valueOf(this.getParameterAsString(parameterDeveloperName)); - // } + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Integer` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `Integer` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + */ + protected Integer getIntegerParameter(String parameterDeveloperName) { + return Integer.valueOf(this.getStringParameter(parameterDeveloperName)); + } - // protected Long getParameterAsLong(String parameterDeveloperName) { - // return Long.valueOf(this.getParameterAsString(parameterDeveloperName)); - // } + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Long` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `Long` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + */ + protected Long getLongParameter(String parameterDeveloperName) { + return Long.valueOf(this.getStringParameter(parameterDeveloperName)); + } - // protected Object getParameterAsObject(String parameterDeveloperName) { - // return (Object) this.getParameterAsString(parameterDeveloperName); - // } + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as an `Object` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `Object` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + */ + protected Object getObjectParameter(String parameterDeveloperName) { + return (Object) this.getStringParameter(parameterDeveloperName); + } - // protected SObject getParameterAsSObject(String parameterDeveloperName) { - // return (SObject) JSON.deserialize(this.getParameterAsString(parameterDeveloperName), SObject.class); - // } + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `SObject` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `SObject` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + */ + protected SObject getSObjectParameter(String parameterDeveloperName) { + return (SObject) JSON.deserialize(this.getStringParameter(parameterDeveloperName), SObject.class); + } - private LoggerSObjectHandlerPluginParameter__mdt getParameter(String parameterDeveloperName) { + /** + * @description Returns the matching instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + */ + protected LoggerSObjectHandlerPluginParameter__mdt getParameter(String parameterDeveloperName) { LoggerSObjectHandlerPluginParameter__mdt parameter = LoggerSObjectHandlerPluginParameter__mdt.getInstance(parameterDeveloperName); if (parameter == null || parameter.IsEnabled__c == false) { diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml index 7c041d4c9..e9e58f749 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml @@ -10,11 +10,6 @@ true false - - Blob - true - - Boolean false From a78b8d8e575aaaada281323fa8212fc2ab8483bd Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 12 Jun 2021 23:55:11 -0700 Subject: [PATCH 57/82] Added plugin-framework folder --- docs/index.md | 10 ++++--- .../LoggerSObjectHandlerPlugin.md | 27 +++++++++++++++++++ .../Slack/classes/SlackLoggerPlugin.cls | 4 +++ .../classes/LoggerSObjectHandlerPlugin.cls | 2 +- .../LoggerSObjectHandlerPlugin.cls-meta.xml | 0 ...er Plugin Parameter Layout.layout-meta.xml | 0 ...ject Handler Plugin Layout.layout-meta.xml | 0 ...andlerPluginParameter__mdt.object-meta.xml | 0 .../fields/DataType__c.field-meta.xml | 0 .../fields/Description__c.field-meta.xml | 0 .../fields/IsEnabled__c.field-meta.xml | 0 .../SObjectHandlerPlugin__c.field-meta.xml | 0 .../fields/Value__c.field-meta.xml | 0 .../listViews/All.listView-meta.xml | 0 .../listViews/AllDisabled.listView-meta.xml | 0 .../listViews/AllEnabled.listView-meta.xml | 0 ...rSObjectHandlerPlugin__mdt.object-meta.xml | 0 .../fields/Description__c.field-meta.xml | 0 .../fields/ExecutionOrder__c.field-meta.xml | 0 .../fields/IsEnabled__c.field-meta.xml | 0 .../fields/PluginApiName__c.field-meta.xml | 0 .../fields/PluginType__c.field-meta.xml | 0 .../fields/SObjectHandler__c.field-meta.xml | 0 .../listViews/All.listView-meta.xml | 0 .../listViews/AllDisabled.listView-meta.xml | 0 .../listViews/AllEnabled.listView-meta.xml | 0 ..._are_not_supported.validationRule-meta.xml | 0 scripts/generate-docs.ps1 | 4 ++- 28 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 docs/plugin-framework/LoggerSObjectHandlerPlugin.md rename nebula-logger/main/{log-management => plugin-framework}/classes/LoggerSObjectHandlerPlugin.cls (99%) rename nebula-logger/main/{log-management => plugin-framework}/classes/LoggerSObjectHandlerPlugin.cls-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Description__c.field-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/IsEnabled__c.field-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/SObjectHandlerPlugin__c.field-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Value__c.field-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllDisabled.listView-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllEnabled.listView-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPlugin__mdt/fields/Description__c.field-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPlugin__mdt/fields/ExecutionOrder__c.field-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPlugin__mdt/fields/IsEnabled__c.field-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPlugin__mdt/fields/SObjectHandler__c.field-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPlugin__mdt/listViews/All.listView-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllDisabled.listView-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllEnabled.listView-meta.xml (100%) rename nebula-logger/main/{log-management => plugin-framework}/objects/LoggerSObjectHandlerPlugin__mdt/validationRules/Plugins_are_not_supported.validationRule-meta.xml (100%) diff --git a/docs/index.md b/docs/index.md index eb5342026..89134c256 100644 --- a/docs/index.md +++ b/docs/index.md @@ -60,10 +60,12 @@ Manages mass deleting `Log__c` records that have been selected by a user on a `L Abstract class used by trigger handlers for shared logic -### [LoggerSObjectHandlerPlugin](log-management/LoggerSObjectHandlerPlugin) - -Abstract class used to define custom plugins to execute when DML statements occur on `Log__c` or `LogEntry__c` - ### [RelatedLogEntriesController](log-management/RelatedLogEntriesController) Controller class for the component RelatedLogEntries + +## Plugin Framework + +### [LoggerSObjectHandlerPlugin](plugin-framework/LoggerSObjectHandlerPlugin) + +Abstract class used to define custom plugins to execute when DML statements occur on `Log__c` or `LogEntry__c` diff --git a/docs/plugin-framework/LoggerSObjectHandlerPlugin.md b/docs/plugin-framework/LoggerSObjectHandlerPlugin.md new file mode 100644 index 000000000..0b526dc47 --- /dev/null +++ b/docs/plugin-framework/LoggerSObjectHandlerPlugin.md @@ -0,0 +1,27 @@ +--- +layout: default +--- + +## LoggerSObjectHandlerPlugin class + +Abstract class used to define custom plugins to execute when DML statements occur on `Log__c` or `LogEntry__c` + +--- + +### Methods + +#### `execute(TriggerOperation triggerOperationType,List triggerNew,Map triggerNewMap,List triggerOld,Map triggerOldMap)` → `void` + +execute description + +##### Parameters + +| Param | Description | +| ---------------------- | ------------------------------------------------------------------------------------------ | +| `triggerOperationType` | The enum instance of `Trigger.operationType` at the time that the handler class is created | +| `triggerNew` | The value `Trigger.new` at the time that the handler class is created | +| `triggerNewMap` | The value `Trigger.newMap` at the time that the handler class is created | +| `triggerOld` | The value `Trigger.old` at the time that the handler class is created | +| `triggerOldMap` | The value `Trigger.oldMap` at the time that the handler class is created | + +--- diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index 54ef65a6f..01c67fbe0 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -3,6 +3,10 @@ // See LICENSE file or go to https://github.com/jongpie/NebulaLogger for full license details. // //------------------------------------------------------------------------------------------------// +/** + * @group Plugins + * @description Optional plugin that integrates with Slack to send alerts for important logs + */ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugin implements Queueable, Database.AllowsCallouts { // Constants used for loading configuration & parameters from custom metadata type objects private static final String PARAM_API_TOKEN = 'SlackApiToken'; diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls b/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls similarity index 99% rename from nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls rename to nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls index 7d7afd240..893f5abe1 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls +++ b/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls @@ -4,7 +4,7 @@ //------------------------------------------------------------------------------------------------// /** - * @group Log Management + * @group Plugin Framework * @description Abstract class used to define custom plugins to execute when DML statements occur on `Log__c` or `LogEntry__c` */ // TODO: convert to `global` once plugin framework is stable/solidified/ready for the managed package (if possible) diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls-meta.xml b/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls-meta.xml similarity index 100% rename from nebula-logger/main/log-management/classes/LoggerSObjectHandlerPlugin.cls-meta.xml rename to nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls-meta.xml diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml b/nebula-logger/main/plugin-framework/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml similarity index 100% rename from nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml rename to nebula-logger/main/plugin-framework/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml diff --git a/nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml b/nebula-logger/main/plugin-framework/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml similarity index 100% rename from nebula-logger/main/log-management/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml rename to nebula-logger/main/plugin-framework/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Description__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Description__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Description__c.field-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Description__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/IsEnabled__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/IsEnabled__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/IsEnabled__c.field-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/IsEnabled__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/SObjectHandlerPlugin__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/SObjectHandlerPlugin__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/SObjectHandlerPlugin__c.field-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/SObjectHandlerPlugin__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Value__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Value__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Value__c.field-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Value__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllDisabled.listView-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllDisabled.listView-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllDisabled.listView-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllDisabled.listView-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllEnabled.listView-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllEnabled.listView-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllEnabled.listView-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllEnabled.listView-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/Description__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/Description__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/Description__c.field-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/Description__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/ExecutionOrder__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/ExecutionOrder__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/ExecutionOrder__c.field-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/ExecutionOrder__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/IsEnabled__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/IsEnabled__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/IsEnabled__c.field-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/IsEnabled__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/SObjectHandler__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/SObjectHandler__c.field-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/fields/SObjectHandler__c.field-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/SObjectHandler__c.field-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/listViews/All.listView-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/All.listView-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/listViews/All.listView-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllDisabled.listView-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllDisabled.listView-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllDisabled.listView-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllDisabled.listView-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllEnabled.listView-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllEnabled.listView-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllEnabled.listView-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/listViews/AllEnabled.listView-meta.xml diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/validationRules/Plugins_are_not_supported.validationRule-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/validationRules/Plugins_are_not_supported.validationRule-meta.xml similarity index 100% rename from nebula-logger/main/log-management/objects/LoggerSObjectHandlerPlugin__mdt/validationRules/Plugins_are_not_supported.validationRule-meta.xml rename to nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/validationRules/Plugins_are_not_supported.validationRule-meta.xml diff --git a/scripts/generate-docs.ps1 b/scripts/generate-docs.ps1 index 4b7d88c58..0af7fb704 100644 --- a/scripts/generate-docs.ps1 +++ b/scripts/generate-docs.ps1 @@ -1,5 +1,5 @@ # This script is used to generate the markdown files used by Github pages -npx apexdocs-generate --configPath config/apexdocs.json --scope global public --sourceDir nebula-logger/main --targetDir docs +npx apexdocs-generate --configPath config/apexdocs.json --scope global public --sourceDir nebula-logger/ --targetDir docs # Make a few adjustments to the generated markdown files so that they work correctly in Github Pages $indexPageFile = "docs/index.md" @@ -7,6 +7,7 @@ Write-Output "Processing file: $indexPageFile" (Get-Content -path $indexPageFile -Raw) -replace ".md","" | Set-Content -Path $indexPageFile -NoNewline (Get-Content -path $indexPageFile -Raw) -replace "/Logger-Engine/","logger-engine/" | Set-Content -Path $indexPageFile -NoNewline (Get-Content -path $indexPageFile -Raw) -replace "/Log-Management/","log-management/" | Set-Content -Path $indexPageFile -NoNewline +(Get-Content -path $indexPageFile -Raw) -replace "/Plugin-Framework/","plugin-framework/" | Set-Content -Path $indexPageFile -NoNewline $docsSubdirectories = "docs/*/*.*" foreach($file in Get-ChildItem $docsSubdirectories) { @@ -14,6 +15,7 @@ foreach($file in Get-ChildItem $docsSubdirectories) { (Get-Content -path $file -Raw) -replace ".md","" | Set-Content -Path $file -NoNewline (Get-Content -path $file -Raw) -replace "/Logger-Engine/","" | Set-Content -Path $file -NoNewline (Get-Content -path $file -Raw) -replace "/Log-Management/","" | Set-Content -Path $file -NoNewline + (Get-Content -path $file -Raw) -replace "/Plugin-Framework/","" | Set-Content -Path $file -NoNewline } prettier ./docs --write From 0d004580cee4d8b3e5c3d788cf40580b035c25b3 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 13 Jun 2021 11:13:48 -0700 Subject: [PATCH 58/82] Lots o' field descriptions, help text & docs updates --- README.md | 6 ++--- docs/index.md | 2 +- .../LoggerSObjectHandlerPlugin.md | 27 ------------------- .../LoggerSObjectHandlerPlugin.md | 4 +-- .../classes/LoggerSObjectHandler.cls | 6 ++--- .../LoggerSObjectHandler__mdt.object-meta.xml | 4 +-- .../classes/LoggerSObjectHandlerPlugin.cls | 12 ++++++--- ...andlerPluginParameter__mdt.object-meta.xml | 4 +-- .../fields/DataType__c.field-meta.xml | 16 ++++++++++- .../fields/IsEnabled__c.field-meta.xml | 2 ++ .../SObjectHandlerPlugin__c.field-meta.xml | 6 +++-- .../fields/Value__c.field-meta.xml | 6 +++++ ...rSObjectHandlerPlugin__mdt.object-meta.xml | 6 ++--- .../fields/ExecutionOrder__c.field-meta.xml | 4 ++- .../fields/IsEnabled__c.field-meta.xml | 4 ++- .../fields/PluginApiName__c.field-meta.xml | 26 ++++++++++-------- .../fields/PluginType__c.field-meta.xml | 4 ++- .../fields/SObjectHandler__c.field-meta.xml | 5 +++- packages/managed-package/sfdx-project.json | 4 +-- sfdx-project.json | 4 +-- 20 files changed, 84 insertions(+), 68 deletions(-) delete mode 100644 docs/log-management/LoggerSObjectHandlerPlugin.md diff --git a/README.md b/README.md index f256c923a..1a9ee409a 100644 --- a/README.md +++ b/README.md @@ -349,14 +349,14 @@ For more details, check out the `LogMessage` class [documentation](https://jongp ## Beta Feature: Custom Plugin Framework for Log\_\_c and LogEntry\_\_c objects -Note: the logger plugin framework is currently not available in the managed package. Once this feature has been stabilized, it'll be added to the managed package version as well. +Note: the logger plugin framework is not available in the managed package due to some platform limitations & considerations with some of the underlying code. The unlocked package is recommended (instead of the managed package) when possible, including if you want to be able to leverage the plugin framework in your org. If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you can leverage Apex or Flow to define "plugins" - the logger system will then automatically run the plugins after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on). - Flow plugins: your Flow should be built with these input parameters: 1. `triggerOperationType` - The name of the current trigger operation (such as BEFORE_INSERT, BEFORE_UPDATE, etc.) - 2. `records` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) - 3. `oldRecords` - The list of logger records as they exist in the datatabase - this is only populated when running in the context of `Trigger.isUpdate` + 2. `triggerNew` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) + 3. `triggerOld` - The list of logger records as they exist in the datatabase - this is only populated when running in the context of `Trigger.isUpdate` - Apex plugins: your Apex class should implement `LoggerSObjectHandlerPlugin`. For example: ```java diff --git a/docs/index.md b/docs/index.md index 89134c256..0309ae72e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -68,4 +68,4 @@ Controller class for the component RelatedLogEntries ### [LoggerSObjectHandlerPlugin](plugin-framework/LoggerSObjectHandlerPlugin) -Abstract class used to define custom plugins to execute when DML statements occur on `Log__c` or `LogEntry__c` +Abstract class used to create custom Apex plugins to execute for all trigger operations on `Log__c` or `LogEntry__c` diff --git a/docs/log-management/LoggerSObjectHandlerPlugin.md b/docs/log-management/LoggerSObjectHandlerPlugin.md deleted file mode 100644 index 0b526dc47..000000000 --- a/docs/log-management/LoggerSObjectHandlerPlugin.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: default ---- - -## LoggerSObjectHandlerPlugin class - -Abstract class used to define custom plugins to execute when DML statements occur on `Log__c` or `LogEntry__c` - ---- - -### Methods - -#### `execute(TriggerOperation triggerOperationType,List triggerNew,Map triggerNewMap,List triggerOld,Map triggerOldMap)` → `void` - -execute description - -##### Parameters - -| Param | Description | -| ---------------------- | ------------------------------------------------------------------------------------------ | -| `triggerOperationType` | The enum instance of `Trigger.operationType` at the time that the handler class is created | -| `triggerNew` | The value `Trigger.new` at the time that the handler class is created | -| `triggerNewMap` | The value `Trigger.newMap` at the time that the handler class is created | -| `triggerOld` | The value `Trigger.old` at the time that the handler class is created | -| `triggerOldMap` | The value `Trigger.oldMap` at the time that the handler class is created | - ---- diff --git a/docs/plugin-framework/LoggerSObjectHandlerPlugin.md b/docs/plugin-framework/LoggerSObjectHandlerPlugin.md index 0b526dc47..3f988ed03 100644 --- a/docs/plugin-framework/LoggerSObjectHandlerPlugin.md +++ b/docs/plugin-framework/LoggerSObjectHandlerPlugin.md @@ -4,7 +4,7 @@ layout: default ## LoggerSObjectHandlerPlugin class -Abstract class used to define custom plugins to execute when DML statements occur on `Log__c` or `LogEntry__c` +Abstract class used to create custom Apex plugins to execute for all trigger operations on `Log__c` or `LogEntry__c` --- @@ -12,7 +12,7 @@ Abstract class used to define custom plugins to execute when DML statements occu #### `execute(TriggerOperation triggerOperationType,List triggerNew,Map triggerNewMap,List triggerOld,Map triggerOldMap)` → `void` -execute description +This method is the entry point for plugins to execute any custom logic. It is automatically called by the logging system for any enabled plugins. Several trigger-based parameters are provided - these parameters should be used by plugins, instead of calling the platform's static variables directly (e.g., use the provided `triggerNew` variable instead of using `Trigger.new` directly, and so on). ##### Parameters diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index cabee0835..7053ce234 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -68,11 +68,11 @@ public abstract class LoggerSObjectHandler { this.setConfigurations(); if (this.handlerConfiguration.IsEnabled__c == true) { + this.triggerOperationType = Trigger.operationType; this.records = Trigger.new; this.recordsById = Trigger.newMap; this.oldRecords = Trigger.old; this.oldRecordsById = Trigger.oldMap; - this.triggerOperationType = Trigger.operationType; } } @@ -132,8 +132,8 @@ public abstract class LoggerSObjectHandler { private void executeFlowPlugin(String flowApiName) { Map flowInputs = new Map(); flowInputs.put('triggerOperationType', this.triggerOperationType?.name()); - flowInputs.put('records', this.records); - flowInputs.put('oldRecords', this.oldRecordsById?.values()); + flowInputs.put('triggerNew', this.records); + flowInputs.put('triggerOld', this.oldRecords); Flow.Interview flowPlugin = Flow.Interview.createInterview(flowApiName, flowInputs); flowPlugin.start(); diff --git a/nebula-logger/main/log-management/objects/LoggerSObjectHandler__mdt/LoggerSObjectHandler__mdt.object-meta.xml b/nebula-logger/main/log-management/objects/LoggerSObjectHandler__mdt/LoggerSObjectHandler__mdt.object-meta.xml index c5ca81420..b97113ef0 100644 --- a/nebula-logger/main/log-management/objects/LoggerSObjectHandler__mdt/LoggerSObjectHandler__mdt.object-meta.xml +++ b/nebula-logger/main/log-management/objects/LoggerSObjectHandler__mdt/LoggerSObjectHandler__mdt.object-meta.xml @@ -1,7 +1,7 @@ Used to configure the Apex trigger handler classes that run on the objects LogEntryEvent__e, Log__c and LogEntry__c - - Logger SObject Handler Configurations + + Logger SObject Handlers Public diff --git a/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls b/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls index 893f5abe1..9f9882800 100644 --- a/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls +++ b/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls @@ -5,12 +5,18 @@ /** * @group Plugin Framework - * @description Abstract class used to define custom plugins to execute when DML statements occur on `Log__c` or `LogEntry__c` + * @description Abstract class used to create custom Apex plugins to execute for all trigger operations on `Log__c` or `LogEntry__c` */ -// TODO: convert to `global` once plugin framework is stable/solidified/ready for the managed package (if possible) +// TODO: If possible, convert to `global` for the managed package - there are some additional platform limitations... +// ... and restrictions with making future changes to abstract classes & interfaces within managed packages... +// ... which could lead to a lot of problems, so for now/indefinitely, plugins will only work in the unlocked package public abstract class LoggerSObjectHandlerPlugin { /** - * @description execute description + * @description This method is the entry point for plugins to execute any custom logic. + * It is automatically called by the logging system for any enabled plugins. + * Several trigger-based parameters are provided - these parameters should be used by plugins, + * instead of calling the platform's static variables directly + * (e.g., use the provided `triggerNew` variable instead of using `Trigger.new` directly, and so on). * @param triggerOperationType The enum instance of `Trigger.operationType` at the time that the handler class is created * @param triggerNew The value `Trigger.new` at the time that the handler class is created * @param triggerNewMap The value `Trigger.newMap` at the time that the handler class is created diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml index 76423568b..6c6f32551 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/LoggerSObjectHandlerPluginParameter__mdt.object-meta.xml @@ -1,7 +1,7 @@ Used to store additional key-value pair parameters that can be used by Logger plugins - - Logger SObject Handler Plugin Parameters + + Logger Plugin Parameters Protected diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml index e9e58f749..ec4dd1ada 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml @@ -1,8 +1,10 @@ - + DataType__c + The expected data type of the parameter value false SubscriberControlled + The expected data type of the parameter value true Picklist @@ -65,6 +67,18 @@ false + + Blob + false + false + + + + Time + false + false + + diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/IsEnabled__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/IsEnabled__c.field-meta.xml index 48d6876ba..77e61e455 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/IsEnabled__c.field-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/IsEnabled__c.field-meta.xml @@ -2,8 +2,10 @@ IsEnabled__c true + Controls if the plugin parameter is enabled/disabled. Only enabled plugin parameters will be used by the Apex plugin framework. false SubscriberControlled + Controls if the plugin parameter is enabled/disabled. Only enabled plugin parameters will be used by the Apex plugin framework. Checkbox diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/SObjectHandlerPlugin__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/SObjectHandlerPlugin__c.field-meta.xml index 916810520..b3ee1ca33 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/SObjectHandlerPlugin__c.field-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/SObjectHandlerPlugin__c.field-meta.xml @@ -1,11 +1,13 @@ SObjectHandlerPlugin__c + The configured plugin that uses this parameter false DeveloperControlled - + The configured plugin that uses this parameter + LoggerSObjectHandlerPlugin__mdt - Logger SObject Handler Plugin Parameters + Logger Plugin Parameters LoggerSObjectHandlerPluginParameters true MetadataRelationship diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Value__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Value__c.field-meta.xml index 631301062..498ea9e20 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Value__c.field-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/Value__c.field-meta.xml @@ -1,8 +1,14 @@ Value__c + The value used by the plugin for this parameter. Since custom metadata type (CMDT) records can be deployed between orgs, you can either: + - Deploy the CMDT records between your orgs - for parameters that should be consistent in all environments + - Manually configure the CMDT records in each org - for parameters that should be environment-specific false SubscriberControlled + The value used by the plugin for this parameter. Since custom metadata type (CMDT) records can be deployed between orgs, you can either: + - Deploy the CMDT records between your orgs - for parameters that should be consistent in all environments + - Manually configure the CMDT records in each org - for parameters that should be environment-specific 131072 LongTextArea diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml index 7259ce4af..427f892cc 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/LoggerSObjectHandlerPlugin__mdt.object-meta.xml @@ -1,7 +1,7 @@ - Used to configure additional Apex classes and Flows that should be executed for all DML statements on Log__c and LogEntry__c - - Logger SObject Handler Plugins + Used to configure additional Apex classes and Flows that should be executed all trigger operations on Log__c and LogEntry__c + + Logger Plugins Protected diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/ExecutionOrder__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/ExecutionOrder__c.field-meta.xml index 4d3a66e91..8b2197334 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/ExecutionOrder__c.field-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/ExecutionOrder__c.field-meta.xml @@ -1,8 +1,10 @@ - + ExecutionOrder__c + The specific order to execute plugins in the org. Plugins are executed in order by sorting by execution order, then plugin name (ORDER BY ExecutionOrder__c NULLS LAST, DeveloperName). false SubscriberControlled + The specific order to execute plugins in the org. Plugins are executed in order by sorting by execution order, then plugin name (ORDER BY ExecutionOrder__c NULLS LAST, DeveloperName). 3 false diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/IsEnabled__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/IsEnabled__c.field-meta.xml index 7c3dca299..6b4db687d 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/IsEnabled__c.field-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/IsEnabled__c.field-meta.xml @@ -1,9 +1,11 @@ - + IsEnabled__c true + Controls if the plugin is enabled/disabled. Only enabled plugins will be executed by the logging system. false SubscriberControlled + Controls if the plugin is enabled/disabled. Only enabled plugins will be executed by the logging system. Checkbox diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml index 6b11a8b3f..b8a7152ef 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml @@ -1,20 +1,24 @@ - + PluginApiName__c The API name of the metadata to run, based on the Plugin Type - - Apex: The name of an Apex class that implements the interface LoggerSObjectHandlerPlugin - - Flow: The API name of a Flow that supports these inputs: - - triggerOperationType: text variable - - records: record collection variable - - oldRecords: record collection variable + +Apex: The name of an Apex class that implements the interface LoggerSObjectHandlerPlugin + +Flow: The API name of a Flow that supports these inputs: + - triggerOperationType: text variable + - triggerNew: record collection variable + - triggerOld: record collection variable false SubscriberControlled The API name of the metadata to run, based on the Plugin Type - - Apex: The name of an Apex class that implements the interface LoggerSObjectHandlerPlugin - - Flow: The API name of a Flow that supports these inputs: - - triggerOperationType: text variable - - records: record collection variable - - oldRecords: record collection variable + +Apex: The name of an Apex class that implements the interface LoggerSObjectHandlerPlugin + +Flow: The API name of a Flow that supports these inputs: + - triggerOperationType: text variable + - triggerNew: record collection variable + - triggerOld: record collection variable 255 true diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml index 470355af0..ffea786d1 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml @@ -1,8 +1,10 @@ - + PluginType__c + The type of plugin that the logging system should dynamically execute - Apex or Flow. false SubscriberControlled + The type of plugin that the logging system should dynamically execute - Apex or Flow. true Picklist diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/SObjectHandler__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/SObjectHandler__c.field-meta.xml index a2425f815..fa88c1444 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/SObjectHandler__c.field-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/SObjectHandler__c.field-meta.xml @@ -1,10 +1,13 @@ - + SObjectHandler__c + The logging system's trigger SObject handler class that should dynamically call the plugin. This controls when the plugin is executed. false SubscriberControlled + The logging system's trigger SObject handler class that should dynamically call the plugin. This controls when the plugin is executed. LoggerSObjectHandler__mdt + Logger Plugins LoggerSObjectHandlerPlugins true MetadataRelationship diff --git a/packages/managed-package/sfdx-project.json b/packages/managed-package/sfdx-project.json index f0a9fb441..e56e959a7 100644 --- a/packages/managed-package/sfdx-project.json +++ b/packages/managed-package/sfdx-project.json @@ -9,10 +9,10 @@ "default": true, "definitionFile": "config/project-scratch-def.json", "postInstallScript": "LoggerInstallHandler", - "versionName": "Logger SObject Handler Plugins", + "versionName": "Code Stability & Bugfixes", "versionNumber": "4.5.0.0", "ancestorVersion": "4.4.0.2", - "versionDescription": "Easily add your own automations for Log__c and LogEntry__c objects using Apex or Flow", + "versionDescription": "Code stability & bugfixes for the managed package. Unlocked package only: new logger plugin framework", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases" } ], diff --git a/sfdx-project.json b/sfdx-project.json index d78ebe6ac..5e9fba436 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -8,9 +8,9 @@ "path": "nebula-logger", "default": true, "definitionFile": "config/project-scratch-def-with-experience-cloud.json", - "versionName": "Logger SObject Handler Plugins", + "versionName": "Logger Plugin Framework", "versionNumber": "4.5.0.0", - "versionDescription": "Easily add your own automations for Log__c and LogEntry__c objects using Apex or Flow", + "versionDescription": "Easily add or install plugins that enhance the Log__c and LogEntry__c objects, using Apex or Flow", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases" }, { From 6910cfe8e18b03896e4ba45e416c74dc971d12b0 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 13 Jun 2021 11:37:57 -0700 Subject: [PATCH 59/82] Renamed Slack CMDT record --- .../Slack/classes/SlackLoggerPlugin.cls-meta.xml | 2 +- ...a.xml => LoggerSObjectHandlerPlugin.Slack.md-meta.xml} | 8 ++++++++ ...ObjectHandlerPluginParameter.SlackApiToken.md-meta.xml | 2 +- ...jectHandlerPluginParameter.SlackAuthMethod.md-meta.xml | 2 +- ...ObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml | 2 +- ...PluginParameter.SlackLoggingLevelThreshold.md-meta.xml | 2 +- ...in.listView-meta.xml => SlackPlugin.listView-meta.xml} | 4 ++-- 7 files changed, 15 insertions(+), 7 deletions(-) rename nebula-logger-plugins/Slack/customMetadata/{LoggerSObjectHandlerPlugin.SlackLoggerPlugin.md-meta.xml => LoggerSObjectHandlerPlugin.Slack.md-meta.xml} (81%) rename nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/{SlackLoggerPlugin.listView-meta.xml => SlackPlugin.listView-meta.xml} (87%) diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls-meta.xml b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls-meta.xml index 482559c8b..d75b0582f 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls-meta.xml +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls-meta.xml @@ -1,4 +1,4 @@ - + 51.0 Active diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackLoggerPlugin.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.Slack.md-meta.xml similarity index 81% rename from nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackLoggerPlugin.md-meta.xml rename to nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.Slack.md-meta.xml index 730b51524..8d86c8a02 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.SlackLoggerPlugin.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.Slack.md-meta.xml @@ -8,6 +8,14 @@ Any logs with MaxLogEntryLoggingLevelOrdinal__c >= the parameter 'SlackLoggingLevelThreshold' will send a notification to Slack + + ExecutionOrder__c + + + + IsEnabled__c + true + PluginApiName__c SlackLoggerPlugin diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackApiToken.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackApiToken.md-meta.xml index 2ed6a4844..a553d2c29 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackApiToken.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackApiToken.md-meta.xml @@ -8,6 +8,6 @@ SObjectHandlerPlugin__c - SlackLoggerPlugin + Slack diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml index 631b0d3ef..1df3f2b9f 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml @@ -15,7 +15,7 @@ NAMED_CREDENTIALS SObjectHandlerPlugin__c - SlackLoggerPlugin + Slack Value__c diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml index b7f0ac3c7..b80650932 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml @@ -8,7 +8,7 @@ SObjectHandlerPlugin__c - SlackLoggerPlugin + Slack Value__c diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml index c472c2a9b..4d38b3685 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml @@ -8,7 +8,7 @@ SObjectHandlerPlugin__c - SlackLoggerPlugin + Slack Value__c diff --git a/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackLoggerPlugin.listView-meta.xml b/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackPlugin.listView-meta.xml similarity index 87% rename from nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackLoggerPlugin.listView-meta.xml rename to nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackPlugin.listView-meta.xml index 16e7b979f..cbad1df91 100644 --- a/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackLoggerPlugin.listView-meta.xml +++ b/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackPlugin.listView-meta.xml @@ -1,6 +1,6 @@ - SlackLoggerPlugin + SlackPlugin MasterLabel DeveloperName SObjectHandlerPlugin__c @@ -12,7 +12,7 @@ SObjectHandlerPlugin__c equals - SlackLoggerPlugin + SlackPlugin From ee587d053a3d3d62e23528a9372b8a9de538b680 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 13 Jun 2021 18:15:03 -0700 Subject: [PATCH 60/82] Slack plugin cleanup + README updates --- README.md | 8 ++--- content/slack-plugin-configuration.png | Bin 0 -> 109637 bytes nebula-logger-plugins/Slack/README.md | 28 +++++------------- .../Slack/classes/SlackLoggerPlugin.cls | 23 +++++--------- ...ggerSObjectHandlerPlugin.Slack.md-meta.xml | 8 ----- ...rPluginParameter.SlackApiToken.md-meta.xml | 13 -------- ...luginParameter.SlackAuthMethod.md-meta.xml | 24 --------------- ...rPluginParameter.SlackEndpoint.md-meta.xml | 8 ++--- ...ter.SlackLoggingLevelThreshold.md-meta.xml | 2 +- .../AllLogsToBeSentToSlack.listView-meta.xml | 26 ++++++++++++++++ 10 files changed, 50 insertions(+), 90 deletions(-) create mode 100644 content/slack-plugin-configuration.png delete mode 100644 nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackApiToken.md-meta.xml delete mode 100644 nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml create mode 100644 nebula-logger/main/log-management/objects/Log__c/listViews/AllLogsToBeSentToSlack.listView-meta.xml diff --git a/README.md b/README.md index 1a9ee409a..836eaae31 100644 --- a/README.md +++ b/README.md @@ -59,10 +59,10 @@ You can choose to install the unlocked package, you can deploy the metadata from Faster release cycle: new enhancements & bugfixes will be immediately available in GitHub - Public Apex Methods - Any public Apex methods are subject to change in the future - they can be used, but you may encounter deployment issues if future changes to public methods are not backwards-compatible + Public & Protected Apex Methods + Any public and protected Apex methods are subject to change in the future - they can be used, but you may encounter deployment issues if future changes to public and protected methods are not backwards-compatible Only global methods are available in managed packages - any global Apex methods available in the managed package will be supported for the foreseeable future - Any public Apex methods are subject to change in the future - they can be used, but you may encounter deployment issues if future changes to public methods are not backwards-compatible + Any public and protected Apex methods are subject to change in the future - they can be used, but you may encounter deployment issues if future changes to public and protected methods are not backwards-compatible Apex Debug Statements @@ -370,7 +370,7 @@ If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, ) { switch on triggerOperationType { when BEFORE_INSERT { - for (Log__c log : logs) { + for (Log__c log : (List) triggerNew) { log.Status__c = 'On Hold'; } } diff --git a/content/slack-plugin-configuration.png b/content/slack-plugin-configuration.png new file mode 100644 index 0000000000000000000000000000000000000000..d8ad876339e9c82209ac62ddcdbbcecee5aef343 GIT binary patch literal 109637 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 literal 0 HcmV?d00001 diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index 881acbf34..668c51b61 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -21,25 +21,13 @@ This plugin includes some add-on metadata for Logger to support the Slack integr ## Installation Steps -1. Ensure that you have the unlocked package version of Nebula Logger installed in your org -2. Install/deploy Slack plugin package for Logger -3. Create a new app in you Slack workspace -4. Add Slack as an Auth Provider in your org -5. Add a named credential called 'Slack' in your org +1. In Salesforce, ensure that you have the unlocked package version of Nebula Logger installed in your org. +2. In Salesforce, deploy the metadata for the Slack plugin for Logger. Currently, this has to be done by cloning/downloading the repo from GitHub and deploying yourself. An unlocked package will be released in the future to make this process much easier. +3. In Slack, create a new app in your Slack workspace and enable incoming webhooks for your app. +4. In Slack, create a new incoming webhook, and copy the webhook URL. +5. In Salesforce, go to Setup --> Custom Metadata Types --> Logger Plugin --> Slack (shown in screenshot below) and find the parameter 'Slack Endpoint'. Paste the Slack webhook URL into the `Value__c` field and save the Plugin Parameter record. +6. In Salesforce, set the desired logging level value for the Logger Plugin Parameter 'Slack Logging Level Threshold` (shown in screenshot below). It controls which logging level (ERROR, WARN, INFO, DEBUG, FINE, FINER OR FINEST) will trigger the Slack notifications to be sent. ---- - -## Setup Steps - -Choose auth method: 'API_TOKEN' or 'NAMED_CREDENTIALS' - -### 'API_TOKEN' Steps - -1. Create remote site setting -2. Create/update logger plugin parameter - -### 'NAMED_CREDENTIALS' Steps +At this point, the Slack integration should now be setup & working - any new logs that meet the threshold logging level (step 6 above) will send a Slack notification. -1. Create Slack app -2. Create Auth Provider & Named Credential - See [UnofficialSF.com's article](https://unofficialsf.com/authorizing-salesforce-access-to-slack/) on how to set this up for Slack -3. Create/update logger plugin parameter +![Slack plugin: configuration](./../../content/slack-plugin-configuration.png) \ No newline at end of file diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index 01c67fbe0..6acdb5096 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -120,6 +120,7 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi } private void requeryLogs() { + // TODO: switch to dynamically querying based on a new `Log__c` field set parameter this.logs = [ SELECT Id, @@ -157,35 +158,32 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi } private HttpRequest createSlackHttpRequest() { - String authMethod = this.getStringParameter(PARAM_AUTH_METHOD); - System.debug('authMethod==' + authMethod); String endpoint = this.getStringParameter(PARAM_ENDPOINT); System.debug('endpoint==' + endpoint); - String apiToken = this.getStringParameter(PARAM_API_TOKEN); - System.debug('apiToken==' + apiToken); HttpRequest request = new HttpRequest(); request.setEndpoint(endpoint); request.setMethod('POST'); request.setHeader('Content-Type', 'application/json'); - if (authMethod == SlackAuthMethod.API_TOKEN.name() && String.isNotBlank(apiToken)) { - request.setHeader('token', apiToken); - } - return request; } private LogDto convertLog(Log__c log) { + LogEntry__c lastLogEntry = log.LogEntries__r.get(0); + String messageText = 'Last Log Entry Message' + + '\n`' + lastLogEntry.LoggingLevel__c + ': ' + lastLogEntry.Message__c + '`'; + LogDto notification = new LogDto(); notification.author_link = Url.getSalesforceBaseUrl().toExternalForm() + '/' + log.LoggedBy__c; notification.author_name = log.LoggedBy__r.Username; notification.color = this.getNotificationColor(log); notification.fields = new List(); - notification.text = Schema.Log__c.TotalLogEntries__c.getDescribe().getLabel() + ': `' + String.valueOf(log.TotalLogEntries__c) + '`'; + notification.text = messageText;//Schema.Log__c.TotalLogEntries__c.getDescribe().getLabel() + ': `' + String.valueOf(log.TotalLogEntries__c) + '`'; notification.title = log.Name; notification.title_link = Url.getSalesforceBaseUrl().toExternalForm() + '/' + log.Id; + // TODO: switch to dynamically creating Slack DTO fields based on a new `Log__c` field set parameter FieldDto startTimeField = new FieldDto(); startTimeField.isShort = true; startTimeField.title = Schema.Log__c.StartTime__c.getDescribe().getLabel(); @@ -210,13 +208,6 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi totalWARNEntriesField.value = '`' + String.valueOf(log.TotalWARNLogEntries__c) + '`'; notification.fields.add(totalWARNEntriesField); - LogEntry__c lastLogEntry = log.LogEntries__r.get(0); - FieldDto logEntryField = new FieldDto(); - logEntryField.isShort = false; - logEntryField.title = 'Last Log Entry Message'; - logEntryField.value = '`' + lastLogEntry.LoggingLevel__c + ': ' + lastLogEntry.Message__c + '`'; - notification.fields.add(logEntryField); - String logOwnerType = log.OwnerId.getSObjectType().getDescribe().getName(); FieldDto logOwnerNameField = new FieldDto(); logOwnerNameField.isShort = true; diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.Slack.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.Slack.md-meta.xml index 8d86c8a02..730b51524 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.Slack.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPlugin.Slack.md-meta.xml @@ -8,14 +8,6 @@ Any logs with MaxLogEntryLoggingLevelOrdinal__c >= the parameter 'SlackLoggingLevelThreshold' will send a notification to Slack - - ExecutionOrder__c - - - - IsEnabled__c - true - PluginApiName__c SlackLoggerPlugin diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackApiToken.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackApiToken.md-meta.xml deleted file mode 100644 index a553d2c29..000000000 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackApiToken.md-meta.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - false - - DataType__c - String - - - SObjectHandlerPlugin__c - Slack - - diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml deleted file mode 100644 index 1df3f2b9f..000000000 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackAuthMethod.md-meta.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - false - - DataType__c - String - - - Description__c - Possible values: - -API_TOKEN -NAMED_CREDENTIALS - - - SObjectHandlerPlugin__c - Slack - - - Value__c - API_TOKEN - - diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml index b80650932..569703dc8 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml @@ -7,11 +7,11 @@ String - SObjectHandlerPlugin__c - Slack + Description__c + The incoming webhook URL for your Slack app - Value__c - https://hooks.slack.com/services/ + SObjectHandlerPlugin__c + Slack diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml index 4d38b3685..8379ab3a2 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml @@ -4,7 +4,7 @@ false DataType__c - Integer + String SObjectHandlerPlugin__c diff --git a/nebula-logger/main/log-management/objects/Log__c/listViews/AllLogsToBeSentToSlack.listView-meta.xml b/nebula-logger/main/log-management/objects/Log__c/listViews/AllLogsToBeSentToSlack.listView-meta.xml new file mode 100644 index 000000000..cdb1bc276 --- /dev/null +++ b/nebula-logger/main/log-management/objects/Log__c/listViews/AllLogsToBeSentToSlack.listView-meta.xml @@ -0,0 +1,26 @@ + + + AllLogsToBeSentToSlack + NAME + LoggedByUsernameLink__c + StartTime__c + OWNER.ALIAS + Priority__c + Status__c + TransactionId__c + TotalLimitsCpuTimeUsed__c + TotalLogEntries__c + TotalERRORLogEntries__c + TotalWARNLogEntries__c + Everything + + SlackNotificationDate__c + equals + + + SendSlackNotification__c + equals + 1 + + + From add0b275e038338add30e190e07733edac17a736 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 13 Jun 2021 18:19:50 -0700 Subject: [PATCH 61/82] Removed unused constants in SlackLoggerPlugin --- nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls | 2 -- 1 file changed, 2 deletions(-) diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index 6acdb5096..0ebc2a7e1 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -9,8 +9,6 @@ */ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugin implements Queueable, Database.AllowsCallouts { // Constants used for loading configuration & parameters from custom metadata type objects - private static final String PARAM_API_TOKEN = 'SlackApiToken'; - private static final String PARAM_AUTH_METHOD = 'SlackAuthMethod'; private static final String PARAM_ENDPOINT = 'SlackEndpoint'; private static final String PARAM_THRESHOLD_LOGGING_LEVEL_NAME = 'SlackLoggingLevelThreshold'; From cedc7d3daebf31194f10c5997d39a0a227676a2e Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 13 Jun 2021 18:27:04 -0700 Subject: [PATCH 62/82] Cleaned up plugin details in README --- README.md | 8 ++++++-- content/logger-handler-configuration.png | Bin 102252 -> 0 bytes 2 files changed, 6 insertions(+), 2 deletions(-) delete mode 100644 content/logger-handler-configuration.png diff --git a/README.md b/README.md index 836eaae31..bd15a7903 100644 --- a/README.md +++ b/README.md @@ -380,9 +380,11 @@ If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, ``` -Once you've created your Apex or Flow plugin(s), you will also need to configure the custom metadata type `LoggerSObjectHandler__mdt` to specify the name(s) of Apex class and Flow to run. +Once you've created your Apex or Flow plugin(s), you will also need to configure the plugin: +- 'Logger Plugin' - use the custom metadata type `LoggerSObjectHandlerPlugin__mdt` to define your plugin, including the plugin type (Apex or Flow) and the API name of your plugin's Apex class or Flow +- 'Logger Plugin Parameter' - use the custom metadata type `LoggerSObjectHandlerPluginParameter__mdt` to define any configurable parameters needed for your plugin, such as environment-specific URLs and other similar configurations -![Logger Handler Configuration](./content/logger-handler-configuration.png) +![Logger plugin: configuration](./content/slack-plugin-configuration.png) ### Beta Plugin: Slack Integration @@ -395,6 +397,8 @@ The optional [Slack plugin](./nebula-logger-plugins/Slack/) leverages the Nebula Check out the [Slack plugin](./nebula-logger-plugins/Slack/) for more details on how to install & customize the plugin +![Slack plugin: notification](./content/slack-plugin-notification.png) + ## Managing Logs To help development and support teams better manage logs (and any underlying code or config issues), some fields on `Log__c` are provided to track the owner, priority and status of a log. These fields are optional, but are helpful in critical environments (production, QA sandboxes, UAT sandboxes, etc.) for monitoring ongoing user activities. diff --git a/content/logger-handler-configuration.png b/content/logger-handler-configuration.png deleted file mode 100644 index 07fc97df1ae2ae27c1e0c89db429bbba001639ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102252 zcmb5VRajh6x-FUzAh^2*C%C(W;O-P&xVt+E8a%i|aCeu&CAho0yZfzlpYBedy&vv@ z^-$lewbry>#u)#s5Cu7LL^wRSckkXIN=k?*y?Y1!<=s07c^C+AONna~$GdlLZ;~QH zDsGF%>9AfZGY@xX$4@EA$M~>X^PNyVp-)O-n`)TWw2jkHv}Tyr)<;TpvxH@Zb+4T? z*(wUOi!}G4>I?DwRwPD1sv1+4r`C2yTNVV3Ps!xu>sNJ|PDxFUXH9!);Qxn}y)@Kb z1Lnw2Fn<5JplM0bD*tZy(TM=74k?84@2lrm5G37SPrw)`O!Y$~u;O?>>0PDp_$G6< zj-av)_Mi`6dX-&=YTtwt%zRm+`|Aym(FnQ~4W*@}_4TtRHBBq0dQ3k!cO06)jp}r` zxVR4w51M85ndPgde_pFo*?*-}wS*h$;_*$9(&xbGN;WVhlGs~mp?ZXf?kdPW2G-<( z`(UtU3ggA8``^O^e-OF*%*eRbff z*Lc%C=h`vMsVn;L4twnTY#J)G8b)nu1{%$jbxwZzc_quF#3yS2f!IiaN>eP>va%a? z)D*o0NWtlH4V^J+I%~fs&GO~aEjUu2D#^V+{pow`CA+PprzBE_X`sE0t85rwV7DQh zg*h@!FX3(j5gpuP2qeV&V9>zaGT%5933#{UaHjDh2GX(>##3PZKK+PI(`j+>ez}=b z^A}jRm@HIaPp@E6?Q9K+6HAKYH!Xgz!@6be=uVA$T z+FN!UBV;v^0b=Gi{Mmr?dvj|I$42qB!8wVR2h1Fq=ZU6S$H{na=Rd10lJ@13f{uoM zmF5lf)|bRUuqkor+qI1tx3R&hbUD?g8_FipKziUB9f92 zyG7RO{X~yN$xgf}#D&u@}!_XjJGNqLb_}quJO(z&@Q8H-BK1t^<%Y<*2jdxk}qo3LP)OSC?CI@7Bzbhx)^z39_D zJy@lEZ@F1exAL&lxz$(t^(3qynHm$k64|K=$A5wWIif5nB(nre;8%vkp|iWYU2
    *-*)kov9xo?nCb|yvCg!HfW_sV6hplBM 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⋙2diZ>i+lslcLs94n;gr=l)e)e?ph%N} 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 From cc862084fdb4a19446b84fcc525c510a4d07e0f7 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 13 Jun 2021 18:36:47 -0700 Subject: [PATCH 63/82] Moved Slack list view to correct folder --- .../Log__c/listViews/AllLogsToBeSentToSlack.listView-meta.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename {nebula-logger/main/log-management => nebula-logger-plugins/Slack}/objects/Log__c/listViews/AllLogsToBeSentToSlack.listView-meta.xml (95%) diff --git a/nebula-logger/main/log-management/objects/Log__c/listViews/AllLogsToBeSentToSlack.listView-meta.xml b/nebula-logger-plugins/Slack/objects/Log__c/listViews/AllLogsToBeSentToSlack.listView-meta.xml similarity index 95% rename from nebula-logger/main/log-management/objects/Log__c/listViews/AllLogsToBeSentToSlack.listView-meta.xml rename to nebula-logger-plugins/Slack/objects/Log__c/listViews/AllLogsToBeSentToSlack.listView-meta.xml index cdb1bc276..0637b0e95 100644 --- a/nebula-logger/main/log-management/objects/Log__c/listViews/AllLogsToBeSentToSlack.listView-meta.xml +++ b/nebula-logger-plugins/Slack/objects/Log__c/listViews/AllLogsToBeSentToSlack.listView-meta.xml @@ -1,4 +1,4 @@ - + AllLogsToBeSentToSlack NAME From 7a475eaa45a66fa9f3a772e44fbcbf66a7d9d6c5 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 13 Jun 2021 18:52:04 -0700 Subject: [PATCH 64/82] Updated Flow plugin details, moved note location about plugin framework & mgd pkg --- README.md | 13 +++++++------ .../log-management/classes/LoggerSObjectHandler.cls | 5 +++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index bd15a7903..d7c2e3f39 100644 --- a/README.md +++ b/README.md @@ -349,14 +349,14 @@ For more details, check out the `LogMessage` class [documentation](https://jongp ## Beta Feature: Custom Plugin Framework for Log\_\_c and LogEntry\_\_c objects -Note: the logger plugin framework is not available in the managed package due to some platform limitations & considerations with some of the underlying code. The unlocked package is recommended (instead of the managed package) when possible, including if you want to be able to leverage the plugin framework in your org. +If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you can leverage Apex or Flow to define "plugins" - the logger system will then automatically run the plugins after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on). This framework makes it easy to build your own plugins, or deploy/install others' prebuilt packages, without having to modify the logging system directly. -If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you can leverage Apex or Flow to define "plugins" - the logger system will then automatically run the plugins after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on). +- Flow plugins: your Flow should be built as auto-launched Flows with these parameters: + 1. `Input` parameter `triggerOperationType` - The name of the current trigger operation (such as BEFORE_INSERT, BEFORE_UPDATE, etc.) + 2. `Input` parameter `triggerNew` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) + 2. `Output` parameter `updatedTriggerNew` - If your Flow makes any updates to the collection of records, you should return a record collection containing the updated records + 3. `Input` parameter `triggerOld` - The list of logger records as they exist in the datatabase -- Flow plugins: your Flow should be built with these input parameters: - 1. `triggerOperationType` - The name of the current trigger operation (such as BEFORE_INSERT, BEFORE_UPDATE, etc.) - 2. `triggerNew` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) - 3. `triggerOld` - The list of logger records as they exist in the datatabase - this is only populated when running in the context of `Trigger.isUpdate` - Apex plugins: your Apex class should implement `LoggerSObjectHandlerPlugin`. For example: ```java @@ -386,6 +386,7 @@ Once you've created your Apex or Flow plugin(s), you will also need to configure ![Logger plugin: configuration](./content/slack-plugin-configuration.png) +Note: the logger plugin framework is not available in the managed package due to some platform limitations & considerations with some of the underlying code. The unlocked package is recommended (instead of the managed package) when possible, including if you want to be able to leverage the plugin framework in your org. ### Beta Plugin: Slack Integration The optional [Slack plugin](./nebula-logger-plugins/Slack/) leverages the Nebula Logger plugin framework to automatically send Slack notifications for logs that meet a certain (configurable) logging level. The plugin also serves as a functioning example of how to build your own plugin for Nebula Logger, such as how to: diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index 7053ce234..78d0d974a 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -137,5 +137,10 @@ public abstract class LoggerSObjectHandler { Flow.Interview flowPlugin = Flow.Interview.createInterview(flowApiName, flowInputs); flowPlugin.start(); + + List updatedTriggerNew = (List) flowPlugin.getVariableValue('updatedTriggerNew'); + if (updatedTriggerNew != null && updatedTriggerNew.size() == this.records.size()) { + this.records = updatedTriggerNew; + } } } From 5c95611c9f84034be9771cf02dea5cca460e44c5 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 13 Jun 2021 18:59:02 -0700 Subject: [PATCH 65/82] Updated trigger framework variable names for consistency & clarity --- .../flows/LogHandler_Tests_Flow.flow-meta.xml | 2 +- .../classes/LogEntryEventHandler.cls | 4 +-- .../log-management/classes/LogHandler.cls | 4 +-- .../classes/LoggerSObjectHandler.cls | 28 +++++++++---------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml b/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml index de2aca961..263580de4 100644 --- a/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml +++ b/extra-tests/extra-metadata/flows/LogHandler_Tests_Flow.flow-meta.xml @@ -76,7 +76,7 @@ Active - oldRecords + triggerOld SObject true true diff --git a/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls b/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls index 3055e73b2..144d299f7 100644 --- a/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryEventHandler.cls @@ -17,7 +17,7 @@ public without sharing class LogEntryEventHandler extends LoggerSObjectHandler { @testVisible private List logEntryEvents { get { - return (List) this.records; + return (List) this.triggerNew; } } @@ -30,7 +30,7 @@ public without sharing class LogEntryEventHandler extends LoggerSObjectHandler { public LogEntryEventHandler(List logEntryEvents) { // Override the records provided by LoggerSObjectHandler - this.records = logEntryEvents; + this.triggerNew = logEntryEvents; } /** diff --git a/nebula-logger/main/log-management/classes/LogHandler.cls b/nebula-logger/main/log-management/classes/LogHandler.cls index 99ea01ef7..e697b2075 100644 --- a/nebula-logger/main/log-management/classes/LogHandler.cls +++ b/nebula-logger/main/log-management/classes/LogHandler.cls @@ -28,14 +28,14 @@ public without sharing class LogHandler extends LoggerSObjectHandler { @testVisible private List logs { get { - return (List) this.records; + return (List) this.triggerNew; } } @testVisible private Map oldLogsById { get { - return (Map) this.oldRecordsById; + return (Map) this.triggerOldMap; } } diff --git a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls index 78d0d974a..264ce929a 100644 --- a/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls +++ b/nebula-logger/main/log-management/classes/LoggerSObjectHandler.cls @@ -53,13 +53,13 @@ public abstract class LoggerSObjectHandler { @testVisible protected TriggerOperation triggerOperationType; @testVisible - protected List records; + protected List triggerNew; @testVisible - protected Map recordsById; + protected Map triggerNewMap; @testVisible - protected List oldRecords; + protected List triggerOld; @testVisible - protected Map oldRecordsById; + protected Map triggerOldMap; private LoggerSObjectHandler__mdt handlerConfiguration; private List plugins; @@ -69,10 +69,10 @@ public abstract class LoggerSObjectHandler { if (this.handlerConfiguration.IsEnabled__c == true) { this.triggerOperationType = Trigger.operationType; - this.records = Trigger.new; - this.recordsById = Trigger.newMap; - this.oldRecords = Trigger.old; - this.oldRecordsById = Trigger.oldMap; + this.triggerNew = Trigger.new; + this.triggerNewMap = Trigger.newMap; + this.triggerOld = Trigger.old; + this.triggerOldMap = Trigger.oldMap; } } @@ -96,7 +96,7 @@ public abstract class LoggerSObjectHandler { } protected void executePlugins() { - if (this.records == null || this.plugins == null || this.plugins.isEmpty()) { + if (this.triggerNew == null || this.plugins == null || this.plugins.isEmpty() == true) { return; } @@ -126,21 +126,21 @@ public abstract class LoggerSObjectHandler { private void executeApexPlugin(String apexClassName) { LoggerSObjectHandlerPlugin apexPlugin = (LoggerSObjectHandlerPlugin) Type.forName(apexClassName).newInstance(); - apexPlugin.execute(this.triggerOperationType, this.records, this.recordsById, this.oldRecords, this.oldRecordsById); + apexPlugin.execute(this.triggerOperationType, this.triggerNew, this.triggerNewMap, this.triggerOld, this.triggerOldMap); } private void executeFlowPlugin(String flowApiName) { Map flowInputs = new Map(); flowInputs.put('triggerOperationType', this.triggerOperationType?.name()); - flowInputs.put('triggerNew', this.records); - flowInputs.put('triggerOld', this.oldRecords); + flowInputs.put('triggerNew', this.triggerNew); + flowInputs.put('triggerOld', this.triggerOld); Flow.Interview flowPlugin = Flow.Interview.createInterview(flowApiName, flowInputs); flowPlugin.start(); List updatedTriggerNew = (List) flowPlugin.getVariableValue('updatedTriggerNew'); - if (updatedTriggerNew != null && updatedTriggerNew.size() == this.records.size()) { - this.records = updatedTriggerNew; + if (updatedTriggerNew != null && updatedTriggerNew.size() == this.triggerNew.size()) { + this.triggerNew = updatedTriggerNew; } } } From fce4708491a6e988d93200c6ae7c36fe9197c2f6 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 13 Jun 2021 19:28:34 -0700 Subject: [PATCH 66/82] Fixed list view criteria, added CMDT description --- nebula-logger-plugins/Slack/README.md | 2 +- ...PluginParameter.SlackLoggingLevelThreshold.md-meta.xml | 8 ++++---- .../listViews/SlackPlugin.listView-meta.xml | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index 668c51b61..6c40c8ca5 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -26,7 +26,7 @@ This plugin includes some add-on metadata for Logger to support the Slack integr 3. In Slack, create a new app in your Slack workspace and enable incoming webhooks for your app. 4. In Slack, create a new incoming webhook, and copy the webhook URL. 5. In Salesforce, go to Setup --> Custom Metadata Types --> Logger Plugin --> Slack (shown in screenshot below) and find the parameter 'Slack Endpoint'. Paste the Slack webhook URL into the `Value__c` field and save the Plugin Parameter record. -6. In Salesforce, set the desired logging level value for the Logger Plugin Parameter 'Slack Logging Level Threshold` (shown in screenshot below). It controls which logging level (ERROR, WARN, INFO, DEBUG, FINE, FINER OR FINEST) will trigger the Slack notifications to be sent. +6. In Salesforce, set the desired logging level value for the Logger Plugin Parameter 'Slack Logging Level Threshold` (shown in screenshot below). It controls which logging level (ERROR, WARN, INFO, DEBUG, FINE, FINER, or FINEST) will trigger the Slack notifications to be sent. At this point, the Slack integration should now be setup & working - any new logs that meet the threshold logging level (step 6 above) will send a Slack notification. diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml index 8379ab3a2..ccc607638 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml @@ -7,11 +7,11 @@ String
    - SObjectHandlerPlugin__c - Slack + Description__c + The logging level name that triggers a Slack notification to be sent. Possible logging levels are: ERROR, WARN, INFO, DEBUG, FINE, FINER, or FINEST - Value__c - WARN + SObjectHandlerPlugin__c + Slack diff --git a/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackPlugin.listView-meta.xml b/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackPlugin.listView-meta.xml index cbad1df91..8377ef925 100644 --- a/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackPlugin.listView-meta.xml +++ b/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackPlugin.listView-meta.xml @@ -12,7 +12,7 @@ SObjectHandlerPlugin__c equals - SlackPlugin + Slack - + From 5b709e367a0a2590500f635a1a29e7b52ec2fbd3 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 13 Jun 2021 23:15:10 -0700 Subject: [PATCH 67/82] Fixed deployment failure due to old variable ref --- nebula-logger-plugins/Slack/README.md | 2 +- .../Slack/classes/SlackLoggerPlugin.cls | 17 +- ...SlackNotificationLoggingLevel.md-meta.xml} | 2 +- .../classes/LogEntryHandler.cls | 2 +- .../classes/LoggerSObjectHandlerPlugin.cls | 213 ++++++++++++++---- 5 files changed, 175 insertions(+), 61 deletions(-) rename nebula-logger-plugins/Slack/customMetadata/{LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml => LoggerSObjectHandlerPluginParameter.SlackNotificationLoggingLevel.md-meta.xml} (92%) diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index 6c40c8ca5..31a2b9c7d 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -26,7 +26,7 @@ This plugin includes some add-on metadata for Logger to support the Slack integr 3. In Slack, create a new app in your Slack workspace and enable incoming webhooks for your app. 4. In Slack, create a new incoming webhook, and copy the webhook URL. 5. In Salesforce, go to Setup --> Custom Metadata Types --> Logger Plugin --> Slack (shown in screenshot below) and find the parameter 'Slack Endpoint'. Paste the Slack webhook URL into the `Value__c` field and save the Plugin Parameter record. -6. In Salesforce, set the desired logging level value for the Logger Plugin Parameter 'Slack Logging Level Threshold` (shown in screenshot below). It controls which logging level (ERROR, WARN, INFO, DEBUG, FINE, FINER, or FINEST) will trigger the Slack notifications to be sent. +6. In Salesforce, set the desired logging level value for the Logger Plugin Parameter 'Slack Notification Logging Level` (shown in screenshot below). It controls which logging level (ERROR, WARN, INFO, DEBUG, FINE, FINER, or FINEST) will trigger the Slack notifications to be sent. At this point, the Slack integration should now be setup & working - any new logs that meet the threshold logging level (step 6 above) will send a Slack notification. diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index 0ebc2a7e1..71de44667 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -10,12 +10,7 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugin implements Queueable, Database.AllowsCallouts { // Constants used for loading configuration & parameters from custom metadata type objects private static final String PARAM_ENDPOINT = 'SlackEndpoint'; - private static final String PARAM_THRESHOLD_LOGGING_LEVEL_NAME = 'SlackLoggingLevelThreshold'; - - private enum SlackAuthMethod { - API_TOKEN, - NAMED_CREDENTIAL - } + private static final String PARAM_NOTIFICATION_LOGGING_LEVEL_NAME = 'SlackNotificationLoggingLevel'; private List logs; @@ -88,15 +83,15 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi } private void flagLogsForSlackNotification() { - String thresholdLoggingLevelName = this.getStringParameter(PARAM_THRESHOLD_LOGGING_LEVEL_NAME); + String notificationLoggingLevelName = this.getParameter(PARAM_NOTIFICATION_LOGGING_LEVEL_NAME)?.Value__c; - if (String.isBlank(thresholdLoggingLevelName)) { + if (String.isBlank(notificationLoggingLevelName)) { return; } - LoggingLevel thresholdLoggingLevel = Logger.getLoggingLevel(thresholdLoggingLevelName); + LoggingLevel notificationLoggingLevel = Logger.getLoggingLevel(notificationLoggingLevelName); for (Log__c log : this.logs) { - if (log.MaxLogEntryLoggingLevelOrdinal__c >= thresholdLoggingLevel.ordinal()) { + if (log.MaxLogEntryLoggingLevelOrdinal__c >= notificationLoggingLevel.ordinal()) { log.SendSlackNotification__c = true; } } @@ -156,7 +151,7 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi } private HttpRequest createSlackHttpRequest() { - String endpoint = this.getStringParameter(PARAM_ENDPOINT); + String endpoint = this.getParameter(PARAM_ENDPOINT)?.Value__c; System.debug('endpoint==' + endpoint); HttpRequest request = new HttpRequest(); diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackNotificationLoggingLevel.md-meta.xml similarity index 92% rename from nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml rename to nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackNotificationLoggingLevel.md-meta.xml index ccc607638..db1dfaf4d 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackLoggingLevelThreshold.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackNotificationLoggingLevel.md-meta.xml @@ -1,6 +1,6 @@ - + false DataType__c diff --git a/nebula-logger/main/log-management/classes/LogEntryHandler.cls b/nebula-logger/main/log-management/classes/LogEntryHandler.cls index 739986c03..9922ccae1 100644 --- a/nebula-logger/main/log-management/classes/LogEntryHandler.cls +++ b/nebula-logger/main/log-management/classes/LogEntryHandler.cls @@ -12,7 +12,7 @@ public without sharing class LogEntryHandler extends LoggerSObjectHandler { @testVisible private List logEntries { get { - return (List) this.records; + return (List) this.triggerNew; } } diff --git a/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls b/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls index 9f9882800..60bf9f06b 100644 --- a/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls +++ b/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls @@ -31,109 +31,223 @@ public abstract class LoggerSObjectHandlerPlugin { Map triggerOldMap ); + // TODO finish parameter methods in a future release /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `String` + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Boolean` * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `String` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + * @return The `Boolean` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled */ - protected String getStringParameter(String parameterDeveloperName) { - return this.getParameter(parameterDeveloperName)?.Value__c; - } + // protected Boolean getBooleanParameter(String parameterDeveloperName) { + // return Boolean.valueOf(this.getStringParameter(parameterDeveloperName)); + // } /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Boolean` + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Boolean` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled */ - protected Boolean getBooleanParameter(String parameterDeveloperName) { - return Boolean.valueOf(this.getStringParameter(parameterDeveloperName)); - } + // protected List getBooleanListParameter(String parameterDeveloperName) { + // return (List) this.castParameter(parameterDeveloperName, List.class); + // } /** * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Date` * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Date` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + * @return The `Date` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled */ - protected Date getDateParameter(String parameterDeveloperName) { - return Date.valueOf(this.getStringParameter(parameterDeveloperName)); - } + // protected Date getDateParameter(String parameterDeveloperName) { + // return Date.valueOf(this.getStringParameter(parameterDeveloperName)); + // } + + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled + */ + // protected List getDateListParameter(String parameterDeveloperName) { + // return (List) this.castParameter(parameterDeveloperName, List.class); + // } /** * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Datetime` * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Datetime` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + * @return The `Datetime` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled */ - protected Datetime getDatetimeParameter(String parameterDeveloperName) { - return Datetime.valueOf(this.getStringParameter(parameterDeveloperName)); - } + // protected Datetime getDatetimeParameter(String parameterDeveloperName) { + // return Datetime.valueOf(this.getStringParameter(parameterDeveloperName)); + // } + + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled + */ + // protected List getDatetimeListParameter(String parameterDeveloperName) { + // return (List) this.castParameter(parameterDeveloperName, List.class); + // } /** * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Decimal` * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Decimal` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + * @return The `Decimal` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled */ - protected Decimal getDecimalParameter(String parameterDeveloperName) { - return Decimal.valueOf(this.getStringParameter(parameterDeveloperName)); - } + // protected Decimal getDecimalParameter(String parameterDeveloperName) { + // return Decimal.valueOf(this.getStringParameter(parameterDeveloperName)); + // } + + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled + */ + // protected List getDecimalListParameter(String parameterDeveloperName) { + // return (List) this.castParameter(parameterDeveloperName, List.class); + // } /** * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Double` * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Double` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + * @return The `Double` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled */ - protected Double getDoubleParameter(String parameterDeveloperName) { - return Double.valueOf(this.getStringParameter(parameterDeveloperName)); - } + // protected Double getDoubleParameter(String parameterDeveloperName) { + // return Double.valueOf(this.getStringParameter(parameterDeveloperName)); + // } /** * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Id` * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Id` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + * @return The `Id` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled */ - protected Id getIdParameter(String parameterDeveloperName) { - return Id.valueOf(this.getStringParameter(parameterDeveloperName)); - } + // protected Id getIdParameter(String parameterDeveloperName) { + // return Id.valueOf(this.getStringParameter(parameterDeveloperName)); + // } + + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled + */ + // protected List getIdListParameter(String parameterDeveloperName) { + // return (List) this.castParameter(parameterDeveloperName, List.class); + // } /** * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Integer` * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Integer` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + * @return The `Integer` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled */ - protected Integer getIntegerParameter(String parameterDeveloperName) { - return Integer.valueOf(this.getStringParameter(parameterDeveloperName)); - } + // protected Integer getIntegerParameter(String parameterDeveloperName) { + // return Integer.valueOf(this.getStringParameter(parameterDeveloperName)); + // } + + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled + */ + // protected List getIntegerListParameter(String parameterDeveloperName) { + // return (List) this.castParameter(parameterDeveloperName, List.class); + // } /** * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Long` * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Long` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + * @return The `Long` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled */ - protected Long getLongParameter(String parameterDeveloperName) { - return Long.valueOf(this.getStringParameter(parameterDeveloperName)); - } + // protected Long getLongParameter(String parameterDeveloperName) { + // return Long.valueOf(this.getStringParameter(parameterDeveloperName)); + // } + + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled + */ + // protected List getLongListParameter(String parameterDeveloperName) { + // return (List) this.castParameter(parameterDeveloperName, List.class); + // } /** * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as an `Object` * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Object` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + * @return The `Object` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled */ - protected Object getObjectParameter(String parameterDeveloperName) { - return (Object) this.getStringParameter(parameterDeveloperName); - } + // protected Object getObjectParameter(String parameterDeveloperName) { + // return (Object) this.getStringParameter(parameterDeveloperName); + // } + + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as an `List` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled + */ + // protected List getObjectListParameter(String parameterDeveloperName) { + // return (List) this.castParameter(parameterDeveloperName, List.class); + // } /** * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `SObject` * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `SObject` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + * @return The `SObject` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled */ - protected SObject getSObjectParameter(String parameterDeveloperName) { - return (SObject) JSON.deserialize(this.getStringParameter(parameterDeveloperName), SObject.class); - } + // protected SObject getSObjectParameter(String parameterDeveloperName) { + // return (SObject) JSON.deserialize(this.getStringParameter(parameterDeveloperName), SObject.class); + // } + + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled + */ + // protected List getSObjectListParameter(String parameterDeveloperName) { + // return (List) this.castParameter(parameterDeveloperName, List.class); + // } + + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `String` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `String` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled + */ + // Since the Value__c field is a string field, this method is used internally by the other parameter methods + // protected String getStringParameter(String parameterDeveloperName) { + // return this.getParameter(parameterDeveloperName)?.Value__c; + // } + + /** + * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` + * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` + * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled + */ + // protected List getStringListParameter(String parameterDeveloperName) { + // return (List) this.castParameter(parameterDeveloperName, List.class); + // } /** * @description Returns the matching instance of `LoggerSObjectHandlerPluginParameter__mdt` * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, or null if not found + * @return The matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, + * or null when not found or disabled */ protected LoggerSObjectHandlerPluginParameter__mdt getParameter(String parameterDeveloperName) { LoggerSObjectHandlerPluginParameter__mdt parameter = LoggerSObjectHandlerPluginParameter__mdt.getInstance(parameterDeveloperName); @@ -144,4 +258,9 @@ public abstract class LoggerSObjectHandlerPlugin { return parameter; } + + // private Object castParameter(String parameterDeveloperName, Type dataType) { + // // return JSON.deserialize(this.getStringParameter(parameterDeveloperName), dataType); + // return JSON.deserialize(this.getParameter(parameterDeveloperName)?.Value__c, dataType); + // } } From 7d4ca50d760ebabc7383d3162b47e4fdb279b3c7 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 14 Jun 2021 16:20:51 -0700 Subject: [PATCH 68/82] Finished (basic) Slack tests + created plugin unlocked package + created separate perm set for custom field access --- README.md | 2 +- nebula-logger-plugins/Slack/README.md | 2 + .../Slack/classes/SlackLoggerPlugin.cls | 29 +++- .../Slack/classes/SlackLoggerPlugin_Tests.cls | 141 +++++++++++++----- .../LoggerLogViewer.permissionset-meta.xml | 14 -- ...erSlackPluginAdmin.permissionset-meta.xml} | 3 +- sfdx-project.json | 13 +- 7 files changed, 142 insertions(+), 62 deletions(-) delete mode 100644 nebula-logger-plugins/Slack/permissionsets/LoggerLogViewer.permissionset-meta.xml rename nebula-logger-plugins/Slack/permissionsets/{LoggerAdmin.permissionset-meta.xml => LoggerSlackPluginAdmin.permissionset-meta.xml} (77%) diff --git a/README.md b/README.md index d7c2e3f39..40b23e9c2 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Designed for Salesforce admins, developers & architects. A robust logger for Apex, Flow, Process Builder & Integrations. -[![Install Unlocked Package](./content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FKqQAM) +[![Install Unlocked Package](./content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FLAQA2) [![Install Managed Package](./content/btn-install-managed-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FKbQAM) [![Deploy Unpackaged Metadata](./content/btn-deploy-unpackaged-metadata.png)](https://githubsfdeploy.herokuapp.com/?owner=jongpie&repo=NebulaLogger&ref=main) [![View Documentation](./content/btn-view-documentation.png)](https://jongpie.github.io/NebulaLogger/) diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index 31a2b9c7d..a221b2537 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -2,6 +2,8 @@ Adds a Slack integration for Nebula Logger. Any logs with log entries that meet a certain (configurable) logging level will automatically be posted to your Slack channel via an asynchronous `Queueable` job. +[![Install Unlocked Package](./content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FLoQAM) + ![Slack plugin: notification](./../../content/slack-plugin-notification.png) --- diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index 71de44667..defb086dc 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -12,15 +12,38 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi private static final String PARAM_ENDPOINT = 'SlackEndpoint'; private static final String PARAM_NOTIFICATION_LOGGING_LEVEL_NAME = 'SlackNotificationLoggingLevel'; + @testVisible + private static String endpoint; + @testVisible + private static LoggingLevel notificationLoggingLevel; + + static { + endpoint = LoggerSObjectHandlerPluginParameter__mdt.getInstance(PARAM_ENDPOINT)?.Value__c; + + LoggerSObjectHandlerPluginParameter__mdt loggingLevelParameter = LoggerSObjectHandlerPluginParameter__mdt.getInstance(PARAM_NOTIFICATION_LOGGING_LEVEL_NAME); + if (loggingLevelParameter != null && loggingLevelParameter.IsEnabled__c == true) { + String notificationLoggingLevelName = loggingLevelParameter?.Value__c; + notificationLoggingLevel = Logger.getLoggingLevel(notificationLoggingLevelName); + } + } + + // Member variables + // @testVisible + // private String endpoint; + // private LoggingLevel notificationLoggingLevel; + private List logs; + // Constructors public SlackLoggerPlugin() { } private SlackLoggerPlugin(List unsentLogs) { + this(); this.logs = unsentLogs; } + // Instance methods public override void execute( TriggerOperation triggerOperationType, List triggerNew, @@ -83,13 +106,10 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi } private void flagLogsForSlackNotification() { - String notificationLoggingLevelName = this.getParameter(PARAM_NOTIFICATION_LOGGING_LEVEL_NAME)?.Value__c; - - if (String.isBlank(notificationLoggingLevelName)) { + if (notificationLoggingLevel == null) { return; } - LoggingLevel notificationLoggingLevel = Logger.getLoggingLevel(notificationLoggingLevelName); for (Log__c log : this.logs) { if (log.MaxLogEntryLoggingLevelOrdinal__c >= notificationLoggingLevel.ordinal()) { log.SendSlackNotification__c = true; @@ -151,7 +171,6 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi } private HttpRequest createSlackHttpRequest() { - String endpoint = this.getParameter(PARAM_ENDPOINT)?.Value__c; System.debug('endpoint==' + endpoint); HttpRequest request = new HttpRequest(); diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin_Tests.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin_Tests.cls index 68248c986..5804e3dff 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin_Tests.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin_Tests.cls @@ -3,6 +3,8 @@ // See LICENSE file or go to https://github.com/jongpie/NebulaLogger for full license details. // //------------------------------------------------------------------------------------------------// +// TODO: need to improve plugin framework to make it easier for plugins to test by making it easier +// to mock CMDT records & instances of LoggerSObjectHandlerPlugin @isTest private class SlackLoggerPlugin_Tests { public class SuccessCalloutMock implements HttpCalloutMock { @@ -23,73 +25,144 @@ private class SlackLoggerPlugin_Tests { } } + static void mockConfigurations(LoggingLevel notificationLoggingLevel) { + // Set the plugin's parameters + LoggerSObjectHandlerPlugin__mdt slackPluginConfig = new LoggerSObjectHandlerPlugin__mdt( + IsEnabled__c = true, + PluginApiName__c = SlackLoggerPlugin.class.getName(), + PluginType__c = 'Apex' + ); + LoggerSObjectHandler.pluginsBySObjectType = new Map>{ + Schema.Log__c.SObjectType => new List{ slackPluginConfig } + }; + + // Set the plugin's internal variables + SlackLoggerPlugin.endpoint = 'https://fake.slack.com/'; + SlackLoggerPlugin.notificationLoggingLevel = notificationLoggingLevel; + } + static void verifyLogEntryCountEquals(Integer expectedCount) { List existingLogEntries = [SELECT Id FROM LogEntry__c]; System.assertEquals(expectedCount, existingLogEntries.size()); } + static List queryLogs() { + return [ + SELECT + Id, + MaxLogEntryLoggingLevelOrdinal__c, + SendSlackNotification__c, + SlackNotificationDate__c, + ( + SELECT Id, LoggingLevel__c, Message__c + FROM LogEntries__r + WHERE LoggingLevelOrdinal__c >= :LoggingLevel.WARN.ordinal() + ORDER BY Timestamp__c DESC + LIMIT 1 + ) + FROM Log__c + ]; + } + @isTest - static void it_should_push_a_debug_log_entry_and_update_push_date() { + static void it_should_push_a_log_when_logging_level_is_met() { + SuccessCalloutMock calloutMock = new SuccessCalloutMock(); + verifyLogEntryCountEquals(0); - Log__c log = new Log__c(SendSlackNotification__c = false, TransactionId__c = '1234'); + Log__c log = new Log__c(LoggedBy__c = UserInfo.getUserId(), SendSlackNotification__c = false, TransactionId__c = '1234'); insert log; - LoggingLevel logEntryLoggingLevel = LoggingLevel.DEBUG; + LoggingLevel logEntryLoggingLevel = LoggingLevel.WARN; LogEntry__c logEntry = new LogEntry__c( Log__c = log.Id, LoggingLevel__c = logEntryLoggingLevel.name(), - LoggingLevelOrdinal__c = logEntryLoggingLevel.ordinal() + LoggingLevelOrdinal__c = logEntryLoggingLevel.ordinal(), + Timestamp__c = System.now() ); insert logEntry; verifyLogEntryCountEquals(1); - log = [SELECT Id, MaxLogEntryLoggingLevelOrdinal__c, SendSlackNotification__c, SlackNotificationDate__c FROM Log__c]; + List logs = queryLogs(); + System.assertEquals(1, logs.size()); + log = logs.get(0); + + System.assertEquals(1, log.LogEntries__r.size()); System.assertEquals(false, log.SendSlackNotification__c); System.assertEquals(null, log.SlackNotificationDate__c); Test.startTest(); - Test.setMock(HttpCalloutMock.class, new SuccessCalloutMock()); + Test.setMock(HttpCalloutMock.class, calloutMock); - new SlackLoggerPlugin().execute(TriggerOperation.BEFORE_UPDATE, new List{ log }, null, null, null); - System.assertEquals(true, log.SendSlackNotification__c); + // Load the mock configurations - the plugin framework won't load actual CMDT records during tests + mockConfigurations(logEntryLoggingLevel); + System.assert(logEntryLoggingLevel.ordinal() >= SlackLoggerPlugin.notificationLoggingLevel.ordinal()); - new SlackLoggerPlugin().execute(TriggerOperation.AFTER_UPDATE, new List{ log }, null, null, null); - // log = [SELECT Id, MaxLogEntryLoggingLevelOrdinal__c, SendSlackNotification__c, SlackNotificationDate__c FROM Log__c]; + // Update the records to trigger the handler framework, which will then run the Slack plugin + update log; + + // Verify that the internal queueable job has been enqueued + System.assertEquals(1, Limits.getAsyncCalls()); + + // Stop the test so the internal queueable job runs + Test.stopTest(); + + log = [SELECT Id, MaxLogEntryLoggingLevelOrdinal__c, SendSlackNotification__c, SlackNotificationDate__c FROM Log__c]; System.assertEquals(true, log.SendSlackNotification__c); System.assertNotEquals(null, log.SlackNotificationDate__c); System.assertEquals(System.today(), log.SlackNotificationDate__c.date()); - - Test.stopTest(); } - // @isTest - // static void it_should_not_push_a_log_entry_when_configured_level_not_met() { - // verifyLogEntryCountEquals(0); - // Logger.warn('testing Slack integration'); - // Logger.saveLog(); - // Test.getEventBus().deliver(); - // verifyLogEntryCountEquals(1); + @isTest + static void it_should_not_push_a_log_when_logging_level_is_not_met() { + SuccessCalloutMock calloutMock = new SuccessCalloutMock(); - // // To make sure that Slack push is not triggered, we need to update a field on the parent Log__c - // Log__c log = [SELECT Id, SendSlackNotification__c FROM Log__c]; - // log.SendSlackNotification__c = false; - // update log; + verifyLogEntryCountEquals(0); - // LogEntry__c logEntry = [SELECT Id, Log__r.SendSlackNotification__c, Log__r.SlackNotificationDate__c FROM LogEntry__c]; - // System.assertEquals(false, logEntry.Log__r.SendSlackNotification__c); - // System.assertEquals(null, logEntry.Log__r.SlackNotificationDate__c); + Log__c log = new Log__c(LoggedBy__c = UserInfo.getUserId(), SendSlackNotification__c = false, TransactionId__c = '1234'); + insert log; - // Test.startTest(); - // Test.setMock(HttpCalloutMock.class, new SuccessCalloutMock()); + LoggingLevel logEntryLoggingLevel = LoggingLevel.WARN; + LogEntry__c logEntry = new LogEntry__c( + Log__c = log.Id, + LoggingLevel__c = logEntryLoggingLevel.name(), + LoggingLevelOrdinal__c = logEntryLoggingLevel.ordinal(), + Timestamp__c = System.now() + ); + insert logEntry; - // Database.executeBatch(new SlackLoggerPlugin()); + verifyLogEntryCountEquals(1); - // Test.stopTest(); + List logs = queryLogs(); + System.assertEquals(1, logs.size()); + log = logs.get(0); - // logEntry = [SELECT Id, Log__r.SendSlackNotification__c, Log__r.SlackNotificationDate__c FROM LogEntry__c]; - // System.assertEquals(false, logEntry.Log__r.SendSlackNotification__c); - // System.assertEquals(null, logEntry.Log__r.SlackNotificationDate__c); - // } + System.assertEquals(1, log.LogEntries__r.size()); + System.assertEquals(false, log.SendSlackNotification__c); + System.assertEquals(null, log.SlackNotificationDate__c); + + Test.startTest(); + Test.setMock(HttpCalloutMock.class, calloutMock); + + // Load the mock configurations - the plugin framework won't load actual CMDT records during tests + LoggingLevel slackLoggingLevel = LoggingLevel.ERROR; + System.assert(logEntryLoggingLevel.ordinal() < slackLoggingLevel.ordinal()); + mockConfigurations(slackLoggingLevel); + System.assert(logEntryLoggingLevel.ordinal() < SlackLoggerPlugin.notificationLoggingLevel.ordinal()); + + // Update the records to trigger the handler framework, which will then run the Slack plugin + update log; + + // Verify that the internal queueable job has been enqueued + System.assertEquals(0, Limits.getAsyncCalls()); + + // Stop the test so the internal queueable job runs + Test.stopTest(); + + log = queryLogs().get(0); + System.assertEquals(1, log.LogEntries__r.size()); + System.assertEquals(false, log.SendSlackNotification__c); + System.assertEquals(null, log.SlackNotificationDate__c); + } } diff --git a/nebula-logger-plugins/Slack/permissionsets/LoggerLogViewer.permissionset-meta.xml b/nebula-logger-plugins/Slack/permissionsets/LoggerLogViewer.permissionset-meta.xml deleted file mode 100644 index 058e922b8..000000000 --- a/nebula-logger-plugins/Slack/permissionsets/LoggerLogViewer.permissionset-meta.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - false - Log__c.SendSlackNotification__c - true - - - false - Log__c.SlackNotificationDate__c - true - - - diff --git a/nebula-logger-plugins/Slack/permissionsets/LoggerAdmin.permissionset-meta.xml b/nebula-logger-plugins/Slack/permissionsets/LoggerSlackPluginAdmin.permissionset-meta.xml similarity index 77% rename from nebula-logger-plugins/Slack/permissionsets/LoggerAdmin.permissionset-meta.xml rename to nebula-logger-plugins/Slack/permissionsets/LoggerSlackPluginAdmin.permissionset-meta.xml index a866655e2..9db9ff4d0 100644 --- a/nebula-logger-plugins/Slack/permissionsets/LoggerAdmin.permissionset-meta.xml +++ b/nebula-logger-plugins/Slack/permissionsets/LoggerSlackPluginAdmin.permissionset-meta.xml @@ -1,5 +1,6 @@ + Provides additional access for the Logger Slack plugin true Log__c.SendSlackNotification__c @@ -10,5 +11,5 @@ Log__c.SlackNotificationDate__c true - + diff --git a/sfdx-project.json b/sfdx-project.json index 5e9fba436..66faf97b2 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -10,7 +10,7 @@ "definitionFile": "config/project-scratch-def-with-experience-cloud.json", "versionName": "Logger Plugin Framework", "versionNumber": "4.5.0.0", - "versionDescription": "Easily add or install plugins that enhance the Log__c and LogEntry__c objects, using Apex or Flow", + "versionDescription": "Easily build or install plugins that enhance the Log__c and LogEntry__c objects, using Apex or Flow", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases" }, { @@ -18,8 +18,7 @@ "path": "nebula-logger-plugins/Slack", "dependencies": [ { - "package": "Nebula Logger - Unlocked Package", - "versionNumber": "4.5.0.LATEST" + "package": "Nebula Logger - Unlocked Package@4.5.0-0-logger-plugin-framework" } ], "versionNumber": "0.9.0.0" @@ -36,8 +35,8 @@ "Nebula Logger - Unlocked Package@4.4.4-0-timestamp-bugfix": "04t5Y0000027FIQQA2", "Nebula Logger - Unlocked Package@4.4.5-0-log-batch-purger-bugfixes": "04t5Y0000027FIVQA2", "Nebula Logger - Unlocked Package@4.4.6-0-new-save-method-synchronous_dml": "04t5Y0000027FJdQAM", - "Nebula Logger - Unlocked Package@4.5.0-0-logger-sobject-handler-plugins": "04t5Y0000027FKWQA2", - "Nebula Logger - Unlocked Package@4.5.0-0": "04t5Y0000027FKqQAM", - "Nebula Logger - Slack Plugin": "0Ho5Y000000TNKoSAO" + "Nebula Logger - Unlocked Package@4.5.0-0-logger-plugin-framework": "04t5Y0000027FLAQA2", + "Nebula Logger - Slack Plugin": "0Ho5Y000000TNKoSAO", + "Nebula Logger - Slack Plugin@0.9.0-0-beta-release": "04t5Y0000027FLoQAM" } -} +} \ No newline at end of file From 3910df6d69fe0a9714ba95667c444a76a093ee11 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 14 Jun 2021 16:23:18 -0700 Subject: [PATCH 69/82] Fixed plugin button image in README.me --- .github/workflows/deploy.yml | 1 + nebula-logger-plugins/Slack/README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ca35a4219..1434f46bb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -16,6 +16,7 @@ on: - 'LICENSE' - 'package.json' - 'README.md' + - './**/README.md' - 'sfdx-project.json' jobs: diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index a221b2537..16bdd3026 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -2,7 +2,7 @@ Adds a Slack integration for Nebula Logger. Any logs with log entries that meet a certain (configurable) logging level will automatically be posted to your Slack channel via an asynchronous `Queueable` job. -[![Install Unlocked Package](./content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FLoQAM) +[![Install Unlocked Package](./../../content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FLoQAM) ![Slack plugin: notification](./../../content/slack-plugin-notification.png) From 4e014f75c28d3aef0ea744d81ffe7fc59fd49e67 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 15 Jun 2021 10:24:45 -0700 Subject: [PATCH 70/82] Added extra test class LoggerSObjectHandlerPlugin_Tests --- README.md | 6 +-- .../LoggerSObjectHandlerPlugin.md | 6 +++ .../classes/LoggerSObjectHandlerPlugin.cls | 26 +++++++----- .../LoggerSObjectHandlerPlugin_Tests.cls | 42 +++++++++++++++++++ ...gerSObjectHandlerPlugin_Tests.cls-meta.xml | 5 +++ 5 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 nebula-logger/tests/plugin-framework/classes/LoggerSObjectHandlerPlugin_Tests.cls create mode 100644 nebula-logger/tests/plugin-framework/classes/LoggerSObjectHandlerPlugin_Tests.cls-meta.xml diff --git a/README.md b/README.md index 40b23e9c2..6dce5499d 100644 --- a/README.md +++ b/README.md @@ -357,11 +357,11 @@ If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, 2. `Output` parameter `updatedTriggerNew` - If your Flow makes any updates to the collection of records, you should return a record collection containing the updated records 3. `Input` parameter `triggerOld` - The list of logger records as they exist in the datatabase -- Apex plugins: your Apex class should implement `LoggerSObjectHandlerPlugin`. For example: +- Apex plugins: your Apex class should extend the abstract class `LoggerSObjectHandlerPlugin`. For example: ```java - public class ExamplePlugin implements LoggerSObjectHandlerPlugin { - public void execute( + public class ExamplePlugin extends LoggerSObjectHandlerPlugin { + public override void execute( TriggerOperation triggerOperationType, List triggerNew, Map triggerNewMap, diff --git a/docs/plugin-framework/LoggerSObjectHandlerPlugin.md b/docs/plugin-framework/LoggerSObjectHandlerPlugin.md index 3f988ed03..31234a243 100644 --- a/docs/plugin-framework/LoggerSObjectHandlerPlugin.md +++ b/docs/plugin-framework/LoggerSObjectHandlerPlugin.md @@ -8,6 +8,12 @@ Abstract class used to create custom Apex plugins to execute for all trigger ope --- +### Constructors + +#### `LoggerSObjectHandlerPlugin()` + +## All instances of `LoggerSObjectHandlerPlugin` are dynamically created, which requires aparameterless constructor + ### Methods #### `execute(TriggerOperation triggerOperationType,List triggerNew,Map triggerNewMap,List triggerOld,Map triggerOldMap)` → `void` diff --git a/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls b/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls index 60bf9f06b..0a8d8db77 100644 --- a/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls +++ b/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls @@ -7,10 +7,16 @@ * @group Plugin Framework * @description Abstract class used to create custom Apex plugins to execute for all trigger operations on `Log__c` or `LogEntry__c` */ -// TODO: If possible, convert to `global` for the managed package - there are some additional platform limitations... -// ... and restrictions with making future changes to abstract classes & interfaces within managed packages... -// ... which could lead to a lot of problems, so for now/indefinitely, plugins will only work in the unlocked package +// TODO: If possible, convert to `global` for the managed package - there are some additional platform limitations +// and restrictions with making future changes to abstract classes & interfaces within managed packages +// which could lead to a lot of problems, so for now/indefinitely, plugins will only work in the unlocked package public abstract class LoggerSObjectHandlerPlugin { + /** + * @description All instances of `LoggerSObjectHandlerPlugin` are dynamically created, which requires aparameterless constructor + */ + public LoggerSObjectHandlerPlugin() { + } + /** * @description This method is the entry point for plugins to execute any custom logic. * It is automatically called by the logging system for any enabled plugins. @@ -249,15 +255,15 @@ public abstract class LoggerSObjectHandlerPlugin { * @return The matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, * or null when not found or disabled */ - protected LoggerSObjectHandlerPluginParameter__mdt getParameter(String parameterDeveloperName) { - LoggerSObjectHandlerPluginParameter__mdt parameter = LoggerSObjectHandlerPluginParameter__mdt.getInstance(parameterDeveloperName); + // protected LoggerSObjectHandlerPluginParameter__mdt getParameter(String parameterDeveloperName) { + // LoggerSObjectHandlerPluginParameter__mdt parameter = LoggerSObjectHandlerPluginParameter__mdt.getInstance(parameterDeveloperName); - if (parameter == null || parameter.IsEnabled__c == false) { - return null; - } + // if (parameter == null || parameter.IsEnabled__c == false) { + // return null; + // } - return parameter; - } + // return parameter; + // } // private Object castParameter(String parameterDeveloperName, Type dataType) { // // return JSON.deserialize(this.getStringParameter(parameterDeveloperName), dataType); diff --git a/nebula-logger/tests/plugin-framework/classes/LoggerSObjectHandlerPlugin_Tests.cls b/nebula-logger/tests/plugin-framework/classes/LoggerSObjectHandlerPlugin_Tests.cls new file mode 100644 index 000000000..b2b89b8be --- /dev/null +++ b/nebula-logger/tests/plugin-framework/classes/LoggerSObjectHandlerPlugin_Tests.cls @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------------------------// +// 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. // +//------------------------------------------------------------------------------------------------// + +@isTest +private class LoggerSObjectHandlerPlugin_Tests { + private static String PLUGIN_LOG_STATUS = 'On Hold'; + + public class ExamplePlugin extends LoggerSObjectHandlerPlugin { + public override void execute( + TriggerOperation triggerOperationType, + List triggerNew, + Map triggerNewMap, + List triggerOld, + Map triggerOldMap + ) { + switch on triggerOperationType { + when BEFORE_INSERT { + for (Log__c log : (List) triggerNew) { + log.Status__c = PLUGIN_LOG_STATUS; + } + } + } + } + } + + @isTest + static void it_should_execute_plugin_logic() { + Log__c log = new Log__c(TransactionId__c = '1234'); + System.assertEquals(null, log.Status__c); + + Test.startTest(); + + ExamplePlugin plugin = new ExamplePlugin(); + plugin.execute(triggerOperation.BEFORE_INSERT, new List{ log }, null, null, null); + + Test.stopTest(); + + System.assertEquals(PLUGIN_LOG_STATUS, log.Status__c); + } +} diff --git a/nebula-logger/tests/plugin-framework/classes/LoggerSObjectHandlerPlugin_Tests.cls-meta.xml b/nebula-logger/tests/plugin-framework/classes/LoggerSObjectHandlerPlugin_Tests.cls-meta.xml new file mode 100644 index 000000000..482559c8b --- /dev/null +++ b/nebula-logger/tests/plugin-framework/classes/LoggerSObjectHandlerPlugin_Tests.cls-meta.xml @@ -0,0 +1,5 @@ + + + 51.0 + Active + From 69a7d6846d3b5d39ee09501d0654a8e73df03e29 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 15 Jun 2021 11:05:52 -0700 Subject: [PATCH 71/82] Changed some CMDT fields to DeveloperControlled --- .../fields/DataType__c.field-meta.xml | 2 +- .../fields/PluginApiName__c.field-meta.xml | 2 +- .../fields/PluginType__c.field-meta.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml index ec4dd1ada..e9bd11d40 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml @@ -3,7 +3,7 @@ DataType__c The expected data type of the parameter value false - SubscriberControlled + DeveloperControlled The expected data type of the parameter value true diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml index b8a7152ef..57c7c769d 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginApiName__c.field-meta.xml @@ -10,7 +10,7 @@ Flow: The API name of a Flow that supports these inputs: - triggerNew: record collection variable - triggerOld: record collection variable false - SubscriberControlled + DeveloperControlled The API name of the metadata to run, based on the Plugin Type Apex: The name of an Apex class that implements the interface LoggerSObjectHandlerPlugin diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml index ffea786d1..cf55ff8bd 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPlugin__mdt/fields/PluginType__c.field-meta.xml @@ -3,7 +3,7 @@ PluginType__c The type of plugin that the logging system should dynamically execute - Apex or Flow. false - SubscriberControlled + DeveloperControlled The type of plugin that the logging system should dynamically execute - Apex or Flow. true From b72c3cb3c730f91bf99f48e053a8c4b3a76c8172 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 15 Jun 2021 11:28:57 -0700 Subject: [PATCH 72/82] A little unrelated code cleanup in RelatedLogEntriesController --- .../classes/RelatedLogEntriesController.cls | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/nebula-logger/main/log-management/classes/RelatedLogEntriesController.cls b/nebula-logger/main/log-management/classes/RelatedLogEntriesController.cls index 8d9ef218e..fc60a4a1f 100644 --- a/nebula-logger/main/log-management/classes/RelatedLogEntriesController.cls +++ b/nebula-logger/main/log-management/classes/RelatedLogEntriesController.cls @@ -84,6 +84,7 @@ public with sharing class RelatedLogEntriesController { }; String logEntryQuery = 'SELECT {0} FROM {1} WHERE {2} = :recordId ORDER BY {3} LIMIT {4}'; logEntryQuery = String.format(logEntryQuery, queryTextReplacements); + System.debug('logEntryQuery==' + logEntryQuery); return (List) Database.query(logEntryQuery); } @@ -149,15 +150,13 @@ public with sharing class RelatedLogEntriesController { for (String fieldName : educatedGuesses) { Schema.SObjectField field = lookupSObjectType.getDescribe().fields.getMap().get(fieldName); - if (field == null) { - continue; - } - - Schema.DescribeFieldResult fieldDescribe = field.getDescribe(); + if (field != null) { + Schema.DescribeFieldResult fieldDescribe = field.getDescribe(); - if (fieldDescribe.isNameField()) { - displayFieldApiName = fieldDescribe.getName(); - break; + if (fieldDescribe.isNameField()) { + displayFieldApiName = fieldDescribe.getName(); + break; + } } } @@ -169,14 +168,7 @@ public with sharing class RelatedLogEntriesController { String tabIcon; for (Schema.DescribeTabSetResult tabSetResult : Schema.describeTabs()) { - if (tabIcon != null) { - break; - } - for (Schema.DescribeTabResult tabResult : tabSetResult.getTabs()) { - if (tabIcon != null) { - break; - } if (tabResult.getSObjectName() != sobjectName) { continue; } @@ -194,12 +186,6 @@ public with sharing class RelatedLogEntriesController { } } } - // Hardcoded exceptions - Salesforce doesn't return SVGs for these objects, so hardcoding is necessary - if (tabIcon == null && sobjectName == 'Asset') { - tabIcon = 'standard:maintenance_asset'; - } else if (tabIcon == null && sobjectName == 'AssetRelationship') { - tabIcon = 'standard:asset_relationship'; - } return tabIcon; } From cf6b17bf7a5cc0ef793b63eb441f1b831eb485c1 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 15 Jun 2021 17:26:17 -0700 Subject: [PATCH 73/82] Added CollectionType field on plugin param CMDT --- nebula-logger-plugins/Slack/README.md | 28 +++++++++++++------ ...rPluginParameter.SlackEndpoint.md-meta.xml | 4 +++ ....SlackNotificationLoggingLevel.md-meta.xml | 4 +++ .../listViews/SlackPlugin.listView-meta.xml | 1 + ...er Plugin Parameter Layout.layout-meta.xml | 4 +++ ...ject Handler Plugin Layout.layout-meta.xml | 1 + .../fields/CollectionType__c.field-meta.xml | 27 ++++++++++++++++++ .../fields/DataType__c.field-meta.xml | 12 -------- .../listViews/All.listView-meta.xml | 1 + .../listViews/AllDisabled.listView-meta.xml | 1 + .../listViews/AllEnabled.listView-meta.xml | 1 + 11 files changed, 64 insertions(+), 20 deletions(-) create mode 100644 nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/CollectionType__c.field-meta.xml diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index 16bdd3026..39d952b13 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -15,7 +15,7 @@ This plugin includes some add-on metadata for Logger to support the Slack integr 1. Apex class `SlackLoggerPlugin` and corresponding tests in `SlackLoggerPlugin_Tests` 2. Plugin configuration details stored in Logger's CMDT objects `LoggerSObjectHandlerPlugin__mdt` and `LoggerSObjectHandlerPluginParameter__mdt` 3. Custom fields `Log__c.SendSlackNotification__c` and `Log__c.SlackNotificationDate__c` -4. Field-level security (FLS) updates for the permission sets `LoggerAdmin` and `LoggerLogViewer` to provide access to the custom Slack fields +4. Field-level security (FLS) via a new permission sets `LoggerSlackPluginAdmin` to provide access to the custom Slack fields 5. Custom list views for the `Log__c` and `LoggerSObjectHandlerPluginParameter__mdt` objects 6. Remote site setting for Slack's API @@ -23,13 +23,25 @@ This plugin includes some add-on metadata for Logger to support the Slack integr ## Installation Steps -1. In Salesforce, ensure that you have the unlocked package version of Nebula Logger installed in your org. -2. In Salesforce, deploy the metadata for the Slack plugin for Logger. Currently, this has to be done by cloning/downloading the repo from GitHub and deploying yourself. An unlocked package will be released in the future to make this process much easier. -3. In Slack, create a new app in your Slack workspace and enable incoming webhooks for your app. -4. In Slack, create a new incoming webhook, and copy the webhook URL. -5. In Salesforce, go to Setup --> Custom Metadata Types --> Logger Plugin --> Slack (shown in screenshot below) and find the parameter 'Slack Endpoint'. Paste the Slack webhook URL into the `Value__c` field and save the Plugin Parameter record. -6. In Salesforce, set the desired logging level value for the Logger Plugin Parameter 'Slack Notification Logging Level` (shown in screenshot below). It controls which logging level (ERROR, WARN, INFO, DEBUG, FINE, FINER, or FINEST) will trigger the Slack notifications to be sent. +In order to use the Slack plugin, there are some configuration changes needed in both Slack and Salesforce + +### Slack setup + +Within Slack, you'll need to setup incoming webhooks to allow the Logger Slack plugin to create messages. The high-level steps are: + +1. Create a new app in your Slack workspace and enable incoming webhooks for your app. +2. Create a new incoming webhook for your app, and copy the webhook URL. This will be used in Salesforce (see below steps) + +Check out [Slack's webhooks documentation](https://api.slack.com/messaging/webhooks) for more details on how to setup incoming webhooks. + +### Salesforce setup + +1. Ensure that you have the unlocked package version of Nebula Logger installed in your org. +2. Deploy the metadata for the Slack plugin for Logger. Currently, this has to be done by cloning/downloading the repo from GitHub and deploying yourself. An unlocked package will be released in the future to make this process much easier. +3. Go to Setup --> Custom Metadata Types --> Logger Plugin --> Slack (shown in screenshot below). There are 2 parameters to configure (shown in screenshot below) + - Parameter 'Slack Endpoint' - Paste the Slack webhook URL into the `Value__c` field and save the Plugin Parameter record. + - Parameter 'Slack Notification Logging Level' - Set the desired logging level value that should trigger a Slack notification to be sent the Logger Plugin Parameter 'Slack Notification Logging Level` . It controls which logging level (ERROR, WARN, INFO, DEBUG, FINE, FINER, or FINEST) will trigger the Slack notifications to be sent. At this point, the Slack integration should now be setup & working - any new logs that meet the threshold logging level (step 6 above) will send a Slack notification. -![Slack plugin: configuration](./../../content/slack-plugin-configuration.png) \ No newline at end of file +![Slack plugin: configuration](./../../content/slack-plugin-configuration.png) diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml index 569703dc8..895b5d587 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackEndpoint.md-meta.xml @@ -2,6 +2,10 @@ false + + CollectionType__c + Single + DataType__c String diff --git a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackNotificationLoggingLevel.md-meta.xml b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackNotificationLoggingLevel.md-meta.xml index db1dfaf4d..7996b1dfd 100644 --- a/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackNotificationLoggingLevel.md-meta.xml +++ b/nebula-logger-plugins/Slack/customMetadata/LoggerSObjectHandlerPluginParameter.SlackNotificationLoggingLevel.md-meta.xml @@ -2,6 +2,10 @@ false + + CollectionType__c + Single + DataType__c String diff --git a/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackPlugin.listView-meta.xml b/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackPlugin.listView-meta.xml index 8377ef925..814bd63d2 100644 --- a/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackPlugin.listView-meta.xml +++ b/nebula-logger-plugins/Slack/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/SlackPlugin.listView-meta.xml @@ -5,6 +5,7 @@ DeveloperName SObjectHandlerPlugin__c IsEnabled__c + CollectionType__c DataType__c Value__c Description__c diff --git a/nebula-logger/main/plugin-framework/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml b/nebula-logger/main/plugin-framework/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml index 149a7114c..715ecc56a 100644 --- a/nebula-logger/main/plugin-framework/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml +++ b/nebula-logger/main/plugin-framework/layouts/LoggerSObjectHandlerPluginParameter__mdt-Logger SObject Handler Plugin Parameter Layout.layout-meta.xml @@ -33,6 +33,10 @@ true + + Required + CollectionType__c + Required DataType__c diff --git a/nebula-logger/main/plugin-framework/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml b/nebula-logger/main/plugin-framework/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml index ae333834e..527380dbe 100644 --- a/nebula-logger/main/plugin-framework/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml +++ b/nebula-logger/main/plugin-framework/layouts/LoggerSObjectHandlerPlugin__mdt-Logger SObject Handler Plugin Layout.layout-meta.xml @@ -104,6 +104,7 @@ MasterLabel DeveloperName IsEnabled__c + CollectionType__c DataType__c Value__c LoggerSObjectHandlerPluginParameter__mdt.SObjectHandlerPlugin__c diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/CollectionType__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/CollectionType__c.field-meta.xml new file mode 100644 index 000000000..c67d76d33 --- /dev/null +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/CollectionType__c.field-meta.xml @@ -0,0 +1,27 @@ + + + CollectionType__c + The expected collection type of the parameter. For example, String vs List<String> + false + DeveloperControlled + The expected collection type of the parameter. For example, String vs List<String> + + true + Picklist + + true + + false + + Single + true + + + + List + false + + + + + diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml index e9bd11d40..8fc10b649 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/fields/DataType__c.field-meta.xml @@ -67,18 +67,6 @@ false - - Blob - false - false - - - - Time - false - false - - diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml index 26bd68504..a0b6d841e 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/All.listView-meta.xml @@ -5,6 +5,7 @@ DeveloperName SObjectHandlerPlugin__c IsEnabled__c + CollectionType__c DataType__c Value__c Description__c diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllDisabled.listView-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllDisabled.listView-meta.xml index b6391d189..c048bc531 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllDisabled.listView-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllDisabled.listView-meta.xml @@ -4,6 +4,7 @@ MasterLabel DeveloperName SObjectHandlerPlugin__c + CollectionType__c DataType__c Value__c Description__c diff --git a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllEnabled.listView-meta.xml b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllEnabled.listView-meta.xml index 51aad8a69..37eaab911 100644 --- a/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllEnabled.listView-meta.xml +++ b/nebula-logger/main/plugin-framework/objects/LoggerSObjectHandlerPluginParameter__mdt/listViews/AllEnabled.listView-meta.xml @@ -4,6 +4,7 @@ MasterLabel DeveloperName SObjectHandlerPlugin__c + CollectionType__c DataType__c Value__c Description__c From 683dba78deabb73d10989d015e7a341f00865a33 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 15 Jun 2021 17:59:24 -0700 Subject: [PATCH 74/82] Slack plugin cleanup --- content/slack-plugin-configuration.png | Bin 109637 -> 102202 bytes nebula-logger-plugins/Slack/README.md | 10 +++++----- .../Slack/classes/SlackLoggerPlugin.cls | 9 ++------- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/content/slack-plugin-configuration.png b/content/slack-plugin-configuration.png index d8ad876339e9c82209ac62ddcdbbcecee5aef343..0149f7dbae6f9c1fd0eeb1534fd82997768d010a 100644 GIT binary patch literal 102202 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 z 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.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 diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index 39d952b13..cb8fbef57 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -15,7 +15,7 @@ This plugin includes some add-on metadata for Logger to support the Slack integr 1. Apex class `SlackLoggerPlugin` and corresponding tests in `SlackLoggerPlugin_Tests` 2. Plugin configuration details stored in Logger's CMDT objects `LoggerSObjectHandlerPlugin__mdt` and `LoggerSObjectHandlerPluginParameter__mdt` 3. Custom fields `Log__c.SendSlackNotification__c` and `Log__c.SlackNotificationDate__c` -4. Field-level security (FLS) via a new permission sets `LoggerSlackPluginAdmin` to provide access to the custom Slack fields +4. Field-level security (FLS) via a new permission set `LoggerSlackPluginAdmin` to provide access to the custom Slack fields 5. Custom list views for the `Log__c` and `LoggerSObjectHandlerPluginParameter__mdt` objects 6. Remote site setting for Slack's API @@ -37,11 +37,11 @@ Check out [Slack's webhooks documentation](https://api.slack.com/messaging/webho ### Salesforce setup 1. Ensure that you have the unlocked package version of Nebula Logger installed in your org. -2. Deploy the metadata for the Slack plugin for Logger. Currently, this has to be done by cloning/downloading the repo from GitHub and deploying yourself. An unlocked package will be released in the future to make this process much easier. -3. Go to Setup --> Custom Metadata Types --> Logger Plugin --> Slack (shown in screenshot below). There are 2 parameters to configure (shown in screenshot below) +2. Install the unlocked package for the Slack plugin. +3. Go to Setup --> Custom Metadata Types --> Logger Plugin --> Slack. There are 2 parameters to configure (shown in screenshot below) - Parameter 'Slack Endpoint' - Paste the Slack webhook URL into the `Value__c` field and save the Plugin Parameter record. - - Parameter 'Slack Notification Logging Level' - Set the desired logging level value that should trigger a Slack notification to be sent the Logger Plugin Parameter 'Slack Notification Logging Level` . It controls which logging level (ERROR, WARN, INFO, DEBUG, FINE, FINER, or FINEST) will trigger the Slack notifications to be sent. + - Parameter 'Slack Notification Logging Level' - Set the desired logging level value that should trigger a Slack notification to be sent the Logger Plugin Parameter 'Slack Notification Logging Level`. It controls which logging level (ERROR, WARN, INFO, DEBUG, FINE, FINER, or FINEST) will trigger the Slack notifications to be sent. -At this point, the Slack integration should now be setup & working - any new logs that meet the threshold logging level (step 6 above) will send a Slack notification. +At this point, the Slack integration should now be setup & working - any new logs that meet the specified notification logging level (step 6 above) will send a Slack notification. ![Slack plugin: configuration](./../../content/slack-plugin-configuration.png) diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index defb086dc..a839bd210 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -8,7 +8,7 @@ * @description Optional plugin that integrates with Slack to send alerts for important logs */ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugin implements Queueable, Database.AllowsCallouts { - // Constants used for loading configuration & parameters from custom metadata type objects + // Constants used for loading parameters from CMDT objects private static final String PARAM_ENDPOINT = 'SlackEndpoint'; private static final String PARAM_NOTIFICATION_LOGGING_LEVEL_NAME = 'SlackNotificationLoggingLevel'; @@ -27,11 +27,6 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi } } - // Member variables - // @testVisible - // private String endpoint; - // private LoggingLevel notificationLoggingLevel; - private List logs; // Constructors @@ -161,7 +156,7 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi ( SELECT Id, LoggingLevel__c, Message__c FROM LogEntries__r - WHERE LoggingLevelOrdinal__c >= :LoggingLevel.WARN.ordinal() + WHERE LoggingLevelOrdinal__c >= :notificationLoggingLevel.ordinal() ORDER BY Timestamp__c DESC LIMIT 1 ) From d18967a29d7e0aabefa3404271f76806cbf21723 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 15 Jun 2021 18:16:01 -0700 Subject: [PATCH 75/82] More details + cleanup in README.md --- README.md | 120 +++++++++++++++++++-------------- content/logger-console-app.png | Bin 0 -> 91717 bytes 2 files changed, 68 insertions(+), 52 deletions(-) create mode 100644 content/logger-console-app.png diff --git a/README.md b/README.md index 6dce5499d..f31a01c70 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,10 @@ Designed for Salesforce admins, developers & architects. A robust logger for Ape 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 -5. View related log entries on any record page by adding the 'Related Log Entries' component in App Builder +5. View related log entries on any Lighting SObject flexipage by adding the 'Related Log Entries' component in App Builder 6. Dynamically assign Topics to `Log__c` and `LogEntry__c` records for tagging/labeling your logs (not currently available in the managed package) -7. Event-Driven Integrations with [Platform Events](https://developer.salesforce.com/docs/atlas.en-us.platform_events.meta/platform_events/platform_events_intro.htm), an event-driven messaging architecture. External integrations can subscribe to log events using the `LogEntryEvent__e` object - see more details at [the Platform Events Developer Guide site](https://developer.salesforce.com/docs/atlas.en-us.platform_events.meta/platform_events/platform_events_subscribe_cometd.htm) +7. Plugin framework: easily build or install plugins that enhance the `Log__c` and `LogEntry__c` objects, using Apex or Flow +8. Event-Driven Integrations with [Platform Events](https://developer.salesforce.com/docs/atlas.en-us.platform_events.meta/platform_events/platform_events_intro.htm), an event-driven messaging architecture. External integrations can subscribe to log events using the `LogEntryEvent__e` object - see more details at [the Platform Events Developer Guide site](https://developer.salesforce.com/docs/atlas.en-us.platform_events.meta/platform_events/platform_events_subscribe_cometd.htm) 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/) @@ -347,15 +348,74 @@ For more details, check out the `LogMessage` class [documentation](https://jongp --- +## Log Management + +### Logger Console App + +The Logger Console app provides access to `Log__c` and `LogEntry__c` object tabs (for any users with the correct access). + +![Logger Console app](./content/logger-console-app.png) + +### Log's 'Manage' Quick Action + +To help development and support teams better manage logs (and any underlying code or config issues), some fields on `Log__c` are provided to track the owner, priority and status of a log. These fields are optional, but are helpful in critical environments (production, QA sandboxes, UAT sandboxes, etc.) for monitoring ongoing user activities. + +- All editable fields on `Log__c` can be updated via the 'Manage Log' quick action (shown below) + + ![Manage Log QuickAction](./content/manage-log-quickaction.png) + +- Additional fields are automatically set based on changes to `Log__c.Status__c` + - `Log__c.ClosedBy__c` - The user who closed the log + - `Log__c.ClosedDate__c` - The datetime that the log was closed + - `Log__c.IsClosed__c` - Indicates if the log is closed, based on the selected status (and associated config in the 'Log Status' custom metadata type) + - `Log__c.IsResolved__c` - Indicates if the log is resolved (meaning that it required analaysis/work, which has been completed). Only closed statuses can be considered resolved. This is also driven based on the selected status (and associated config in the 'Log Status' custom metadata type) +- To customize the statuses provided, simply update the picklist values for `Log__c.Status__c` and create/update corresponding records in the custom metadata type `LogStatus__mdt`. This custom metadata type controls which statuses are considerd closed and resolved. + +--- + +### View Related Log Entries on a Record Page + +Within App Builder, admins can add the 'Related Log Entries' lightning web component to any record page. Admins can also control which columns are displayed be creating & selecting a field set on `LogEntry__c` with the desired fields. + +- The component automatically shows any related log entries, based on `LogEntry__c.RecordId__c == :recordId` +- Users can search the list of log entries for a particular record using the component's built-insearch box. The component dynamically searches all related log entries using SOSL. +- Component automatically enforces Salesforce's security model + - Object-Level Security - Users without read access to `LogEntry__c` will not see the component + - Record-Level Security - Users will only see records that have been shared with them + - Field-Level Security - Users will only see the fields within the field set that they have access to + +![Related Log Entries](./content/relate-log-entries-lwc.png) + +--- + +## Deleting Old Logs + +Admins can easily delete old logs using 2 methods: list views or Apex batch jobs + +### Mass Deleting with List Views + +Salesforce (still) does not support mass deleting records out-of-the-box. There's been [an Idea for 11+ years](https://trailblazer.salesforce.com/ideaView?id=08730000000BqczAAC) about it, but it's still not standard functionality. A custom button is available on `Log__c` list views to provide mass deletion functionality. + +1. Users can select 1 or more `Log__c` records from the list view to choose which logs will be deleted + +![Mass Delete Selection](./content/log-mass-delete-selection.png) + +2. The button shows a Visualforce page `LogMassDelete` to confirm that the user wants to delete the records + +![Mass Delete Confirmation](./content/log-mass-delete-confirmation.png) + +--- + ## Beta Feature: Custom Plugin Framework for Log\_\_c and LogEntry\_\_c objects If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, you can leverage Apex or Flow to define "plugins" - the logger system will then automatically run the plugins after each trigger event (BEFORE_INSERT, BEFORE_UPDATE, AFTER_INSERT, AFTER_UPDATE, and so on). This framework makes it easy to build your own plugins, or deploy/install others' prebuilt packages, without having to modify the logging system directly. - Flow plugins: your Flow should be built as auto-launched Flows with these parameters: + 1. `Input` parameter `triggerOperationType` - The name of the current trigger operation (such as BEFORE_INSERT, BEFORE_UPDATE, etc.) 2. `Input` parameter `triggerNew` - The list of logger records being processed (`Log__c` or `LogEntry__c` records) - 2. `Output` parameter `updatedTriggerNew` - If your Flow makes any updates to the collection of records, you should return a record collection containing the updated records - 3. `Input` parameter `triggerOld` - The list of logger records as they exist in the datatabase + 3. `Output` parameter `updatedTriggerNew` - If your Flow makes any updates to the collection of records, you should return a record collection containing the updated records + 4. `Input` parameter `triggerOld` - The list of logger records as they exist in the datatabase - Apex plugins: your Apex class should extend the abstract class `LoggerSObjectHandlerPlugin`. For example: @@ -381,12 +441,14 @@ If you want to add your own automation to the `Log__c` or `LogEntry__c` objects, ``` Once you've created your Apex or Flow plugin(s), you will also need to configure the plugin: -- 'Logger Plugin' - use the custom metadata type `LoggerSObjectHandlerPlugin__mdt` to define your plugin, including the plugin type (Apex or Flow) and the API name of your plugin's Apex class or Flow -- 'Logger Plugin Parameter' - use the custom metadata type `LoggerSObjectHandlerPluginParameter__mdt` to define any configurable parameters needed for your plugin, such as environment-specific URLs and other similar configurations + +- 'Logger Plugin' - use the custom metadata type `LoggerSObjectHandlerPlugin__mdt` to define your plugin, including the plugin type (Apex or Flow) and the API name of your plugin's Apex class or Flow +- 'Logger Plugin Parameter' - use the custom metadata type `LoggerSObjectHandlerPluginParameter__mdt` to define any configurable parameters needed for your plugin, such as environment-specific URLs and other similar configurations ![Logger plugin: configuration](./content/slack-plugin-configuration.png) Note: the logger plugin framework is not available in the managed package due to some platform limitations & considerations with some of the underlying code. The unlocked package is recommended (instead of the managed package) when possible, including if you want to be able to leverage the plugin framework in your org. + ### Beta Plugin: Slack Integration The optional [Slack plugin](./nebula-logger-plugins/Slack/) leverages the Nebula Logger plugin framework to automatically send Slack notifications for logs that meet a certain (configurable) logging level. The plugin also serves as a functioning example of how to build your own plugin for Nebula Logger, such as how to: @@ -400,54 +462,8 @@ Check out the [Slack plugin](./nebula-logger-plugins/Slack/) for more details on ![Slack plugin: notification](./content/slack-plugin-notification.png) -## Managing Logs - -To help development and support teams better manage logs (and any underlying code or config issues), some fields on `Log__c` are provided to track the owner, priority and status of a log. These fields are optional, but are helpful in critical environments (production, QA sandboxes, UAT sandboxes, etc.) for monitoring ongoing user activities. - -- All editable fields on `Log__c` can be updated via the 'Manage Log' quick action (shown below) - - ![Manage Log QuickAction](./content/manage-log-quickaction.png) - -- Additional fields are automatically set based on changes to `Log__c.Status__c` - - `Log__c.ClosedBy__c` - The user who closed the log - - `Log__c.ClosedDate__c` - The datetime that the log was closed - - `Log__c.IsClosed__c` - Indicates if the log is closed, based on the selected status (and associated config in the 'Log Status' custom metadata type) - - `Log__c.IsResolved__c` - Indicates if the log is resolved (meaning that it required analaysis/work, which has been completed). Only closed statuses can be considered resolved. This is also driven based on the selected status (and associated config in the 'Log Status' custom metadata type) -- To customize the statuses provided, simply update the picklist values for `Log__c.Status__c` and create/update corresponding records in the custom metadata type `LogStatus__mdt`. This custom metadata type controls which statuses are considerd closed and resolved. - --- -## View Related Log Entries on a Record Page - -Within App Builder, admins can add the 'Related Log Entries' lightning web component to any record page. Admins can also control which columns are displayed be creating & selecting a field set on `LogEntry__c` with the desired fields. - -- The component automatically shows any related log entries, based on `LogEntry__c.RecordId__c == :recordId` -- Users can search the list of log entries for a particular record using the component's built-insearch box. The component dynamically searches all related log entries using SOSL. -- Component automatically enforces Salesforce's security model - - Object-Level Security - Users without read access to `LogEntry__c` will not see the component - - Record-Level Security - Users will only see records that have been shared with them - - Field-Level Security - Users will only see the fields within the field set that they have access to - -![Related Log Entries](./content/relate-log-entries-lwc.png) - ---- - -## Deleting Old Logs - -Admins can easily delete old logs using 2 methods: list views or Apex batch jobs - -### Mass Deleting with List Views - -Salesforce (still) does not support mass deleting records out-of-the-box. There's been [an Idea for 11+ years](https://trailblazer.salesforce.com/ideaView?id=08730000000BqczAAC) about it, but it's still not standard functionality. A custom button is available on `Log__c` list views to provide mass deletion functionality. - -1. Users can select 1 or more `Log__c` records from the list view to choose which logs will be deleted - -![Mass Delete Selection](./content/log-mass-delete-selection.png) - -2. The button shows a Visualforce page `LogMassDelete` to confirm that the user wants to delete the records - -![Mass Delete Confirmation](./content/log-mass-delete-confirmation.png) - ### Batch Deleting with Apex Jobs Two Apex classes are provided out-of-the-box to handle automatically deleting old logs diff --git a/content/logger-console-app.png b/content/logger-console-app.png new file mode 100644 index 0000000000000000000000000000000000000000..b060b1e62c25ef5b33a0d288e37bec4dae7f627a GIT binary patch literal 91717 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 z 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 Date: Tue, 15 Jun 2021 18:24:49 -0700 Subject: [PATCH 76/82] Fixed some formatting issues in README.md --- README.md | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index f31a01c70..db8761487 100644 --- a/README.md +++ b/README.md @@ -388,15 +388,15 @@ Within App Builder, admins can add the 'Related Log Entries' lightning web compo --- -## Deleting Old Logs +### Deleting Old Logs Admins can easily delete old logs using 2 methods: list views or Apex batch jobs -### Mass Deleting with List Views +##### Mass Deleting with List Views Salesforce (still) does not support mass deleting records out-of-the-box. There's been [an Idea for 11+ years](https://trailblazer.salesforce.com/ideaView?id=08730000000BqczAAC) about it, but it's still not standard functionality. A custom button is available on `Log__c` list views to provide mass deletion functionality. -1. Users can select 1 or more `Log__c` records from the list view to choose which logs will be deleted +1. Admins can select 1 or more `Log__c` records from the list view to choose which logs will be deleted ![Mass Delete Selection](./content/log-mass-delete-selection.png) @@ -404,6 +404,15 @@ Salesforce (still) does not support mass deleting records out-of-the-box. There' ![Mass Delete Confirmation](./content/log-mass-delete-confirmation.png) +#### Batch Deleting with Apex Jobs + +Two Apex classes are provided out-of-the-box to handle automatically deleting old logs + +1. `LogBatchPurger` - this batch Apex class will delete any `Log__c` records with `Log__c.LogRetentionDate__c <= System.today()`. + - By default, this field is populated with "TODAY + 14 DAYS" - the number of days to retain a log can be customized in `LoggerSettings__c`. + - Admins can also manually edit this field to change the retention date - or set it to null to prevent the log from being automatically deleted +2. `LogBatchPurgeScheduler` - this schedulable Apex class can be schedule to run `LogBatchPurger` on a daily or weekly basis + --- ## Beta Feature: Custom Plugin Framework for Log\_\_c and LogEntry\_\_c objects @@ -464,17 +473,6 @@ Check out the [Slack plugin](./nebula-logger-plugins/Slack/) for more details on --- -### Batch Deleting with Apex Jobs - -Two Apex classes are provided out-of-the-box to handle automatically deleting old logs - -1. `LogBatchPurger` - this batch Apex class will delete any `Log__c` records with `Log__c.LogRetentionDate__c <= System.today()`. - - By default, this field is populated with "TODAY + 14 DAYS" - the number of days to retain a log can be customized in `LoggerSettings__c`. - - Users can also manually edit this field to change the retention date - or set it to null to prevent the log from being automatically deleted -2. `LogBatchPurgeScheduler` - this schedulable Apex class can be schedule to run `LogBatchPurger` on a daily or weekly basis - ---- - ## Uninstalling/Removing Logger If you want to remove the unlocked or managed packages, you can do so by simply uninstalling them in your org under Setup --> Installed Packages. From a24f860a07f02967b347da74b3ef821ee431e0ae Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 15 Jun 2021 21:10:20 -0700 Subject: [PATCH 77/82] New pkg versions for ALL the packages --- .forceignore | 2 ++ .gitignore | 1 + README.md | 4 ++-- force-app/README.md | 4 ++++ nebula-logger-plugins/Slack/README.md | 10 ++++---- .../Slack/classes/SlackLoggerPlugin.cls | 15 ++++++++---- package.json | 4 +--- packages/managed-package/sfdx-project.json | 2 +- sfdx-project.json | 24 ++++++++++++------- 9 files changed, 42 insertions(+), 24 deletions(-) create mode 100644 force-app/README.md diff --git a/.forceignore b/.forceignore index 5556f53e9..04d1f4c5e 100644 --- a/.forceignore +++ b/.forceignore @@ -2,6 +2,8 @@ # More information: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm # +nebula-logger/main/default/** + # Directory/package-specific README files **/README.md diff --git a/.gitignore b/.gitignore index 619c37538..7fa3b5714 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .sfdx/ .vscode/ coverage/ +force-app/ nebula-logger/main/default/ nebula-logger/managed-package/ .vim-force.com diff --git a/README.md b/README.md index db8761487..d2b54a708 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ Designed for Salesforce admins, developers & architects. A robust logger for Apex, Flow, Process Builder & Integrations. -[![Install Unlocked Package](./content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FLAQA2) -[![Install Managed Package](./content/btn-install-managed-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FKbQAM) +[![Install Unlocked Package](./content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FM3QAM) +[![Install Managed Package](./content/btn-install-managed-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FLyQAM) [![Deploy Unpackaged Metadata](./content/btn-deploy-unpackaged-metadata.png)](https://githubsfdeploy.herokuapp.com/?owner=jongpie&repo=NebulaLogger&ref=main) [![View Documentation](./content/btn-view-documentation.png)](https://jongpie.github.io/NebulaLogger/) diff --git a/force-app/README.md b/force-app/README.md new file mode 100644 index 000000000..9a3cf127d --- /dev/null +++ b/force-app/README.md @@ -0,0 +1,4 @@ +This folder is used as the default folder by SFDX specifically so that no unwanted metadata accidentally gets added to the Nebula Logger packages. + +- Any metadata in this folder (`./force-app/`) can be deployed to your scratch org, but all files are ignored in `.gitignore` +- Any metadata that needs to be added to the unlocked package should be moved to the folder `./nebula-logger/` diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index cb8fbef57..c3f5106ae 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -2,7 +2,7 @@ Adds a Slack integration for Nebula Logger. Any logs with log entries that meet a certain (configurable) logging level will automatically be posted to your Slack channel via an asynchronous `Queueable` job. -[![Install Unlocked Package](./../../content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FLoQAM) +[![Install Unlocked Package](./../../content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5e0000005whPAAQ) ![Slack plugin: notification](./../../content/slack-plugin-notification.png) @@ -29,19 +29,19 @@ In order to use the Slack plugin, there are some configuration changes needed in Within Slack, you'll need to setup incoming webhooks to allow the Logger Slack plugin to create messages. The high-level steps are: -1. Create a new app in your Slack workspace and enable incoming webhooks for your app. +1. Create a new app in your Slack workspace and enable incoming webhooks for your app 2. Create a new incoming webhook for your app, and copy the webhook URL. This will be used in Salesforce (see below steps) Check out [Slack's webhooks documentation](https://api.slack.com/messaging/webhooks) for more details on how to setup incoming webhooks. ### Salesforce setup -1. Ensure that you have the unlocked package version of Nebula Logger installed in your org. -2. Install the unlocked package for the Slack plugin. +1. Ensure that you have the unlocked package version of Nebula Logger installed in your org +2. Install the unlocked package for the Slack plugin 3. Go to Setup --> Custom Metadata Types --> Logger Plugin --> Slack. There are 2 parameters to configure (shown in screenshot below) - Parameter 'Slack Endpoint' - Paste the Slack webhook URL into the `Value__c` field and save the Plugin Parameter record. - Parameter 'Slack Notification Logging Level' - Set the desired logging level value that should trigger a Slack notification to be sent the Logger Plugin Parameter 'Slack Notification Logging Level`. It controls which logging level (ERROR, WARN, INFO, DEBUG, FINE, FINER, or FINEST) will trigger the Slack notifications to be sent. -At this point, the Slack integration should now be setup & working - any new logs that meet the specified notification logging level (step 6 above) will send a Slack notification. +The Slack integration should now be setup & working - any new logs that meet the specified notification logging level (step 6 above) will send a Slack notification. ![Slack plugin: configuration](./../../content/slack-plugin-configuration.png) diff --git a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls index a839bd210..47b86c62c 100644 --- a/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls +++ b/nebula-logger-plugins/Slack/classes/SlackLoggerPlugin.cls @@ -20,7 +20,9 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi static { endpoint = LoggerSObjectHandlerPluginParameter__mdt.getInstance(PARAM_ENDPOINT)?.Value__c; - LoggerSObjectHandlerPluginParameter__mdt loggingLevelParameter = LoggerSObjectHandlerPluginParameter__mdt.getInstance(PARAM_NOTIFICATION_LOGGING_LEVEL_NAME); + LoggerSObjectHandlerPluginParameter__mdt loggingLevelParameter = LoggerSObjectHandlerPluginParameter__mdt.getInstance( + PARAM_NOTIFICATION_LOGGING_LEVEL_NAME + ); if (loggingLevelParameter != null && loggingLevelParameter.IsEnabled__c == true) { String notificationLoggingLevelName = loggingLevelParameter?.Value__c; notificationLoggingLevel = Logger.getLoggingLevel(notificationLoggingLevelName); @@ -161,7 +163,11 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi LIMIT 1 ) FROM Log__c - WHERE Id IN :this.logs AND SendSlackNotification__c = TRUE AND SlackNotificationDate__c = NULL + WHERE + Id IN :this.logs + AND MaxLogEntryLoggingLevelOrdinal__c >= :notificationLoggingLevel.ordinal() + AND SendSlackNotification__c = TRUE + AND SlackNotificationDate__c = NULL ]; } @@ -178,15 +184,14 @@ public without sharing class SlackLoggerPlugin extends LoggerSObjectHandlerPlugi private LogDto convertLog(Log__c log) { LogEntry__c lastLogEntry = log.LogEntries__r.get(0); - String messageText = 'Last Log Entry Message' - + '\n`' + lastLogEntry.LoggingLevel__c + ': ' + lastLogEntry.Message__c + '`'; + String messageText = 'Last Log Entry Message' + '\n`' + lastLogEntry.LoggingLevel__c + ': ' + lastLogEntry.Message__c + '`'; LogDto notification = new LogDto(); notification.author_link = Url.getSalesforceBaseUrl().toExternalForm() + '/' + log.LoggedBy__c; notification.author_name = log.LoggedBy__r.Username; notification.color = this.getNotificationColor(log); notification.fields = new List(); - notification.text = messageText;//Schema.Log__c.TotalLogEntries__c.getDescribe().getLabel() + ': `' + String.valueOf(log.TotalLogEntries__c) + '`'; + notification.text = messageText; //Schema.Log__c.TotalLogEntries__c.getDescribe().getLabel() + ': `' + String.valueOf(log.TotalLogEntries__c) + '`'; notification.title = log.Name; notification.title_link = Url.getSalesforceBaseUrl().toExternalForm() + '/' + log.Id; diff --git a/package.json b/package.json index 07554d085..d719ecda4 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,8 @@ "org:delete:noprompt": "sfdx force:org:delete --json --noprompt", "org:details": "sfdx force:org:display --json --verbose", "org:open": "sfdx force:org:open", - "package:version:create:managed": "pwsh .scripts/switch-to-managed-package-project-json.ps1 && sfdx force:package:version:create --json --package \"Nebula Logger - Managed Package\" --codecoverage --installationkeybypass --wait 30 && pwsh ./scripts/restore-unlocked-package-project-json.ps1", - "package:version:create:managed:skipvalidation": "pwsh ./scripts/switch-to-managed-package-project-json.ps1 && sfdx force:package:version:create --json --package \"Nebula Logger - Managed Package\" --skipvalidation --installationkeybypass --wait 30 && pwsh ./scripts/restore-unlocked-package-project-json.ps1", + "package:version:create:managed": "pwsh ./scripts/switch-to-managed-package-project-json.ps1 && sfdx force:package:version:create --json --package \"Nebula Logger - Managed Package\" --codecoverage --installationkeybypass --wait 30 && pwsh ./scripts/restore-unlocked-package-project-json.ps1", "package:version:create:unlocked": "sfdx force:package:version:create --json --package \"Nebula Logger - Unlocked Package\" --codecoverage --installationkeybypass --wait 30", - "package:version:create:unlocked:skipvalidation": "sfdx force:package:version:create --json --package \"Nebula Logger - Unlocked Package\" --skipvalidation --installationkeybypass --wait 30", "package:version:list": "sfdx force:package:version:list --json --verbose --orderby PatchVersion", "package:version:list:released": "sfdx force:package:version:list --json --verbose --released --orderby PatchVersion", "package:version:list:managed": "pwsh ./scripts/switch-to-managed-package-project-json.ps1 && sfdx force:package:version:list --json --verbose --orderby PatchVersion --packages \"Nebula Logger - Managed Package\" && pwsh ./scripts/restore-unlocked-package-project-json.ps1", diff --git a/packages/managed-package/sfdx-project.json b/packages/managed-package/sfdx-project.json index e56e959a7..945cbb874 100644 --- a/packages/managed-package/sfdx-project.json +++ b/packages/managed-package/sfdx-project.json @@ -22,6 +22,6 @@ "Nebula Logger - Managed Package@4.2.0-0-more-fields-and-methods": "04t5Y000000Xg4wQAC", "Nebula Logger - Managed Package@4.3.0-3-logger-console-app": "04t5Y000000YLDLQA4", "Nebula Logger - Managed Package@4.4.0-2-config-default-save-method": "04t5Y0000027FFgQAM", - "Nebula Logger - Managed Package@4.5.0-0-logger-sobject-handler-plugins": "04t5Y0000027FKbQAM" + "Nebula Logger - Managed Package@4.5.0-0-logger-plugin-framework": "04t5Y0000027FLyQAM" } } diff --git a/sfdx-project.json b/sfdx-project.json index 66faf97b2..e74af7836 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -3,10 +3,14 @@ "sfdcLoginUrl": "https://login.salesforce.com", "sourceApiVersion": "51.0", "packageDirectories": [ + { + "path": "force-app", + "default": true + }, { "package": "Nebula Logger - Unlocked Package", "path": "nebula-logger", - "default": true, + "default": false, "definitionFile": "config/project-scratch-def-with-experience-cloud.json", "versionName": "Logger Plugin Framework", "versionNumber": "4.5.0.0", @@ -14,17 +18,21 @@ "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases" }, { - "package": "Nebula Logger - Slack Plugin", "path": "nebula-logger-plugins/Slack", + "package": "Nebula Logger Plugin - Slack", "dependencies": [ { "package": "Nebula Logger - Unlocked Package@4.5.0-0-logger-plugin-framework" } ], - "versionNumber": "0.9.0.0" + "versionName": "Beta Release", + "versionNumber": "0.9.0.0", + "versionDescription": "New beta plugin for Nebula Logger", + "default": false }, { - "path": "extra-tests" + "path": "extra-tests", + "default": false } ], "packageAliases": { @@ -35,8 +43,8 @@ "Nebula Logger - Unlocked Package@4.4.4-0-timestamp-bugfix": "04t5Y0000027FIQQA2", "Nebula Logger - Unlocked Package@4.4.5-0-log-batch-purger-bugfixes": "04t5Y0000027FIVQA2", "Nebula Logger - Unlocked Package@4.4.6-0-new-save-method-synchronous_dml": "04t5Y0000027FJdQAM", - "Nebula Logger - Unlocked Package@4.5.0-0-logger-plugin-framework": "04t5Y0000027FLAQA2", - "Nebula Logger - Slack Plugin": "0Ho5Y000000TNKoSAO", - "Nebula Logger - Slack Plugin@0.9.0-0-beta-release": "04t5Y0000027FLoQAM" + "Nebula Logger - Unlocked Package@4.5.0-0-logger-plugin-framework": "04t5Y0000027FM8QAM", + "Nebula Logger Plugin - Slack": "0Ho5e000000oM3pCAE", + "Nebula Logger Plugin - Slack@0.9.0-0-beta-release": "04t5e0000005whPAAQ" } -} \ No newline at end of file +} From e468dcd46aa984bb6a58c4c83ff216d789d22f44 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 15 Jun 2021 21:11:32 -0700 Subject: [PATCH 78/82] Stupid README inconsistency --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d2b54a708..a1c965c47 100644 --- a/README.md +++ b/README.md @@ -392,7 +392,7 @@ Within App Builder, admins can add the 'Related Log Entries' lightning web compo Admins can easily delete old logs using 2 methods: list views or Apex batch jobs -##### Mass Deleting with List Views +#### Mass Deleting with List Views Salesforce (still) does not support mass deleting records out-of-the-box. There's been [an Idea for 11+ years](https://trailblazer.salesforce.com/ideaView?id=08730000000BqczAAC) about it, but it's still not standard functionality. A custom button is available on `Log__c` list views to provide mass deletion functionality. From 3727a52e21c4678646d23b11f3e340a47aa8e8a5 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Wed, 16 Jun 2021 22:01:25 -0700 Subject: [PATCH 79/82] Removed redundant text that was redundant Also, it was repetitive, too --- nebula-logger-plugins/Slack/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index c3f5106ae..b9fa01fe9 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -29,7 +29,7 @@ In order to use the Slack plugin, there are some configuration changes needed in Within Slack, you'll need to setup incoming webhooks to allow the Logger Slack plugin to create messages. The high-level steps are: -1. Create a new app in your Slack workspace and enable incoming webhooks for your app +1. Create a new app in your Slack workspace (or use an existing app, if you prefer) 2. Create a new incoming webhook for your app, and copy the webhook URL. This will be used in Salesforce (see below steps) Check out [Slack's webhooks documentation](https://api.slack.com/messaging/webhooks) for more details on how to setup incoming webhooks. From 7f4a84d6e9bde2e9ee1d31ea16411693489d2cab Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 19 Jun 2021 22:34:04 -0700 Subject: [PATCH 80/82] Updates to Slack README.md --- nebula-logger-plugins/Slack/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index b9fa01fe9..5bde2c615 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -39,7 +39,9 @@ Check out [Slack's webhooks documentation](https://api.slack.com/messaging/webho 1. Ensure that you have the unlocked package version of Nebula Logger installed in your org 2. Install the unlocked package for the Slack plugin 3. Go to Setup --> Custom Metadata Types --> Logger Plugin --> Slack. There are 2 parameters to configure (shown in screenshot below) - - Parameter 'Slack Endpoint' - Paste the Slack webhook URL into the `Value__c` field and save the Plugin Parameter record. + - Parameter 'Slack Endpoint' - You can configure this webhook in 1 of 2 ways: + - Easier but less secure: Paste the Slack webhook URL into the `Value__c` field and save the Plugin Parameter record. + - More secure: Create a new Named Credential, using the webhook URL as the endpoint. Within the Parameter 'Slack Endpoint', enter `callout:` into the `Value__c` field and save the Plugin Parameter record - Parameter 'Slack Notification Logging Level' - Set the desired logging level value that should trigger a Slack notification to be sent the Logger Plugin Parameter 'Slack Notification Logging Level`. It controls which logging level (ERROR, WARN, INFO, DEBUG, FINE, FINER, or FINEST) will trigger the Slack notifications to be sent. The Slack integration should now be setup & working - any new logs that meet the specified notification logging level (step 6 above) will send a Slack notification. From 4d139996eefdf41e339220797d1d91327b71320a Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sat, 19 Jun 2021 22:43:37 -0700 Subject: [PATCH 81/82] Removed commented-out code in LoggerSObjectHandlerPlugin --- .../classes/LoggerSObjectHandlerPlugin.cls | 233 ------------------ 1 file changed, 233 deletions(-) diff --git a/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls b/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls index 0a8d8db77..bbf36aefd 100644 --- a/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls +++ b/nebula-logger/main/plugin-framework/classes/LoggerSObjectHandlerPlugin.cls @@ -36,237 +36,4 @@ public abstract class LoggerSObjectHandlerPlugin { List triggerOld, Map triggerOldMap ); - - // TODO finish parameter methods in a future release - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Boolean` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Boolean` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected Boolean getBooleanParameter(String parameterDeveloperName) { - // return Boolean.valueOf(this.getStringParameter(parameterDeveloperName)); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected List getBooleanListParameter(String parameterDeveloperName) { - // return (List) this.castParameter(parameterDeveloperName, List.class); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Date` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Date` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected Date getDateParameter(String parameterDeveloperName) { - // return Date.valueOf(this.getStringParameter(parameterDeveloperName)); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected List getDateListParameter(String parameterDeveloperName) { - // return (List) this.castParameter(parameterDeveloperName, List.class); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Datetime` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Datetime` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected Datetime getDatetimeParameter(String parameterDeveloperName) { - // return Datetime.valueOf(this.getStringParameter(parameterDeveloperName)); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected List getDatetimeListParameter(String parameterDeveloperName) { - // return (List) this.castParameter(parameterDeveloperName, List.class); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Decimal` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Decimal` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected Decimal getDecimalParameter(String parameterDeveloperName) { - // return Decimal.valueOf(this.getStringParameter(parameterDeveloperName)); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected List getDecimalListParameter(String parameterDeveloperName) { - // return (List) this.castParameter(parameterDeveloperName, List.class); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Double` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Double` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected Double getDoubleParameter(String parameterDeveloperName) { - // return Double.valueOf(this.getStringParameter(parameterDeveloperName)); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Id` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Id` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected Id getIdParameter(String parameterDeveloperName) { - // return Id.valueOf(this.getStringParameter(parameterDeveloperName)); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected List getIdListParameter(String parameterDeveloperName) { - // return (List) this.castParameter(parameterDeveloperName, List.class); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Integer` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Integer` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected Integer getIntegerParameter(String parameterDeveloperName) { - // return Integer.valueOf(this.getStringParameter(parameterDeveloperName)); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected List getIntegerListParameter(String parameterDeveloperName) { - // return (List) this.castParameter(parameterDeveloperName, List.class); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `Long` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Long` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected Long getLongParameter(String parameterDeveloperName) { - // return Long.valueOf(this.getStringParameter(parameterDeveloperName)); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected List getLongListParameter(String parameterDeveloperName) { - // return (List) this.castParameter(parameterDeveloperName, List.class); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as an `Object` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `Object` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected Object getObjectParameter(String parameterDeveloperName) { - // return (Object) this.getStringParameter(parameterDeveloperName); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as an `List` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected List getObjectListParameter(String parameterDeveloperName) { - // return (List) this.castParameter(parameterDeveloperName, List.class); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `SObject` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `SObject` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected SObject getSObjectParameter(String parameterDeveloperName) { - // return (SObject) JSON.deserialize(this.getStringParameter(parameterDeveloperName), SObject.class); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected List getSObjectListParameter(String parameterDeveloperName) { - // return (List) this.castParameter(parameterDeveloperName, List.class); - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `String` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `String` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // Since the Value__c field is a string field, this method is used internally by the other parameter methods - // protected String getStringParameter(String parameterDeveloperName) { - // return this.getParameter(parameterDeveloperName)?.Value__c; - // } - - /** - * @description Returns the configured value of the field `LoggerSObjectHandlerPluginParameter__mdt.Value__c` as a `List` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The `List` value configured in the matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected List getStringListParameter(String parameterDeveloperName) { - // return (List) this.castParameter(parameterDeveloperName, List.class); - // } - - /** - * @description Returns the matching instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @param parameterDeveloperName The developer name of the instance of `LoggerSObjectHandlerPluginParameter__mdt` - * @return The matching instance of `LoggerSObjectHandlerPluginParameter__mdt`, - * or null when not found or disabled - */ - // protected LoggerSObjectHandlerPluginParameter__mdt getParameter(String parameterDeveloperName) { - // LoggerSObjectHandlerPluginParameter__mdt parameter = LoggerSObjectHandlerPluginParameter__mdt.getInstance(parameterDeveloperName); - - // if (parameter == null || parameter.IsEnabled__c == false) { - // return null; - // } - - // return parameter; - // } - - // private Object castParameter(String parameterDeveloperName, Type dataType) { - // // return JSON.deserialize(this.getStringParameter(parameterDeveloperName), dataType); - // return JSON.deserialize(this.getParameter(parameterDeveloperName)?.Value__c, dataType); - // } } From 6fef1d09516faf38628315b6321e07488c339c4e Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Sun, 20 Jun 2021 15:10:51 -0700 Subject: [PATCH 82/82] New package versions --- README.md | 4 ++-- nebula-logger-plugins/Slack/README.md | 2 +- packages/managed-package/sfdx-project.json | 2 +- sfdx-project.json | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a1c965c47..826656390 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ Designed for Salesforce admins, developers & architects. A robust logger for Apex, Flow, Process Builder & Integrations. -[![Install Unlocked Package](./content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FM3QAM) -[![Install Managed Package](./content/btn-install-managed-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FLyQAM) +[![Install Unlocked Package](./content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FMrQAM) +[![Install Managed Package](./content/btn-install-managed-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000027FMhQAM) [![Deploy Unpackaged Metadata](./content/btn-deploy-unpackaged-metadata.png)](https://githubsfdeploy.herokuapp.com/?owner=jongpie&repo=NebulaLogger&ref=main) [![View Documentation](./content/btn-view-documentation.png)](https://jongpie.github.io/NebulaLogger/) diff --git a/nebula-logger-plugins/Slack/README.md b/nebula-logger-plugins/Slack/README.md index 5bde2c615..cca1c8584 100644 --- a/nebula-logger-plugins/Slack/README.md +++ b/nebula-logger-plugins/Slack/README.md @@ -2,7 +2,7 @@ Adds a Slack integration for Nebula Logger. Any logs with log entries that meet a certain (configurable) logging level will automatically be posted to your Slack channel via an asynchronous `Queueable` job. -[![Install Unlocked Package](./../../content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5e0000005whPAAQ) +[![Install Unlocked Package](./../../content/btn-install-unlocked-package.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5e00000061lHAAQ) ![Slack plugin: notification](./../../content/slack-plugin-notification.png) diff --git a/packages/managed-package/sfdx-project.json b/packages/managed-package/sfdx-project.json index 945cbb874..9426bbdc8 100644 --- a/packages/managed-package/sfdx-project.json +++ b/packages/managed-package/sfdx-project.json @@ -22,6 +22,6 @@ "Nebula Logger - Managed Package@4.2.0-0-more-fields-and-methods": "04t5Y000000Xg4wQAC", "Nebula Logger - Managed Package@4.3.0-3-logger-console-app": "04t5Y000000YLDLQA4", "Nebula Logger - Managed Package@4.4.0-2-config-default-save-method": "04t5Y0000027FFgQAM", - "Nebula Logger - Managed Package@4.5.0-0-logger-plugin-framework": "04t5Y0000027FLyQAM" + "Nebula Logger - Managed Package@4.5.0-0-logger-plugin-framework": "04t5Y0000027FMhQAM" } } diff --git a/sfdx-project.json b/sfdx-project.json index e74af7836..5dfd48e0c 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -18,8 +18,8 @@ "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases" }, { - "path": "nebula-logger-plugins/Slack", "package": "Nebula Logger Plugin - Slack", + "path": "nebula-logger-plugins/Slack", "dependencies": [ { "package": "Nebula Logger - Unlocked Package@4.5.0-0-logger-plugin-framework" @@ -43,8 +43,8 @@ "Nebula Logger - Unlocked Package@4.4.4-0-timestamp-bugfix": "04t5Y0000027FIQQA2", "Nebula Logger - Unlocked Package@4.4.5-0-log-batch-purger-bugfixes": "04t5Y0000027FIVQA2", "Nebula Logger - Unlocked Package@4.4.6-0-new-save-method-synchronous_dml": "04t5Y0000027FJdQAM", - "Nebula Logger - Unlocked Package@4.5.0-0-logger-plugin-framework": "04t5Y0000027FM8QAM", + "Nebula Logger - Unlocked Package@4.5.0-0-logger-plugin-framework": "04t5Y0000027FMrQAM", "Nebula Logger Plugin - Slack": "0Ho5e000000oM3pCAE", - "Nebula Logger Plugin - Slack@0.9.0-0-beta-release": "04t5e0000005whPAAQ" + "Nebula Logger Plugin - Slack@0.9.0-0-beta-release": "04t5e00000061lHAAQ" } -} +} \ No newline at end of file