Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added plugin framework + re-added Slack integration #165

Merged
merged 85 commits into from
Jun 20, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
d8f2bac
Added basic functionality for handler post-processors in LogHandler a…
jongpie Jun 4, 2021
1de4a65
Added all trigger operations + updates in README
jongpie Jun 4, 2021
5ffe394
Added triggerOperation parameter
jongpie Jun 4, 2021
a9224c2
Fixed Flow input details
jongpie Jun 4, 2021
778af21
Added IsActive__c flag on config CMDT
jongpie Jun 4, 2021
9ff08ba
Moved post-processor interface outside of LoggerHandler, LoggerHandle…
jongpie Jun 4, 2021
b93e75f
Merge branch 'main' of https://github.com/jongpie/NebulaLogger into f…
jongpie Jun 4, 2021
e93a5cf
Swapped `super` for `this`
jongpie Jun 5, 2021
e9b7454
Added handler tests for Apex post-processors + cleaned up field names
jongpie Jun 5, 2021
30fe68c
More renames
jongpie Jun 6, 2021
e295a3a
Updated version to v4.5.0
jongpie Jun 6, 2021
5ced29b
Updated docs
jongpie Jun 6, 2021
1a4f46f
Added IsEnabled__c flag to handler config CMDT
jongpie Jun 7, 2021
6739628
Updated relationship name on CMDT
jongpie Jun 7, 2021
76c5f8e
Renamed config.LoggerSObject__c field to SObjectType__c
jongpie Jun 7, 2021
492ab3e
Updated screenshot of handler config
jongpie Jun 7, 2021
8ed788b
WIP: Fixed most of the failing tests again
jongpie Jun 7, 2021
89c7e21
Added tests to verify handlers dont run when disabled via CMDT
jongpie Jun 7, 2021
5b87d7d
Merge branch 'main' of https://github.com/jongpie/NebulaLogger into f…
jongpie Jun 7, 2021
1979b69
Added tests to make sure default configs are used when no CMDT is found
jongpie Jun 7, 2021
fc2f754
Small fix for trigger operation in Flow post-processing
jongpie Jun 8, 2021
6d59996
Changed CMDT mocking approach to be 83% less goofy based on @jamessim…
jongpie Jun 8, 2021
128f8f3
Centralized more trigger-based logic into LoggerSObjectHandler
jongpie Jun 8, 2021
dd86d6e
Removed safe navigators - there shouldnt be nulls in this situation
jongpie Jun 8, 2021
b3b6e0c
Added extra tests for Flow post-processors
jongpie Jun 8, 2021
bb7846f
Temp commenting out an assert
jongpie Jun 8, 2021
01f1fd4
Fixed incorrect SObject type
jongpie Jun 8, 2021
8df593a
Finished test for invoking Flow post-processor
jongpie Jun 8, 2021
be7744a
Added extra assert in test (just to be safe)
jongpie Jun 8, 2021
747cd5d
Generated new package versions
jongpie Jun 8, 2021
5878d89
Generated new package versions
jongpie Jun 8, 2021
608b80a
Fixed some config issues with SObjectType__c CMDT field
jongpie Jun 8, 2021
65006ef
Fixed VR rule name
jongpie Jun 8, 2021
0766406
Removed unused describe call
jongpie Jun 9, 2021
9ffcb7b
Moved post-processor config into a 2nd CMDT object
jongpie Jun 10, 2021
1ff13f3
Renamed 'post processors' to 'plugins' instead, added all 4 trigger S…
jongpie Jun 11, 2021
0e6e1e1
Fixed a few more old refs to 'post-processor' to use 'plugin' instead
jongpie Jun 11, 2021
8bf8a1a
Created Slack plugin prototype
jongpie Jun 11, 2021
dc1a179
Some code cleanup in SlackLoggerPlugin
jongpie Jun 11, 2021
58707f9
Hello there, LoggerSObjectHandlerPluginParameter__mdt
jongpie Jun 12, 2021
a3d63eb
Added description fields to plugin & param CMDT objects + new list views
jongpie Jun 12, 2021
85f4328
WIP: SlackLoggerPlugin_Tests (currently failing)
jongpie Jun 12, 2021
88af654
Renamed Slack parameter list view
jongpie Jun 12, 2021
a3bf731
Added description to Slack remote site setting
jongpie Jun 12, 2021
2df4727
Made more changes to the format of Slack notification
jongpie Jun 12, 2021
75fb074
Converted plugin framework to public for now - once stabilized, I'll …
jongpie Jun 13, 2021
cd8aada
Added more plugin details in README.md
jongpie Jun 13, 2021
37344cb
More formatting changes in README.md
jongpie Jun 13, 2021
e1a5592
Fixed Slack API token usage
jongpie Jun 13, 2021
e59df71
Added screenshot of Slack notification examples
jongpie Jun 13, 2021
c36236a
Removed Slack plugin install btn for now
jongpie Jun 13, 2021
47799f4
Added "What's Included" section in Slack's README.me
jongpie Jun 13, 2021
a057b3f
Formatting cleanup in Slack README.md
jongpie Jun 13, 2021
2d66eb3
Added detail that notifications are created via a queueable job
jongpie Jun 13, 2021
1e408ba
Changed plugin header title in README.md
jongpie Jun 13, 2021
ed31f18
More README header updates
jongpie Jun 13, 2021
45cd230
Corrected ApexDocs for LoggerSObjectHandlerPlugin
jongpie Jun 13, 2021
b090589
More ApexDocs updates
jongpie Jun 13, 2021
a78b8d8
Added plugin-framework folder
jongpie Jun 13, 2021
0d00458
Lots o' field descriptions, help text & docs updates
jongpie Jun 13, 2021
6910cfe
Renamed Slack CMDT record
jongpie Jun 13, 2021
ee587d0
Slack plugin cleanup + README updates
jongpie Jun 14, 2021
add0b27
Removed unused constants in SlackLoggerPlugin
jongpie Jun 14, 2021
cedc7d3
Cleaned up plugin details in README
jongpie Jun 14, 2021
cc86208
Moved Slack list view to correct folder
jongpie Jun 14, 2021
7a475ea
Updated Flow plugin details, moved note location about plugin framewo…
jongpie Jun 14, 2021
5c95611
Updated trigger framework variable names for consistency & clarity
jongpie Jun 14, 2021
fce4708
Fixed list view criteria, added CMDT description
jongpie Jun 14, 2021
5b709e3
Fixed deployment failure due to old variable ref
jongpie Jun 14, 2021
7d4ca50
Finished (basic) Slack tests + created plugin unlocked package + crea…
jongpie Jun 14, 2021
3910df6
Fixed plugin button image in README.me
jongpie Jun 14, 2021
4e014f7
Added extra test class LoggerSObjectHandlerPlugin_Tests
jongpie Jun 15, 2021
69a7d68
Changed some CMDT fields to DeveloperControlled
jongpie Jun 15, 2021
b72c3cb
A little unrelated code cleanup in RelatedLogEntriesController
jongpie Jun 15, 2021
cf6b17b
Added CollectionType field on plugin param CMDT
jongpie Jun 16, 2021
683dba7
Slack plugin cleanup
jongpie Jun 16, 2021
d18967a
More details + cleanup in README.md
jongpie Jun 16, 2021
5bc2804
Fixed some formatting issues in README.md
jongpie Jun 16, 2021
a24f860
New pkg versions for ALL the packages
jongpie Jun 16, 2021
e468dcd
Stupid README inconsistency
jongpie Jun 16, 2021
3727a52
Removed redundant text that was redundant
jongpie Jun 17, 2021
7c5f80a
Merge branch 'main' of https://github.com/jongpie/NebulaLogger into f…
jongpie Jun 20, 2021
7f4a84d
Updates to Slack README.md
jongpie Jun 20, 2021
4d13999
Removed commented-out code in LoggerSObjectHandlerPlugin
jongpie Jun 20, 2021
6fef1d0
New package versions
jongpie Jun 20, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,35 @@ 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 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.)
- Apex post-processors: your Apex class should implement `LoggerPostProcessor`. For example:

```java
public class ExamplePostProcessor implements LoggerPostProcessor {
public void execute(Trigger.operationType triggerOperation, List<Log__c> logs, Map<Id, SObject> oldLoggerRecordsById) {
switch on triggerOperation {
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.

![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.
Expand Down
Binary file added content/logger-handler-configuration.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, Log__c> TRANSACTION_ID_TO_LOG = new Map<String, Log__c>();

@testVisible
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@
* @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<LogEntry__c> logEntries;
@testVisible
private Map<Id, LogEntry__c> oldLogEntriesById;
@testVisible
private TriggerOperation triggerOperationType;

public LogEntryHandler() {
this.logEntries = (List<LogEntry__c>) Trigger.new;
this.oldLogEntriesById = (Map<Id, LogEntry__c>) Trigger.oldMap;
this.triggerOperationType = Trigger.operationType;
}

Expand All @@ -39,6 +42,9 @@ public without sharing class LogEntryHandler {
this.setCheckboxFields();
}
}

// Run any post-processors
super.executePostProcessors(this.logEntries, this.oldLogEntriesById);
jongpie marked this conversation as resolved.
Show resolved Hide resolved
}

private void setCheckboxFields() {
Expand Down
5 changes: 4 additions & 1 deletion nebula-logger/main/log-management/classes/LogHandler.cls
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -58,6 +58,9 @@ public without sharing class LogHandler {
this.shareLogsWithLoggingUsers();
}
}

// Run any post-processors
super.executePostProcessors(this.logs, this.oldLogsById);
jongpie marked this conversation as resolved.
Show resolved Hide resolved
}

private void setOrgReleaseCycle() {
Expand Down
53 changes: 53 additions & 0 deletions nebula-logger/main/log-management/classes/LoggerHandler.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//------------------------------------------------------------------------------------------------//
// 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<SObject> loggerRecords, Map<Id, SObject> oldLoggerRecordsById) {
if (loggerRecords == null) {
return;
}

String sobjectTypeCmdtName = loggerRecords.getSObjectType().getDescribe().getName().replace('__c', '');

List<LoggerHandlerConfiguration__mdt> 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);

executeApexClass(loggerHandlerConfiguration?.ApexClassName__c, loggerRecords, oldLoggerRecordsById);
executeFlow(loggerHandlerConfiguration?.FlowName__c, loggerRecords, oldLoggerRecordsById);
}

private void executeApexClass(String apexClassName, List<SObject> loggerRecords, Map<Id, SObject> oldLoggerRecordsById) {
if (String.isBlank(apexClassName)) {
return;
}

Type postProcessorType = Type.forName(apexClassName);
LoggerPostProcessor recordPostProcessor = (LoggerPostProcessor) postProcessorType.newInstance();
recordPostProcessor.execute(Trigger.operationType, loggerRecords, oldLoggerRecordsById);
}

private void executeFlow(String flowName, List<SObject> loggerRecords, Map<Id, SObject> oldLoggerRecordsById) {
if (String.isBlank(flowName)) {
return;
}

Map<String, Object> flowInputs = new Map<String, Object>();
flowInputs.put('records', loggerRecords);
flowInputs.put('oldRecords', oldLoggerRecordsById?.values());
flowInputs.put('triggerOperation', Trigger.operationType);

Flow.Interview recordFlow = Flow.Interview.createInterview(flowName, flowInputs);
recordFlow.start();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>51.0</apiVersion>
<status>Active</status>
</ApexClass>
13 changes: 13 additions & 0 deletions nebula-logger/main/log-management/classes/LoggerPostProcessor.cls
Original file line number Diff line number Diff line change
@@ -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<SObject> loggerRecords, Map<Id, SObject> oldLoggerRecordsById);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>51.0</apiVersion>
<status>Active</status>
</ApexClass>
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<Layout xmlns="http://soap.sforce.com/2006/04/metadata">
<layoutSections>
<customLabel>false</customLabel>
<detailHeading>false</detailHeading>
<editHeading>true</editHeading>
<label>Information</label>
<layoutColumns>
<layoutItems>
<behavior>Required</behavior>
<field>MasterLabel</field>
</layoutItems>
<layoutItems>
<behavior>Required</behavior>
<field>DeveloperName</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>IsActive__c</field>
</layoutItems>
</layoutColumns>
<layoutColumns>
<layoutItems>
<behavior>Required</behavior>
<field>LoggerSObject__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>ApexClassName__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>FlowName__c</field>
</layoutItems>
</layoutColumns>
<style>TwoColumnsTopToBottom</style>
</layoutSections>
<layoutSections>
<customLabel>false</customLabel>
<detailHeading>false</detailHeading>
<editHeading>true</editHeading>
<label>System Information</label>
<layoutColumns>
<layoutItems>
<behavior>Required</behavior>
<field>NamespacePrefix</field>
</layoutItems>
<layoutItems>
<behavior>Readonly</behavior>
<field>CreatedById</field>
</layoutItems>
</layoutColumns>
<layoutColumns>
<layoutItems>
<behavior>Edit</behavior>
<field>IsProtected</field>
</layoutItems>
<layoutItems>
<behavior>Readonly</behavior>
<field>LastModifiedById</field>
</layoutItems>
</layoutColumns>
<style>TwoColumnsTopToBottom</style>
</layoutSections>
<layoutSections>
<customLabel>true</customLabel>
<detailHeading>false</detailHeading>
<editHeading>false</editHeading>
<label>Custom Links</label>
<layoutColumns/>
<layoutColumns/>
<layoutColumns/>
<style>CustomLinks</style>
</layoutSections>
<showEmailCheckbox>false</showEmailCheckbox>
<showHighlightsPanel>false</showHighlightsPanel>
<showInteractionLogPanel>false</showInteractionLogPanel>
<showRunAssignmentRulesCheckbox>false</showRunAssignmentRulesCheckbox>
<showSubmitAndAttachButton>false</showSubmitAndAttachButton>
<summaryLayout>
<masterLabel>00h3F0000048LpM</masterLabel>
<sizeX>4</sizeX>
<sizeY>0</sizeY>
<summaryLayoutStyle>Default</summaryLayoutStyle>
</summaryLayout>
</Layout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
<description>Used to configure additional Apex classes that should be executed by Logger after creating or updating records in Log__c or LogEntry__c</description>
<label>Logger Handler Config</label>
<pluralLabel>Logger Handler Configs</pluralLabel>
<visibility>Public</visibility>
</CustomObject>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>ApexClassName__c</fullName>
<description>The name of an Apex class that implements LoggerPostProcessor.Handler</description>
<externalId>false</externalId>
<fieldManageability>DeveloperControlled</fieldManageability>
<inlineHelpText>The name of an Apex class that implements LoggerPostProcessor.Handler</inlineHelpText>
<label>Apex Class Name</label>
<length>255</length>
<required>false</required>
<type>Text</type>
<unique>false</unique>
</CustomField>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>FlowName__c</fullName>
<externalId>false</externalId>
<fieldManageability>DeveloperControlled</fieldManageability>
<label>Flow Name</label>
<length>255</length>
<required>false</required>
<type>Text</type>
<unique>false</unique>
</CustomField>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>IsActive__c</fullName>
<defaultValue>true</defaultValue>
<externalId>false</externalId>
<fieldManageability>SubscriberControlled</fieldManageability>
<label>Is Active</label>
<type>Checkbox</type>
</CustomField>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>LoggerSObject__c</fullName>
<description>The Logger object to process - Log__c or LogEntry__c</description>
<externalId>false</externalId>
<fieldManageability>DeveloperControlled</fieldManageability>
<inlineHelpText>The Logger object to process - Log__c or LogEntry__c</inlineHelpText>
<label>Logger Object</label>
<referenceTo>EntityDefinition</referenceTo>
<relationshipLabel>Logger Post Processors</relationshipLabel>
<relationshipName>LoggerPostProcessors</relationshipName>
<required>true</required>
<type>MetadataRelationship</type>
<unique>true</unique>
</CustomField>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<ListView xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>All</fullName>
<columns>MasterLabel</columns>
<columns>DeveloperName</columns>
<columns>IsActive__c</columns>
<columns>LoggerSObject__c</columns>
<columns>ApexClassName__c</columns>
<columns>FlowName__c</columns>
<filterScope>Everything</filterScope>
<label>All</label>
</ListView>
2 changes: 1 addition & 1 deletion nebula-logger/main/log-management/triggers/Log.trigger
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}