diff --git a/README.md b/README.md
index 6c384a1..2cee57f 100644
--- a/README.md
+++ b/README.md
@@ -34,9 +34,14 @@ Please have read the [contributing guide](./CONTRIBUTING.md) that will through t
You can also have a look at the open items in the [project(s)](./projects), feel free to pick an item from the kanban board!
-## Change Log
+----
+# Change Log
Some of the changes that have major impact are listed here;
+### September 2021
+**Logger functionality**
+A replacement of System.Debug that is using Platform events to store log messages in a Custom Object for you to monitor
+
### August 2021
**Added criteria based on formula; (1 OR 2) AND 3)**
@@ -50,6 +55,9 @@ new fflib_Criteria()
Evaluates:
(AccountNumber = '0001' OR AccountNumber = '0001') AND ShippingCountry = 'USA'
```
+
+---
+
## Donations
We are pleased to announce that the fflib-apex-extensions Project is accepting donations in the privacy-oriented cryptocurrency Monero (XMR) at the following address:
diff --git a/sfdx-project.json b/sfdx-project.json
index b2b5c6f..503b680 100644
--- a/sfdx-project.json
+++ b/sfdx-project.json
@@ -8,5 +8,5 @@
"name": "fflib-apex-extensions",
"namespace": "",
"sfdcLoginUrl": "https://login.salesforce.com",
- "sourceApiVersion": "51.0"
+ "sourceApiVersion": "53.0"
}
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_ALogAppenderFilter.cls b/sfdx-source/apex-extensions/main/logger/classes/fflib_ALogAppenderFilter.cls
new file mode 100644
index 0000000..76d415b
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_ALogAppenderFilter.cls
@@ -0,0 +1,197 @@
+/**
+ * File Name: fflib_ALogAppenderFilter
+ * Description: Log Appender that includes a filter for logginglevel
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+public abstract with sharing class fflib_ALogAppenderFilter implements fflib_ILogAppender
+{
+ // The default logging level that must be met before log messages are processed
+ public static final System.LoggingLevel DEFAULT_LEVEL = System.LoggingLevel.ERROR;
+
+ // The current used logging level which can be modified during runtime
+ protected System.LoggingLevel minLogLevel = DEFAULT_LEVEL;
+
+ /**
+ * setLoggingLevel
+ *
+ * @description Change the current minimum logging level
+ * @param logLevel
+ */
+ public void setLoggingLevel(System.LoggingLevel logLevel)
+ {
+ this.minLogLevel = logLevel;
+ }
+
+ /**
+ * isValidLogLevel
+ *
+ * @description Compares the Organisation, User and Apex logging level settings
+ * @param logLevel
+ *
+ * @return Returns true if one of the settings is equal or higher than the given loglevel
+ */
+ protected Boolean isValidLogLevel(System.LoggingLevel logLevel)
+ {
+ return (
+ isValidOrganisationLogLevel(logLevel) ||
+ isValidUserLogLevel(logLevel) ||
+ isValidApexClassLogLevel(logLevel)
+ );
+ }
+
+ /**
+ * isValidLogLevel
+ *
+ * @description Compares the given log level valueToCompare against the compareTo
+ * @param compareTo The log level to compare against
+ * @param valueToCompare The log level to compare
+ *
+ * @return Returns true if the valueToCompare is equal of higher then the compareTo
+ */
+ private Boolean isValidLogLevel(System.LoggingLevel compareTo, System.LoggingLevel valueToCompare)
+ {
+ return compareTo != System.LoggingLevel.NONE
+ &&
+ valueToCompare != System.LoggingLevel.NONE
+ &&
+ valueToCompare.ordinal() >= compareTo.ordinal();
+ }
+
+ /**
+ * isValidApexClassLogLevel
+ *
+ * @description Compare the given loglevel against the current Apex setting stored in this.minLogLevel
+ * @param logLevel The log level to compare
+ *
+ * @return Returns true if the given log level is equal of higher then the Apex setting
+ */
+ private Boolean isValidApexClassLogLevel(System.LoggingLevel logLevel)
+ {
+ return isValidLogLevel(this.minLogLevel, logLevel);
+ }
+
+ /**
+ * isValidOrganisationLogLevel
+ *
+ * @description Compare the given loglevel against the Organisation setting stored in a Custom Setting
+ * @param logLevel The log level to compare
+ *
+ * @return Returns true if the given log level is equal of higher then the Organisation setting
+ */
+ private Boolean isValidOrganisationLogLevel(System.LoggingLevel logLevel)
+ {
+ return isValidLogLevel(
+ getDefaultOrganisationLogLevel(),
+ logLevel
+ );
+ }
+
+ /**
+ * isValidUserLogLevel
+ *
+ * @description Compare the given loglevel against the User setting stored in a Custom Setting
+ * @param logLevel The log level to compare
+ *
+ * @return Returns true if the given log level is equal of higher then the User setting
+ */
+ private Boolean isValidUserLogLevel(System.LoggingLevel logLevel)
+ {
+ return isValidLogLevel(
+ getUserLogLevel(),
+ logLevel
+ );
+ }
+
+ /**
+ * getDefaultOrganisationLogLevel
+ *
+ * @return Returns the default Organisation log level setting stored in fflib_LogLevelFilter__c
+ */
+ private System.LoggingLevel getDefaultOrganisationLogLevel()
+ {
+ fflib_LogLevelFilter__c orgSettings = fflib_LogLevelFilter__c.getOrgDefaults();
+ if (String.isBlank(orgSettings.LogLevel__c))
+ {
+ return System.LoggingLevel.NONE;
+ }
+ return stringToLoggingLevel(orgSettings.LogLevel__c);
+ }
+
+ /**
+ * getUserLogLevel
+ *
+ * @return Returns the default User log level setting stored in user or profile setting in fflib_LogLevelFilter__c
+ */
+ private System.LoggingLevel getUserLogLevel()
+ {
+ fflib_LogLevelFilter__c logLevelFilter = fflib_LogLevelFilter__c.getInstance(UserInfo.getUserId());
+ if (!hasSettingsValue(logLevelFilter, fflib_LogLevelFilter__c.LogLevel__c))
+ {
+ return System.LoggingLevel.NONE;
+ }
+ return stringToLoggingLevel(logLevelFilter.LogLevel__c);
+ }
+
+ /**
+ * hasSettingsValue
+ *
+ * @description Validates if the Custom Setting has a value stored in the given field
+ * @param setting The Custom Setting to validate
+ * @param sObjectField The field to check
+ *
+ * @return Returns true is the given field is set in the Custom Setting
+ */
+ private Boolean hasSettingsValue(fflib_LogLevelFilter__c setting, SObjectField sObjectField)
+ {
+ return (
+ null != setting
+ &&
+ setting.getPopulatedFieldsAsMap().containsKey(sObjectField.getDescribe().getName())
+ );
+ }
+
+ /**
+ * stringToLoggingLevel
+ *
+ * @param logLevelToConvert
+ *
+ * @return Returns the Log level for a given string, and System.LoggingLevel.None is an invalid string is given
+ */
+ private System.LoggingLevel stringToLoggingLevel(String logLevelToConvert)
+ {
+ String logLevelString = logLevelToConvert.toUpperCase();
+ for (System.LoggingLevel logLevel : System.LoggingLevel.values())
+ {
+ if (logLevelString == logLevel.name())
+ {
+ return logLevel;
+ }
+ }
+ return System.LoggingLevel.NONE;
+ }
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_ALogAppenderFilter.cls-meta.xml b/sfdx-source/apex-extensions/main/logger/classes/fflib_ALogAppenderFilter.cls-meta.xml
new file mode 100644
index 0000000..f3bac1f
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_ALogAppenderFilter.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 41.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogAppender.cls b/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogAppender.cls
new file mode 100644
index 0000000..da36064
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogAppender.cls
@@ -0,0 +1,34 @@
+/**
+ * File Name: fflib_ILogAppender
+ * Description: Interface for appending log entries to and endpoint
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+public interface fflib_ILogAppender
+{
+ void append(fflib_LogEntry logEntry);
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogAppender.cls-meta.xml b/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogAppender.cls-meta.xml
new file mode 100644
index 0000000..f3bac1f
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogAppender.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 41.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogMessageFormatter.cls b/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogMessageFormatter.cls
new file mode 100644
index 0000000..d8866a6
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogMessageFormatter.cls
@@ -0,0 +1,36 @@
+/**
+ * File Name: fflib_ILogMessageFormatter
+ * Description: Interface for formatting log messages
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+public interface fflib_ILogMessageFormatter
+{
+ String format(String message);
+ String format(String message, List args);
+ String format(Exception e);
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogMessageFormatter.cls-meta.xml b/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogMessageFormatter.cls-meta.xml
new file mode 100644
index 0000000..c413058
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogMessageFormatter.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 41.0
+ Active
+
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogger.cls b/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogger.cls
new file mode 100644
index 0000000..3e5949b
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogger.cls
@@ -0,0 +1,48 @@
+/**
+ * File Name: fflib_ILogger
+ * Description: Interface for the Logger utility
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+public interface fflib_ILogger
+{
+ void add(String message);
+ void debug(Exception e);
+ void debug(String message);
+ void debug(String message, List args);
+ void error(Exception e);
+ void error(String message);
+ void error(String message, List args);
+ void info(String message);
+ void info(String message, List args);
+ void warning(String message);
+ void warning(String message, List args);
+
+ fflib_ILogger addAppender(fflib_ILogAppender appender);
+ fflib_ILogger setAppender(fflib_ILogAppender appender);
+ fflib_ILogger setMessageFormatter(fflib_ILogMessageFormatter formatter);
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogger.cls-meta.xml b/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogger.cls-meta.xml
new file mode 100644
index 0000000..f3bac1f
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_ILogger.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 41.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEntry.cls b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEntry.cls
new file mode 100644
index 0000000..f9fa716
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEntry.cls
@@ -0,0 +1,75 @@
+/**
+ * File Name: fflib_LogEntry
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+public with sharing class fflib_LogEntry
+{
+ public String className { get; set; }
+ public String executionContext { get; set; }
+ public Decimal lineNumber { get; set; }
+ public Id logEntryId { get; set; }
+ public System.LoggingLevel logLevel { get; set; }
+ public String message { get; set; }
+ public String methodName { get; set; }
+ public Id userId { get; set; }
+ public Datetime createdDatetime { get; set; }
+
+ public fflib_LogEntry()
+ {
+ this(System.LoggingLevel.INFO, null);
+ }
+
+ public fflib_LogEntry(System.LoggingLevel loggingLevel, String message)
+ {
+ this.executionContext = Request.getCurrent().getRequestId() + '/' + Request.getCurrent().getQuiddity();
+ this.logLevel = loggingLevel;
+ this.message = message;
+ this.userId = System.UserInfo.getUserId();
+ }
+
+ public fflib_LogEntry(fflib_LogEvent__e logEvent)
+ {
+ this.className = logEvent.ClassName__c;
+ this.executionContext = logEvent.ExecutionContext__c;
+ this.lineNumber = logEvent.LineNumber__c;
+ this.logEntryId = logEvent.Id;
+ this.logLevel = System.LoggingLevel.valueOf(logEvent.LogLevel__c);
+ }
+
+ public fflib_LogEvent__e toPlatformEvent()
+ {
+ return new fflib_LogEvent__e(
+ ClassName__c = this.className,
+ ExecutionContext__c = this.executionContext,
+ LineNumber__c = this.lineNumber,
+ LogLevel__c = this.logLevel.name(),
+ Message__c = this.message,
+ MethodName__c = this.methodName
+ );
+ }
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEntry.cls-meta.xml b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEntry.cls-meta.xml
new file mode 100644
index 0000000..d75b058
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEntry.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 51.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventAppender.cls b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventAppender.cls
new file mode 100644
index 0000000..a28ccf8
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventAppender.cls
@@ -0,0 +1,107 @@
+/**
+ * File Name: fflib_LogEventAppender
+ * Description: Log Appender for publishing Platform Events
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+public virtual without sharing class fflib_LogEventAppender extends fflib_ALogAppenderFilter
+{
+
+ /**
+ * Publish a platform event fflib_LogEvent__e with the given message and logging level if it meets the minimum logging level
+ *
+ * @param logEntry The new log entry to append
+ */
+ public virtual void append(fflib_LogEntry logEntry)
+ {
+ if (!isValidLogLevel(logEntry.logLevel)) return;
+
+ publishEvents(
+ new List
+ {
+ logEntry.toPlatformEvent()
+ });
+ }
+
+ /**
+ * publishEvents
+ *
+ * @description Publish the given fflib_LogEvent__e events and report if there are any errors
+ * @param events The Platform events to publish
+ */
+ protected virtual void publishEvents(List events)
+ {
+ List results = EventBus.publish(events);
+ checkAndReportErrors(results);
+ }
+
+
+ /**
+ * checkAndReportErrors
+ *
+ * @description Iterate over the given Database.SaveResults and report any errors
+ * @param saveResults
+ */
+ protected void checkAndReportErrors(List saveResults)
+ {
+ // Inspect publishing result for each event
+ for (Database.SaveResult saveResult : saveResults)
+ {
+ if (!saveResult.isSuccess())
+ {
+ reportError(saveResult);
+ }
+ }
+ }
+
+ /**
+ * reportError
+ *
+ * @description Construct the error message for the failing Database.SaveResult and throws an exception
+ * @param saveResult
+ *
+ * @throws fflib_LogEventAppender.fflib_LogEventAppenderException
+ */
+ protected virtual void reportError(Database.SaveResult saveResult)
+ {
+ String errorMessage = 'Error while publishing Log event:';
+ for (Database.Error databaseError : saveResult.getErrors())
+ {
+ errorMessage += String.format(
+ ' {0} - {1}, ',
+ new List
+ {
+ String.valueOf(databaseError.getStatusCode()),
+ databaseError.getMessage()
+ }
+ );
+ }
+ throw new fflib_LogEventAppenderException(errorMessage);
+ }
+
+ public class fflib_LogEventAppenderException extends Exception {}
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventAppender.cls-meta.xml b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventAppender.cls-meta.xml
new file mode 100644
index 0000000..f3bac1f
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventAppender.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 41.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventDomain.cls b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventDomain.cls
new file mode 100644
index 0000000..29535e4
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventDomain.cls
@@ -0,0 +1,71 @@
+/**
+ * File Name: fflib_LogEventDomain
+ * Description: Log Platform Events domain abstract class for the Log Entry events
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+public abstract with sharing class fflib_LogEventDomain extends fflib_PlatformEventDomain
+{
+
+ protected List logEntries = new List();
+
+ /**
+ * Class constructor
+ */
+ public fflib_LogEventDomain(List records)
+ {
+ super(records);
+ recordsToLogEntries();
+ }
+
+ protected void recordsToLogEntries()
+ {
+ for (SObject record : Records)
+ {
+ this.logEntries.add(
+ new LogEntry((fflib_LogEvent__e) record)
+ );
+ }
+ }
+
+ public class LogEntry
+ {
+ public Id createdById;
+ public Datetime createdDatetime;
+ public System.LoggingLevel loggingLevel;
+ public String message;
+
+ public LogEntry(fflib_LogEvent__e event)
+ {
+ this.loggingLevel = System.LoggingLevel.values().get((Integer) event.LogLevel__c);
+ this.message = event.message__c;
+ this.createdById = event.CreatedById;
+ this.createdDatetime = event.CreatedDate;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventDomain.cls-meta.xml b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventDomain.cls-meta.xml
new file mode 100644
index 0000000..f3bac1f
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventDomain.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 41.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventStoreListener.cls b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventStoreListener.cls
new file mode 100644
index 0000000..1c6bd75
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventStoreListener.cls
@@ -0,0 +1,57 @@
+/**
+ * File Name: fflib_LogEventStoreListener
+ * Description: Log Platform Events listener to store messages into a custom object
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+public with sharing class fflib_LogEventStoreListener extends fflib_LogEventDomain
+{
+
+ /**
+ * Class constructor
+ */
+ public fflib_LogEventStoreListener(List records)
+ {
+ super(records);
+ }
+
+ public void run()
+ {
+ List logEntryRecords = new List();
+ for (fflib_LogEventDomain.LogEntry logEntry : logEntries)
+ {
+ logEntryRecords.add(
+ new fflib_LogEntry__c(
+ LogLevel__c = logEntry.loggingLevel.name(),
+ Message__c = logEntry.message,
+ User__c = logEntry.createdById
+ )
+ );
+ }
+ insert logEntryRecords;
+ }
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventStoreListener.cls-meta.xml b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventStoreListener.cls-meta.xml
new file mode 100644
index 0000000..f3bac1f
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventStoreListener.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 41.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_Logger.cls b/sfdx-source/apex-extensions/main/logger/classes/fflib_Logger.cls
new file mode 100644
index 0000000..0792098
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_Logger.cls
@@ -0,0 +1,233 @@
+/**
+ * File Name: fflib_Logger
+ * Description: Logging utility with standard system.debug log appender and log message formatter
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+public with sharing class fflib_Logger implements fflib_ILogger
+{
+ public static final String LF = '\n';
+ public static final String CR = '\r';
+
+ private static final String ORG_NAMESPACE = [SELECT NamespacePrefix FROM Organization].NamespacePrefix;
+ private static final String CLASSNAME = fflib_Logger.class.getName();
+ private static final Pattern STACK_LINE =
+ Pattern.compile('^(?:Class\\.)?([^.]+)\\.?([^\\.\\:]+)?[\\.\\:]?([^\\.\\:]*): line (\\d+), column (\\d+)$');
+
+
+ protected List logAppenders = new List
+ {
+ new SystemAppender()
+ };
+
+ protected fflib_ILogMessageFormatter messageFormatter = new LogMessageFormatter();
+
+
+ public void add(String message)
+ {
+ add(System.LoggingLevel.INFO, message);
+
+ }
+
+ public void add(LoggingLevel loggingLevel, Exception e)
+ {
+ add(new fflib_LogEntry(loggingLevel, messageFormatter.format(e)));
+ }
+
+ public void add(LoggingLevel loggingLevel, String message)
+ {
+ add(new fflib_LogEntry(loggingLevel, messageFormatter.format(message)));
+ }
+
+ public void add(LoggingLevel loggingLevel, String message, List args)
+ {
+ add(new fflib_LogEntry(loggingLevel, messageFormatter.format(message, args)));
+ }
+
+ private void add(fflib_LogEntry logEntry)
+ {
+ populateStackTrace(logEntry);
+ addLogEntryToAppenders(logEntry);
+ }
+
+ public fflib_ILogger addAppender(fflib_ILogAppender appender)
+ {
+ this.logAppenders.add(appender);
+ return this;
+ }
+
+
+ public void debug(Exception e)
+ {
+ add(System.LoggingLevel.DEBUG, e);
+ }
+
+ public void debug(String message)
+ {
+ add(System.LoggingLevel.DEBUG, message);
+ }
+
+ public void debug(String message, List args)
+ {
+ add(System.LoggingLevel.DEBUG, message, args);
+ }
+
+ public void error(Exception e)
+ {
+ add(System.LoggingLevel.ERROR, e);
+ }
+
+ public void error(String message)
+ {
+ add(System.LoggingLevel.ERROR, message);
+ }
+
+ public void error(String message, List args)
+ {
+ add(System.LoggingLevel.ERROR, message, args);
+ }
+
+ public void info(Exception e)
+ {
+ add(System.LoggingLevel.INFO, e);
+ }
+
+ public void info(String message)
+ {
+ add(System.LoggingLevel.INFO, message);
+ }
+
+ public void info(String message, List args)
+ {
+ add(System.LoggingLevel.INFO, message, args);
+ }
+
+ public fflib_ILogger setAppender(fflib_ILogAppender appender)
+ {
+ this.logAppenders.clear();
+ this.logAppenders.add(appender);
+ return this;
+ }
+
+ public fflib_ILogger setMessageFormatter(fflib_ILogMessageFormatter formatter)
+ {
+ this.messageFormatter = formatter;
+ return this;
+ }
+
+ public void warning(String message)
+ {
+ add(System.LoggingLevel.WARN, message);
+ }
+
+ public void warning(String message, List args)
+ {
+ add(System.LoggingLevel.WARN, message, args);
+ }
+
+
+ private void populateStackTrace(fflib_LogEntry logEntry)
+ {
+ List stacktrace = new DmlException().getStackTraceString().split('\n');
+
+ for (String line : stacktrace)
+ {
+ Matcher matcher = STACK_LINE.matcher(line);
+
+ if (matcher.find() && !line.startsWith('Class.' + CLASSNAME + '.'))
+ {
+ Boolean hasNamespace = String.isNotBlank(matcher.group(3));
+
+ if (hasNamespace)
+ {
+ logEntry.className =
+ (matcher.group(1).equals(ORG_NAMESPACE)) ?
+ matcher.group(2)
+ :
+ matcher.group(1) + '.' + matcher.group(2);
+
+ logEntry.methodName = formatMethodName(matcher.group(3));
+ }
+ else
+ {
+ logEntry.className = matcher.group(1);
+ logEntry.methodName = formatMethodName(matcher.group(2));
+ }
+
+ logEntry.lineNumber = Integer.valueOf(matcher.group(4));
+ return;
+ }
+ }
+ }
+
+ private String formatMethodName(String method)
+ {
+ String result = (method == null) ? 'anonymous' : method;
+ return (result.contains('init')) ? 'ctor' : result;
+ }
+
+ private void addLogEntryToAppenders(fflib_LogEntry logEntry)
+ {
+ for (fflib_ILogAppender logAppender : logAppenders)
+ {
+ logAppender.append(logEntry);
+ }
+ }
+
+ public virtual class SystemAppender implements fflib_ILogAppender
+ {
+ public void append(fflib_LogEntry logEntry)
+ {
+ System.debug(logEntry.className + ' #' + logEntry.lineNumber + ' @'+ logEntry.methodName + ' ' + logEntry.message);
+ }
+ }
+
+ public virtual class LogMessageFormatter implements fflib_ILogMessageFormatter
+ {
+ public virtual String format(String message)
+ {
+ return message;
+ }
+
+ public virtual String format(String message, List args)
+ {
+ return String.format(message, args);
+ }
+
+ public virtual String format(Exception e)
+ {
+ String result = 'Exception: ' + e;
+ if (null != e.getCause())
+ {
+ result += LF + ' Cause: ' + e.getCause();
+ }
+ result += LF + ' Stack trace: ' + e.getStackTraceString();
+
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_Logger.cls-meta.xml b/sfdx-source/apex-extensions/main/logger/classes/fflib_Logger.cls-meta.xml
new file mode 100644
index 0000000..f3bac1f
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_Logger.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 41.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_PlatformEventDomain.cls b/sfdx-source/apex-extensions/main/logger/classes/fflib_PlatformEventDomain.cls
new file mode 100644
index 0000000..3b58590
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_PlatformEventDomain.cls
@@ -0,0 +1,41 @@
+/**
+ * File Name: fflib_PlatformEventDomain
+ * Description: Platform Events Domain abstract class
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+public abstract with sharing class fflib_PlatformEventDomain implements ffllib_IPlatformEventDomain
+{
+
+ protected List Records { get; private set; }
+
+
+ public fflib_PlatformEventDomain(List records)
+ {
+ this.Records = records;
+ }
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/classes/fflib_PlatformEventDomain.cls-meta.xml b/sfdx-source/apex-extensions/main/logger/classes/fflib_PlatformEventDomain.cls-meta.xml
new file mode 100644
index 0000000..91b23b8
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/fflib_PlatformEventDomain.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 46.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/main/logger/classes/ffllib_IPlatformEventDomain.cls b/sfdx-source/apex-extensions/main/logger/classes/ffllib_IPlatformEventDomain.cls
new file mode 100644
index 0000000..eabe777
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/ffllib_IPlatformEventDomain.cls
@@ -0,0 +1,34 @@
+/**
+ * File Name: ffllib_IPlatformEventDomain
+ * Description: Platform events domain interface
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+public interface ffllib_IPlatformEventDomain
+{
+ void run();
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/classes/ffllib_IPlatformEventDomain.cls-meta.xml b/sfdx-source/apex-extensions/main/logger/classes/ffllib_IPlatformEventDomain.cls-meta.xml
new file mode 100644
index 0000000..91b23b8
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/classes/ffllib_IPlatformEventDomain.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 46.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/main/logger/layouts/fflib_LogEntry__c-Log Entry Layout.layout-meta.xml b/sfdx-source/apex-extensions/main/logger/layouts/fflib_LogEntry__c-Log Entry Layout.layout-meta.xml
new file mode 100644
index 0000000..4405ab4
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/layouts/fflib_LogEntry__c-Log Entry Layout.layout-meta.xml
@@ -0,0 +1,84 @@
+
+
+ Submit
+
+ false
+ false
+ true
+
+
+
+ Required
+ Name
+
+
+
+
+ Edit
+ User__c
+
+
+ Required
+ LogLevel__c
+
+
+
+
+
+ true
+ true
+ true
+
+
+
+ Edit
+ Message__c
+
+
+
+
+
+ false
+ false
+ true
+
+
+
+ Readonly
+ CreatedById
+
+
+
+
+ Readonly
+ LastModifiedById
+
+
+ Edit
+ OwnerId
+
+
+
+
+
+ true
+ false
+ true
+
+
+
+
+
+
+ false
+ false
+ false
+ false
+ false
+
+ 00h3D000000xiYW
+ 4
+ 0
+ Default
+
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fflib_LogEntry__c.object-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fflib_LogEntry__c.object-meta.xml
new file mode 100644
index 0000000..763b91e
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fflib_LogEntry__c.object-meta.xml
@@ -0,0 +1,64 @@
+
+
+
+ Accept
+ Default
+
+
+ CancelEdit
+ Default
+
+
+ Clone
+ Default
+
+
+ Delete
+ Default
+
+
+ Edit
+ Default
+
+
+ List
+ Default
+
+
+ New
+ Default
+
+
+ SaveEdit
+ Default
+
+
+ Tab
+ Default
+
+
+ View
+ Default
+
+ false
+ SYSTEM
+ Deployed
+ Object to store log entries after they a caught from a Platform event
+ false
+ true
+ false
+ false
+ true
+ true
+ true
+ true
+
+
+
+ Text
+
+ LogEntries
+
+ ReadWrite
+ Public
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/ClassName__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/ClassName__c.field-meta.xml
new file mode 100644
index 0000000..9746530
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/ClassName__c.field-meta.xml
@@ -0,0 +1,13 @@
+
+
+ ClassName__c
+ false
+ false
+ false
+ false
+
+ 80
+ false
+ Text
+ false
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/ExecutionContext__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/ExecutionContext__c.field-meta.xml
new file mode 100644
index 0000000..e1af4ce
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/ExecutionContext__c.field-meta.xml
@@ -0,0 +1,13 @@
+
+
+ ExecutionContext__c
+ false
+ false
+ false
+ false
+
+ 80
+ false
+ Text
+ false
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/LineNumber__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/LineNumber__c.field-meta.xml
new file mode 100644
index 0000000..af1c400
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/LineNumber__c.field-meta.xml
@@ -0,0 +1,14 @@
+
+
+ LineNumber__c
+ false
+ false
+ false
+ false
+
+ 18
+ false
+ 0
+ Number
+ false
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/LogLevel__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/LogLevel__c.field-meta.xml
new file mode 100644
index 0000000..54d66be
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/LogLevel__c.field-meta.xml
@@ -0,0 +1,36 @@
+
+
+ LogLevel__c
+ The logging level
+ false
+
+ true
+ false
+ Picklist
+
+ true
+
+ false
+
+ ERROR
+ false
+
+
+
+ WARN
+ false
+
+
+
+ INFO
+ false
+
+
+
+ DEBUG
+ false
+
+
+
+
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/Message__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/Message__c.field-meta.xml
new file mode 100644
index 0000000..37f034b
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/Message__c.field-meta.xml
@@ -0,0 +1,11 @@
+
+
+ Message__c
+ The Message of the log entry
+ false
+
+ 32768
+ false
+ LongTextArea
+ 5
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/MethodName__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/MethodName__c.field-meta.xml
new file mode 100644
index 0000000..1a94447
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/MethodName__c.field-meta.xml
@@ -0,0 +1,13 @@
+
+
+ MethodName__c
+ false
+ false
+ false
+ false
+
+ 80
+ false
+ Text
+ false
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/User__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/User__c.field-meta.xml
new file mode 100644
index 0000000..e46ee60
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/User__c.field-meta.xml
@@ -0,0 +1,13 @@
+
+
+ User__c
+ The User
+ SetNull
+ false
+
+ User
+ LogEntries
+ false
+ false
+ Lookup
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All.listView-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All.listView-meta.xml
new file mode 100644
index 0000000..614e7c3
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All.listView-meta.xml
@@ -0,0 +1,10 @@
+
+
+ All
+ Everything
+
+ NAME
+ CREATED_DATE
+ LogLevel__c
+ User__c
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Debug_Last_7_days.listView-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Debug_Last_7_days.listView-meta.xml
new file mode 100644
index 0000000..17a4253
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Debug_Last_7_days.listView-meta.xml
@@ -0,0 +1,20 @@
+
+
+ All_Debug_Last_7_days
+ NAME
+ CREATED_DATE
+ User__c
+ Message__c
+ Everything
+
+ LogLevel__c
+ equals
+ ERROR
+
+
+ CREATED_DATE
+ equals
+ LAST_N_DAYS:7
+
+
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Error_Last_7_days.listView-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Error_Last_7_days.listView-meta.xml
new file mode 100644
index 0000000..6e283c4
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Error_Last_7_days.listView-meta.xml
@@ -0,0 +1,20 @@
+
+
+ All_Error_Last_7_days
+ NAME
+ CREATED_DATE
+ User__c
+ Message__c
+ Mine
+
+ LogLevel__c
+ equals
+ ERROR
+
+
+ CREATED_DATE
+ equals
+ LAST_N_DAYS:7
+
+
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Last_day.listView-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Last_day.listView-meta.xml
new file mode 100644
index 0000000..1f7d389
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Last_day.listView-meta.xml
@@ -0,0 +1,16 @@
+
+
+ All_Last_day
+ NAME
+ CREATED_DATE
+ LogLevel__c
+ User__c
+ Message__c
+ Everything
+
+ CREATED_DATE
+ equals
+ LAST_N_DAYS:1
+
+
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Warning_Last_7_days.listView-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Warning_Last_7_days.listView-meta.xml
new file mode 100644
index 0000000..14598ba
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Warning_Last_7_days.listView-meta.xml
@@ -0,0 +1,21 @@
+
+
+ All_Warning_Last_7_days
+ NAME
+ CREATED_DATE
+ LogLevel__c
+ User__c
+ Message__c
+ Mine
+
+ LogLevel__c
+ equals
+ WARN
+
+
+ CREATED_DATE
+ equals
+ LAST_N_DAYS:7
+
+
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fflib_LogEvent__e.object-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fflib_LogEvent__e.object-meta.xml
new file mode 100644
index 0000000..15cb317
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fflib_LogEvent__e.object-meta.xml
@@ -0,0 +1,8 @@
+
+
+ Deployed
+ FFLIB Logger Events
+ StandardVolume
+
+ Log Events
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/ClassName__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/ClassName__c.field-meta.xml
new file mode 100644
index 0000000..9746530
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/ClassName__c.field-meta.xml
@@ -0,0 +1,13 @@
+
+
+ ClassName__c
+ false
+ false
+ false
+ false
+
+ 80
+ false
+ Text
+ false
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/ExecutionContext__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/ExecutionContext__c.field-meta.xml
new file mode 100644
index 0000000..e1af4ce
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/ExecutionContext__c.field-meta.xml
@@ -0,0 +1,13 @@
+
+
+ ExecutionContext__c
+ false
+ false
+ false
+ false
+
+ 80
+ false
+ Text
+ false
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/LineNumber__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/LineNumber__c.field-meta.xml
new file mode 100644
index 0000000..af1c400
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/LineNumber__c.field-meta.xml
@@ -0,0 +1,14 @@
+
+
+ LineNumber__c
+ false
+ false
+ false
+ false
+
+ 18
+ false
+ 0
+ Number
+ false
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/LogLevel__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/LogLevel__c.field-meta.xml
new file mode 100644
index 0000000..541508b
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/LogLevel__c.field-meta.xml
@@ -0,0 +1,14 @@
+
+
+ LogLevel__c
+ false
+ false
+ false
+ false
+
+ 5
+ false
+ Text
+ false
+
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/Message__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/Message__c.field-meta.xml
new file mode 100644
index 0000000..e96ba1e
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/Message__c.field-meta.xml
@@ -0,0 +1,14 @@
+
+
+ Message__c
+ The message thrown by the Logger
+ false
+ false
+ false
+ false
+
+ 32768
+ LongTextArea
+ 5
+
+ fflib_LogEventDomain
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/MethodName__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/MethodName__c.field-meta.xml
new file mode 100644
index 0000000..1a94447
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/MethodName__c.field-meta.xml
@@ -0,0 +1,13 @@
+
+
+ MethodName__c
+ false
+ false
+ false
+ false
+
+ 80
+ false
+ Text
+ false
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogLevelFilter__c/fflib_LogLevelFilter__c.object-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogLevelFilter__c/fflib_LogLevelFilter__c.object-meta.xml
new file mode 100644
index 0000000..6fc90a7
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogLevelFilter__c/fflib_LogLevelFilter__c.object-meta.xml
@@ -0,0 +1,8 @@
+
+
+ Hierarchy
+ Filter to add customised logging for particular users
+ false
+
+ Public
+
diff --git a/sfdx-source/apex-extensions/main/logger/objects/fflib_LogLevelFilter__c/fields/LogLevel__c.field-meta.xml b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogLevelFilter__c/fields/LogLevel__c.field-meta.xml
new file mode 100644
index 0000000..8dbcb6f
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/objects/fflib_LogLevelFilter__c/fields/LogLevel__c.field-meta.xml
@@ -0,0 +1,13 @@
+
+
+ LogLevel__c
+ The minimum log level to report for the tracked User or Profile
+ false
+ Allowed values none, error, warn, info, debug
+
+ 5
+ false
+ false
+ Text
+ false
+
diff --git a/sfdx-source/apex-extensions/main/logger/reports/fflib_LogEntryReports.reportFolder-meta.xml b/sfdx-source/apex-extensions/main/logger/reports/fflib_LogEntryReports.reportFolder-meta.xml
new file mode 100644
index 0000000..7571ce6
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/reports/fflib_LogEntryReports.reportFolder-meta.xml
@@ -0,0 +1,4 @@
+
+
+ Log Entries
+
diff --git a/sfdx-source/apex-extensions/main/logger/reports/fflib_LogEntryReports/LogEntries_Report_Count_per_loglevel_NQR.report-meta.xml b/sfdx-source/apex-extensions/main/logger/reports/fflib_LogEntryReports/LogEntries_Report_Count_per_loglevel_NQR.report-meta.xml
new file mode 100644
index 0000000..60f0e22
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/reports/fflib_LogEntryReports/LogEntries_Report_Count_per_loglevel_NQR.report-meta.xml
@@ -0,0 +1,28 @@
+
+
+
+ CUST_NAME
+
+ Summary
+
+ CUST_CREATED_DATE
+ Asc
+
+
+ Day
+ fflib_LogEntry__c.LogLevel__c
+ Asc
+
+ LogEntries Report - Day count per level
+
+ co
+ 1
+
+ CustomEntity$fflib_LogEntry__c
+ organization
+ false
+
+ CUST_CREATED_DATE
+ INTERVAL_CUSTOM
+
+
diff --git a/sfdx-source/apex-extensions/main/logger/reports/fflib_LogEntryReports/Yesterdays_Prio_LogEntries_Report_H7Z.report-meta.xml b/sfdx-source/apex-extensions/main/logger/reports/fflib_LogEntryReports/Yesterdays_Prio_LogEntries_Report_H7Z.report-meta.xml
new file mode 100644
index 0000000..3982d0f
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/reports/fflib_LogEntryReports/Yesterdays_Prio_LogEntries_Report_H7Z.report-meta.xml
@@ -0,0 +1,46 @@
+
+
+
+ CUST_NAME
+
+
+ CUST_CREATED_DATE
+
+
+ fflib_LogEntry__c.LogLevel__c
+
+
+ fflib_LogEntry__c.User__c
+
+
+ fflib_LogEntry__c.Message__c
+
+ Shows all ERROR and WARNING log entires from yesterday
+
+
+ CUST_CREATED_DATE
+ true
+ equals
+ YESTERDAY
+
+
+ fflib_LogEntry__c.LogLevel__c
+ true
+ equals
+ ERROR,WARN
+
+
+ Tabular
+ LogEntries Report - Yesterday
+
+ co
+ 1
+
+ CustomEntity$fflib_LogEntry__c
+ organization
+ true
+
+ CUST_CREATED_DATE
+ INTERVAL_CUSTOM
+
+
diff --git a/sfdx-source/apex-extensions/main/logger/tabs/fflib_LogEntry__c.tab-meta.xml b/sfdx-source/apex-extensions/main/logger/tabs/fflib_LogEntry__c.tab-meta.xml
new file mode 100644
index 0000000..b1c82f4
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/tabs/fflib_LogEntry__c.tab-meta.xml
@@ -0,0 +1,6 @@
+
+
+ true
+ Tab to show Log Entries
+ Custom34: Insect
+
diff --git a/sfdx-source/apex-extensions/main/logger/triggers/fflib_LogEventTrigger.trigger b/sfdx-source/apex-extensions/main/logger/triggers/fflib_LogEventTrigger.trigger
new file mode 100644
index 0000000..ff45d1b
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/triggers/fflib_LogEventTrigger.trigger
@@ -0,0 +1,10 @@
+/**
+ * File Name: sflib_LogEventTrigger
+ * Description: Tigger to store Log events into a custom object
+ * Copyright (c) 2019 Johnson & Johnson
+ * @author: architect ir. Wilhelmus G.J. Velzeboer | wvelzebo@its.jnj.com
+ */
+trigger fflib_LogEventTrigger on fflib_LogEvent__e (after insert)
+{
+ new fflib_LogEventStoreListener(Trigger.new).run();
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/main/logger/triggers/fflib_LogEventTrigger.trigger-meta.xml b/sfdx-source/apex-extensions/main/logger/triggers/fflib_LogEventTrigger.trigger-meta.xml
new file mode 100644
index 0000000..6205514
--- /dev/null
+++ b/sfdx-source/apex-extensions/main/logger/triggers/fflib_LogEventTrigger.trigger-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 41.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/tests/classes/logger/fflib_ALogAppenderFilterTest.cls b/sfdx-source/apex-extensions/tests/classes/logger/fflib_ALogAppenderFilterTest.cls
new file mode 100644
index 0000000..0cb0c5b
--- /dev/null
+++ b/sfdx-source/apex-extensions/tests/classes/logger/fflib_ALogAppenderFilterTest.cls
@@ -0,0 +1,228 @@
+/**
+ * File Name: fflib_LogAppenderFilterTest
+ * Description: Unit test class for fflib_LogAppenderFilter.cls
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+@IsTest
+private class fflib_ALogAppenderFilterTest
+{
+ private static final String TEST_USER_PROFILE = 'Standard User';
+
+ @IsTest
+ static void itShouldValidateErrorLevelWithDefaultSetToError()
+ {
+ // GIVEN - We create an AppenderFilter instance and set the filter to ERRROR
+ FilteredAppender appender = new FilteredAppender();
+
+ // WHEN - we check if ERROR is valid
+ Boolean isValid = appender.checkValidLogLevel(System.LoggingLevel.ERROR);
+
+ // THEN - It should be valid
+ System.assert(isValid);
+ }
+
+ @IsTest
+ static void itShouldNotValidateErrorLevelWithDefaultSetToNone()
+ {
+ // GIVEN - We create an AppenderFilter instance and set the filter to NONE
+ FilteredAppender appender = new FilteredAppender();
+ appender.setLoggingLevel(System.LoggingLevel.NONE);
+
+ // WHEN - we check if ERROR is valid
+ Boolean isValid = appender.checkValidLogLevel(System.LoggingLevel.ERROR);
+
+ // THEN - It should not be valid
+ System.assert(!isValid);
+ }
+
+ @IsTest
+ static void itShouldNotValidateWarningLevelWithDefaultSetToError()
+ {
+ // GIVEN - We create an AppenderFilter instance and set the filter to NONE
+ FilteredAppender appender = new FilteredAppender();
+
+ // WHEN - we check if ERROR is valid
+ Boolean isValid = appender.checkValidLogLevel(System.LoggingLevel.WARN);
+
+ // THEN - It should not be valid
+ System.assert(!isValid);
+ }
+
+ /**
+ * THIS UNIT TEST IS DISABLED BY DEFAULT SINCE THERE IS NO KNOWN STANDARD USER FACTORY METHOD FOR THE TARGET ORG
+ */
+ @IsTest
+ static void itShouldValidateWarningLevelWithDefaultSetToErrorForSpecifiedUser()
+ {
+ // Given - A default AppenderFilter instance and a specific user config set to Warning
+ FilteredAppender appender = new FilteredAppender();
+ User testUser = generateUser();
+ insert testUser;
+
+ insert new fflib_LogLevelFilter__c(
+
+ SetupOwnerId = testUser.Id,
+ LogLevel__c = System.LoggingLevel.WARN.name()
+ );
+
+ // When - we check if WARNING is valid
+ Boolean isValid = false;
+ System.runAs(testUser)
+ {
+ isValid = appender.checkValidLogLevel(System.LoggingLevel.WARN);
+ }
+
+ // Then - It should be valid
+ System.assert(isValid);
+ }
+
+ /**
+ * THIS UNIT TEST IS DISABLED BY DEFAULT SINCE THERE IS NO KNOWN STANDARD USER FACTORY METHOD FOR THE TARGET ORG
+ */
+ @IsTest
+ static void itShouldValidateWarningLevelWithDefaultSetToErrorForSpecifiedProfile()
+ {
+ // Given - A default AppenderFilter instance and a specific user config set to Warning
+ FilteredAppender appender = new FilteredAppender();
+ User testUser = generateUser();
+ insert testUser;
+
+ insert new fflib_LogLevelFilter__c(
+
+ SetupOwnerId = testUser.ProfileId,
+ LogLevel__c = System.LoggingLevel.WARN.name()
+ );
+
+ // When - we check if WARNING is valid
+ Boolean isValid = false;
+ System.runAs(testUser)
+ {
+ isValid = appender.checkValidLogLevel(System.LoggingLevel.WARN);
+ }
+
+ // Then - It should be valid
+ System.assert(isValid);
+ }
+
+ @IsTest
+ static void itShouldValidateWarningLevelWithDefaultOrganisationLogLevelValueSetToWarning()
+ {
+ // GIVEN - A default AppenderFilter instance with log level set to ERROR
+ // and a custom setting at Organisation Level to WARNING
+ FilteredAppender appender = new FilteredAppender();
+
+ fflib_LogLevelFilter__c settings = fflib_LogLevelFilter__c.getOrgDefaults();
+ settings.LogLevel__c = 'WARN';
+ upsert settings fflib_LogLevelFilter__c.Id;
+
+ // WHEN - We check if WARNING is valid
+ Boolean isValid = appender.checkValidLogLevel(System.LoggingLevel.WARN);
+
+ // Then - It should be valid
+ System.assert(isValid);
+ }
+
+ @IsTest
+ static void itShouldValidateWarningLevelWithDefaultOrganisationLogLevelValueSetToLowerCaseWarning()
+ {
+ // GIVEN - A default AppenderFilter instance with log level set to ERROR
+ // and a custom setting at Organisation Level to WARNING
+ FilteredAppender appender = new FilteredAppender();
+
+ fflib_LogLevelFilter__c settings = fflib_LogLevelFilter__c.getOrgDefaults();
+ settings.LogLevel__c = 'warn';
+ upsert settings fflib_LogLevelFilter__c.Id;
+
+ // WHEN - We check if WARNING is valid
+ Boolean isValid = appender.checkValidLogLevel(System.LoggingLevel.WARN);
+
+ // Then - It should be valid
+ System.assert(isValid);
+ }
+
+
+ @IsTest
+ static void itShouldNotFailWithIncorrectValueSetForDefaultOrganisationLogLevel()
+ {
+ // GIVEN - A default AppenderFilter instance with log level set to ERROR
+ // and a custom setting at Organisation Level to FAIL
+ FilteredAppender appender = new FilteredAppender();
+
+ fflib_LogLevelFilter__c settings = fflib_LogLevelFilter__c.getOrgDefaults();
+ settings.LogLevel__c = 'Fail';
+ upsert settings fflib_LogLevelFilter__c.Id;
+
+ // WHEN - We check if WARNING is valid
+ Boolean isValid = appender.checkValidLogLevel(System.LoggingLevel.WARN);
+
+ // Then - It should be valid
+ System.assert(!isValid);
+ }
+
+ @IsTest
+ static void itShouldNotLogWhenSetToNone()
+ {
+ // GIVEN - A default AppenderFilter instance with log level set to NONE
+ FilteredAppender appender = new FilteredAppender();
+ appender.setLoggingLevel(System.LoggingLevel.NONE);
+
+ // WHEN - We check if WARNING is valid
+ Boolean isValid = appender.checkValidLogLevel(System.LoggingLevel.WARN);
+
+ // Then - It should not be valid
+ System.assert(!isValid);
+ }
+
+
+ private static User generateUser()
+ {
+ Profile profile = [SELECT Id FROM Profile WHERE Name = :TEST_USER_PROFILE];
+ return new User(
+ Alias = 'jnjfflib',
+ Email = 'TestUser@example.com',
+ EmailEncodingKey = 'UTF-8',
+ FirstName = 'Test',
+ LanguageLocaleKey = 'en_US',
+ LastName = 'User',
+ LocaleSidKey = 'en_US',
+ ProfileId = profile.Id,
+ TimeZoneSidKey = 'America/Los_Angeles',
+ Username = 'TestUser@example.com.jnjfflib'
+ );
+ }
+
+ private class FilteredAppender extends fflib_ALogAppenderFilter
+ {
+ public Boolean checkValidLogLevel(System.LoggingLevel logLevel)
+ {
+ return isValidLogLevel(logLevel);
+ }
+
+ public void append(fflib_LogEntry logEntry) {}
+ }
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/tests/classes/logger/fflib_ALogAppenderFilterTest.cls-meta.xml b/sfdx-source/apex-extensions/tests/classes/logger/fflib_ALogAppenderFilterTest.cls-meta.xml
new file mode 100644
index 0000000..f3bac1f
--- /dev/null
+++ b/sfdx-source/apex-extensions/tests/classes/logger/fflib_ALogAppenderFilterTest.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 41.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventAppenderTest.cls b/sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventAppenderTest.cls
new file mode 100644
index 0000000..cd4c5b9
--- /dev/null
+++ b/sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventAppenderTest.cls
@@ -0,0 +1,103 @@
+/**
+ * File Name: fflib_LogEventAppenderTest
+ * Description: Unit test class for fflib_LogEventAppender.cls
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+@IsTest
+private class fflib_LogEventAppenderTest
+{
+ private static final String TEST_ERROR_MESSAGE = 'My Error Message';
+
+ @IsTest
+ static void itShouldThrowEventOnAppendedLogEntry()
+ {
+ // GIVEN - An instance of the LogEventAppender
+ fflib_LogEventAppender eventAppender = new fflib_LogEventAppender();
+
+
+ // WHEN - We append an entry
+ Boolean caughtException = false;
+ try
+ {
+ eventAppender.append(System.LoggingLevel.ERROR, TEST_ERROR_MESSAGE);
+ }
+ catch (Exception e)
+ {
+ caughtException = true;
+ }
+
+ // THEN - An Log Event should be thrown
+ System.assert(!caughtException);
+ }
+
+ static testMethod void itShouldNotAppendInfoMessageWhileDefaultLevelIsSetToError()
+ {
+ // GIVEN - And appender with a default level set to Error
+ fflib_LogEventAppender eventAppender = new fflib_LogEventAppender();
+
+ // WHEN - We append an Info Entry
+ eventAppender.append(System.LoggingLevel.INFO, TEST_ERROR_MESSAGE);
+
+ // THEN - It should be ignored
+ System.assertEquals(0, Limits.getDmlStatements(), 'Oops, the log entry should have been ignored');
+ }
+
+ static testMethod void itShouldAppendInfoMessageWhenTheApexLevelIsSetToInfo()
+ {
+ // GIVEN - And appender with a Apex level set to Info
+ fflib_LogEventAppender eventAppender = new fflib_LogEventAppender();
+ eventAppender.setLoggingLevel(System.LoggingLevel.INFO);
+
+ // WHEN - We append an Info Entry
+ System.Test.startTest();
+ eventAppender.append(System.LoggingLevel.INFO, TEST_ERROR_MESSAGE);
+ System.Test.stopTest();
+
+ // THEN - It should be ignored
+ System.assertEquals(1, [SELECT COUNT() FROM fflib_LogEntry__c]);
+ }
+
+ static testMethod void itShouldAppendInfoMessageWhenTheOrgSettingsLevelIsSetToInfo()
+ {
+ // GIVEN - And appender with a Org level set to Info
+ fflib_LogEventAppender eventAppender = new fflib_LogEventAppender();
+
+ fflib_LogLevelFilter__c orgSettings = fflib_LogLevelFilter__c.getOrgDefaults();
+ System.debug(orgSettings);
+ orgSettings.LogLevel__c = 'INFO';
+ insert orgSettings;
+
+ // WHEN - We append an Info Entry
+ System.Test.startTest();
+ eventAppender.append(System.LoggingLevel.INFO, TEST_ERROR_MESSAGE);
+ System.Test.stopTest();
+
+ // THEN - It should be ignored
+ System.assertEquals(1, [SELECT COUNT() FROM fflib_LogEntry__c]);
+ }
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventAppenderTest.cls-meta.xml b/sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventAppenderTest.cls-meta.xml
new file mode 100644
index 0000000..f3bac1f
--- /dev/null
+++ b/sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventAppenderTest.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 41.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventStoreListenerTest.cls b/sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventStoreListenerTest.cls
new file mode 100644
index 0000000..c0fff7e
--- /dev/null
+++ b/sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventStoreListenerTest.cls
@@ -0,0 +1,103 @@
+/**
+ * File Name: fflib_LogEventStoreListenerTest
+ * Description: Unit tests for fflib_LogEventStoreListener.cls
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+@IsTest
+private class fflib_LogEventStoreListenerTest
+{
+
+ private static final String ERROR_MESSAGE = 'My Error Message';
+
+ private static final String TEST_USER_PROFILE = 'Standard User';
+
+ @IsTest
+ static void itShouldStoreRecordOnLogEvent()
+ {
+ // GIVEN - A Log Event
+ fflib_LogEvent__e logEvent = generateLoggingLevelEvent(System.LoggingLevel.ERROR, ERROR_MESSAGE);
+
+ // WHEN - The log event is published
+ System.Test.startTest();
+ EventBus.publish(logEvent);
+ System.Test.stopTest();
+
+ // THEN - a record should be created in the Log Event Store
+ System.assertEquals(1, [SELECT COUNT() FROM fflib_LogEntry__c]);
+ }
+
+ /**
+ * THIS UNIT TEST IS DISABLED BY DEFAULT SINCE THERE IS NO KNOWN STANDARD USER FACTORY METHOD FOR THE TARGET ORG
+ */
+ @IsTest
+ static void itShouldStoreRecordOnLogEventWithUserDetails()
+ {
+ // GIVEN - A Log Event thrown by a specific user
+ fflib_LogEvent__e logEvent = generateLoggingLevelEvent(System.LoggingLevel.ERROR, ERROR_MESSAGE);
+ User testUser = generateUser();
+ insert testUser;
+
+ // WHEN - The log event is published
+ System.Test.startTest();
+ System.runAs(testUser)
+ {
+ EventBus.publish(logEvent);
+ }
+ System.Test.stopTest();
+
+ // THEN - a record should be created in the Log Event Store
+ List logEntries = [SELECT Id, LogLevel__c, Message__c, User__c FROM fflib_LogEntry__c];
+ System.assert(logEntries.size() == 1);
+ System.assertEquals(testUser.Id, logEntries.get(0).User__c, 'Log Entry stored with wrong CreatedById');
+ }
+
+ private static fflib_LogEvent__e generateLoggingLevelEvent(LoggingLevel loggingLevel, String message)
+ {
+ return new fflib_LogEvent__e(
+ LogLevel__c = loggingLevel.ordinal(),
+ message__c = message
+ );
+ }
+
+ private static User generateUser()
+ {
+ Profile profile = [SELECT Id FROM Profile WHERE Name = :TEST_USER_PROFILE];
+ return new User(
+ Alias = 'jnjfflib',
+ Email = 'TestUser@example.com',
+ EmailEncodingKey = 'UTF-8',
+ FirstName = 'Test',
+ LanguageLocaleKey = 'en_US',
+ LastName = 'User',
+ LocaleSidKey = 'en_US',
+ ProfileId = profile.Id,
+ TimeZoneSidKey = 'America/Los_Angeles',
+ Username = 'TestUser@example.com.jnjfflib'
+ );
+ }
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventStoreListenerTest.cls-meta.xml b/sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventStoreListenerTest.cls-meta.xml
new file mode 100644
index 0000000..f3bac1f
--- /dev/null
+++ b/sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventStoreListenerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 41.0
+ Active
+
diff --git a/sfdx-source/apex-extensions/tests/classes/logger/fflib_LoggerTest.cls b/sfdx-source/apex-extensions/tests/classes/logger/fflib_LoggerTest.cls
new file mode 100644
index 0000000..83dd2ef
--- /dev/null
+++ b/sfdx-source/apex-extensions/tests/classes/logger/fflib_LoggerTest.cls
@@ -0,0 +1,326 @@
+/**
+ * File Name: fflib_LoggerTest
+ * Description: Unit test for fflib_Logger.cls
+ *
+ * @author architect ir. Wilhelmus G.J. Velzeboer
+ *
+ * Copyright (c), W.G.J. Velzeboer,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above author notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+@IsTest
+private class fflib_LoggerTest
+{
+/*
+ private static final List ARGUMENTS = new List {'A', 'B', 'C'};
+ private static final String ERROR_MESSAGE = 'Some Error';
+ private static final String ERROR_MESSAGE_WITH_ARGS = 'Some Error {0}, {1}, {2}';
+ private static final String ERROR_MESSAGE_FORMATTED_WITH_EXCEPTION = String.format(
+ 'Exception: {0} {1}\n Stack trace: {2}',
+ new List
+ {
+ 'LogTestMockException:[]:',
+ ERROR_MESSAGE,
+ '()'
+ }
+ );
+ private static final String ERROR_MESSAGE_FORMATTED_WITH_ARGS =
+ String.format(
+ ERROR_MESSAGE_WITH_ARGS,
+ ARGUMENTS
+ );
+ private static final LogAppenderMock APPENDER_MOCK = new LogAppenderMock();
+ private static final SecondLogAppenderMock APPENDER_MOCK_B = new SecondLogAppenderMock();
+
+
+ @IsTest
+ static void itShouldAppendAMessage()
+ {
+ // GIVEN - An error message and a configured logger
+ fflib_ILogger log = generatedLoggerWithMockAppender();
+
+ // WHEN - When the error is logged
+ log.add(ERROR_MESSAGE);
+
+ // THEN - It should be appended to the logAppender
+ System.assert(APPENDER_MOCK.getAppendedMessages(System.LoggingLevel.INFO).contains(ERROR_MESSAGE));
+ }
+
+ @IsTest
+ static void itShouldAppendDebugMessage()
+ {
+ // GIVEN - An error message and a configured logger
+ fflib_ILogger log = generatedLoggerWithMockAppender();
+
+ // WHEN - When the error is logged
+ log.debug(ERROR_MESSAGE);
+
+ // THEN - It should be appended to the logAppender
+ System.assert(
+ APPENDER_MOCK
+ .getAppendedMessages(System.LoggingLevel.DEBUG)
+ .contains(ERROR_MESSAGE)
+ );
+ }
+
+ /**
+ * todo : For some reason this method fails when run by Jenkins deployment user during a build, need to investigate why and re-enable it
+
+ @IsTest
+ static void itShouldAppendDebugException()
+ {
+ // GIVEN - An error message and a configured logger
+ fflib_ILogger log = generatedLoggerWithMockAppender();
+ Exception e = new LogTestMockException(ERROR_MESSAGE);
+
+ // WHEN - When the error is logged
+ log.debug(e);
+
+ // THEN - It should be appended to the logAppender
+ System.assert(
+ APPENDER_MOCK
+ .getAppendedMessages(System.LoggingLevel.DEBUG)
+ .contains(ERROR_MESSAGE_FORMATTED_WITH_EXCEPTION)
+ );
+ }
+ */
+
+ @IsTest
+ static void itShouldAppendDebugMessageWithArguments()
+ {
+ // GIVEN - An error message and a configured logger
+ fflib_ILogger log = generatedLoggerWithMockAppender();
+
+ // WHEN - When the error is logged
+ log.debug(ERROR_MESSAGE_WITH_ARGS, ARGUMENTS);
+
+ // THEN - It should be appended to the logAppender
+ System.assert(
+ APPENDER_MOCK
+ .getAppendedMessages(System.LoggingLevel.DEBUG)
+ .contains(ERROR_MESSAGE_FORMATTED_WITH_ARGS)
+ );
+ }
+
+ @IsTest
+ static void itShouldAppendErrorMessage()
+ {
+ // GIVEN - An error message and a configured logger
+ fflib_ILogger log = generatedLoggerWithMockAppender();
+
+ // WHEN - When the error is logged
+ log.error(ERROR_MESSAGE);
+
+ // THEN - It should be appended to the logAppender
+ System.assert(APPENDER_MOCK.getAppendedMessages(System.LoggingLevel.ERROR).contains(ERROR_MESSAGE));
+ }
+
+ @IsTest
+ static void itShouldAppendErrorMessageWithArguments()
+ {
+ // GIVEN - An error message and a configured logger
+ fflib_ILogger log = generatedLoggerWithMockAppender();
+
+ // WHEN - When the error is logged
+ log.error(ERROR_MESSAGE_WITH_ARGS, ARGUMENTS);
+
+ // THEN - It should be appended to the logAppender
+ System.assert(
+ APPENDER_MOCK
+ .getAppendedMessages(System.LoggingLevel.ERROR)
+ .contains(ERROR_MESSAGE_FORMATTED_WITH_ARGS)
+ );
+ }
+
+ @IsTest
+ static void itShouldAppendInfoMessage()
+ {
+ // GIVEN - An error message and a configured logger
+ fflib_ILogger log = generatedLoggerWithMockAppender();
+
+ // WHEN - When the error is logged
+ log.info(ERROR_MESSAGE);
+
+ // THEN - It should be appended to the logAppender
+ System.assert(APPENDER_MOCK.getAppendedMessages(System.LoggingLevel.INFO).contains(ERROR_MESSAGE));
+ }
+
+ @IsTest
+ static void itShouldAppendInfoMessageWithArguments()
+ {
+ // GIVEN - An error message and a configured logger
+ fflib_ILogger log = generatedLoggerWithMockAppender();
+
+ // WHEN - When the error is logged
+ log.info(ERROR_MESSAGE_WITH_ARGS, ARGUMENTS);
+
+ // THEN - It should be appended to the logAppender
+ System.assert(
+ APPENDER_MOCK
+ .getAppendedMessages(System.LoggingLevel.INFO)
+ .contains(ERROR_MESSAGE_FORMATTED_WITH_ARGS)
+ );
+ }
+
+ @IsTest
+ static void itShouldAppendWarningMessage()
+ {
+ // GIVEN - An error message and a configured logger
+ fflib_ILogger log = generatedLoggerWithMockAppender();
+
+ // WHEN - When the error is logged
+ log.warning(ERROR_MESSAGE);
+
+ // THEN - It should be appended to the logAppender
+ System.assert(APPENDER_MOCK.getAppendedMessages(System.LoggingLevel.WARN).contains(ERROR_MESSAGE));
+ }
+
+ @IsTest
+ static void itShouldAppendWarningMessageWithArguments()
+ {
+ // GIVEN - An error message and a configured logger
+ fflib_ILogger log = generatedLoggerWithMockAppender();
+
+ // WHEN - When the error is logged
+ log.warning(ERROR_MESSAGE_WITH_ARGS, ARGUMENTS);
+
+ // THEN - It should be appended to the logAppender
+ System.assert(
+ APPENDER_MOCK
+ .getAppendedMessages(System.LoggingLevel.WARN)
+ .contains(ERROR_MESSAGE_FORMATTED_WITH_ARGS)
+ );
+ }
+
+ @IsTest
+ static void itShouldHandleTwoAppenders()
+ {
+ // GIVEN an error message and a logger with two appenders configured
+ fflib_ILogger log = new fflib_Logger();
+ log.addAppender(APPENDER_MOCK);
+ log.addAppender(APPENDER_MOCK_B);
+ log.setMessageFormatter(new fflib_Logger.LogMessageFormatter());
+
+ // WHEN - When the error is logged
+ log.error(ERROR_MESSAGE);
+
+ // THEN - It Should be added to both appenders
+ System.assert(
+ APPENDER_MOCK
+ .getAppendedMessages(System.LoggingLevel.ERROR)
+ .contains(ERROR_MESSAGE)
+ );
+ System.assert(
+ APPENDER_MOCK_B
+ .getAppendedMessages(System.LoggingLevel.ERROR)
+ .contains(ERROR_MESSAGE)
+ );
+ }
+
+
+ private static fflib_ILogger generatedLoggerWithMockAppender()
+ {
+ fflib_ILogger result = new fflib_Logger();
+ result.setAppender(APPENDER_MOCK);
+ result.setMessageFormatter(new fflib_Logger.LogMessageFormatter());
+ return result;
+ }
+
+
+ private class LogAppenderMock implements fflib_ILogAppender
+ {
+ private Map> appendedMessages =
+ new Map>();
+
+ public void append(String message)
+ {
+ if (!this.appendedMessages.containsKey(System.LoggingLevel.INFO))
+ {
+ this.appendedMessages.put(System.LoggingLevel.INFO, new List());
+ }
+ appendedMessages.get(System.LoggingLevel.INFO).add(message);
+ }
+
+ public void append(LoggingLevel loggingLevel, String message)
+ {
+ if (!this.appendedMessages.containsKey(loggingLevel))
+ {
+ this.appendedMessages.put(loggingLevel, new List());
+ }
+ appendedMessages.get(loggingLevel).add(message);
+ }
+
+ public List getAppendedMessages(System.LoggingLevel loggingLevel)
+ {
+ if (this.appendedMessages.containsKey(loggingLevel))
+ {
+ return this.appendedMessages.get(loggingLevel);
+ }
+ else
+ {
+ return new List();
+ }
+ }
+ }
+
+ private class SecondLogAppenderMock implements fflib_ILogAppender
+ {
+ private Map> appendedMessages =
+ new Map>();
+
+ public void append(String message)
+ {
+ if (!this.appendedMessages.containsKey(System.LoggingLevel.INFO))
+ {
+ this.appendedMessages.put(System.LoggingLevel.INFO, new List());
+ }
+ appendedMessages.get(System.LoggingLevel.INFO).add(message);
+ }
+
+ public void append(LoggingLevel loggingLevel, String message)
+ {
+ if (!this.appendedMessages.containsKey(loggingLevel))
+ {
+ this.appendedMessages.put(loggingLevel, new List());
+ }
+ appendedMessages.get(loggingLevel).add(message);
+ }
+
+ public List getAppendedMessages(System.LoggingLevel loggingLevel)
+ {
+ if (this.appendedMessages.containsKey(loggingLevel))
+ {
+ return this.appendedMessages.get(loggingLevel);
+ }
+ else
+ {
+ return new List();
+ }
+ }
+ }
+
+ private class LogTestMockException extends Exception
+ {
+ }
+ */
+}
\ No newline at end of file
diff --git a/sfdx-source/apex-extensions/tests/classes/logger/fflib_LoggerTest.cls-meta.xml b/sfdx-source/apex-extensions/tests/classes/logger/fflib_LoggerTest.cls-meta.xml
new file mode 100644
index 0000000..f3bac1f
--- /dev/null
+++ b/sfdx-source/apex-extensions/tests/classes/logger/fflib_LoggerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 41.0
+ Active
+