From 898ca0b0f42e877d3ce8629a5cbb367b94277844 Mon Sep 17 00:00:00 2001 From: Wim Velzeboer Date: Wed, 15 Sep 2021 10:08:01 +0100 Subject: [PATCH] Waiting for Winter'22 update to use enum.valueOf --- README.md | 10 +- sfdx-project.json | 2 +- .../classes/fflib_ALogAppenderFilter.cls | 197 +++++++++++ .../fflib_ALogAppenderFilter.cls-meta.xml | 5 + .../logger/classes/fflib_ILogAppender.cls | 34 ++ .../classes/fflib_ILogAppender.cls-meta.xml | 5 + .../classes/fflib_ILogMessageFormatter.cls | 36 ++ .../fflib_ILogMessageFormatter.cls-meta.xml | 5 + .../main/logger/classes/fflib_ILogger.cls | 48 +++ .../logger/classes/fflib_ILogger.cls-meta.xml | 5 + .../main/logger/classes/fflib_LogEntry.cls | 75 ++++ .../classes/fflib_LogEntry.cls-meta.xml | 5 + .../logger/classes/fflib_LogEventAppender.cls | 107 ++++++ .../fflib_LogEventAppender.cls-meta.xml | 5 + .../logger/classes/fflib_LogEventDomain.cls | 71 ++++ .../classes/fflib_LogEventDomain.cls-meta.xml | 5 + .../classes/fflib_LogEventStoreListener.cls | 57 +++ .../fflib_LogEventStoreListener.cls-meta.xml | 5 + .../main/logger/classes/fflib_Logger.cls | 233 +++++++++++++ .../logger/classes/fflib_Logger.cls-meta.xml | 5 + .../classes/fflib_PlatformEventDomain.cls | 41 +++ .../fflib_PlatformEventDomain.cls-meta.xml | 5 + .../classes/ffllib_IPlatformEventDomain.cls | 34 ++ .../ffllib_IPlatformEventDomain.cls-meta.xml | 5 + ...gEntry__c-Log Entry Layout.layout-meta.xml | 84 +++++ .../fflib_LogEntry__c.object-meta.xml | 64 ++++ .../fields/ClassName__c.field-meta.xml | 13 + .../fields/ExecutionContext__c.field-meta.xml | 13 + .../fields/LineNumber__c.field-meta.xml | 14 + .../fields/LogLevel__c.field-meta.xml | 36 ++ .../fields/Message__c.field-meta.xml | 11 + .../fields/MethodName__c.field-meta.xml | 13 + .../fields/User__c.field-meta.xml | 13 + .../listViews/All.listView-meta.xml | 10 + .../All_Debug_Last_7_days.listView-meta.xml | 20 ++ .../All_Error_Last_7_days.listView-meta.xml | 20 ++ .../listViews/All_Last_day.listView-meta.xml | 16 + .../All_Warning_Last_7_days.listView-meta.xml | 21 ++ .../fflib_LogEvent__e.object-meta.xml | 8 + .../fields/ClassName__c.field-meta.xml | 13 + .../fields/ExecutionContext__c.field-meta.xml | 13 + .../fields/LineNumber__c.field-meta.xml | 14 + .../fields/LogLevel__c.field-meta.xml | 14 + .../fields/Message__c.field-meta.xml | 14 + .../fields/MethodName__c.field-meta.xml | 13 + .../fflib_LogLevelFilter__c.object-meta.xml | 8 + .../fields/LogLevel__c.field-meta.xml | 13 + ...flib_LogEntryReports.reportFolder-meta.xml | 4 + ...ort_Count_per_loglevel_NQR.report-meta.xml | 28 ++ ...Prio_LogEntries_Report_H7Z.report-meta.xml | 46 +++ .../tabs/fflib_LogEntry__c.tab-meta.xml | 6 + .../triggers/fflib_LogEventTrigger.trigger | 10 + .../fflib_LogEventTrigger.trigger-meta.xml | 5 + .../logger/fflib_ALogAppenderFilterTest.cls | 228 ++++++++++++ .../fflib_ALogAppenderFilterTest.cls-meta.xml | 5 + .../logger/fflib_LogEventAppenderTest.cls | 103 ++++++ .../fflib_LogEventAppenderTest.cls-meta.xml | 5 + .../fflib_LogEventStoreListenerTest.cls | 103 ++++++ ...lib_LogEventStoreListenerTest.cls-meta.xml | 5 + .../tests/classes/logger/fflib_LoggerTest.cls | 326 ++++++++++++++++++ .../logger/fflib_LoggerTest.cls-meta.xml | 5 + 61 files changed, 2335 insertions(+), 2 deletions(-) create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_ALogAppenderFilter.cls create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_ALogAppenderFilter.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_ILogAppender.cls create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_ILogAppender.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_ILogMessageFormatter.cls create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_ILogMessageFormatter.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_ILogger.cls create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_ILogger.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_LogEntry.cls create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_LogEntry.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventAppender.cls create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventAppender.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventDomain.cls create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventDomain.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventStoreListener.cls create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_LogEventStoreListener.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_Logger.cls create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_Logger.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_PlatformEventDomain.cls create mode 100644 sfdx-source/apex-extensions/main/logger/classes/fflib_PlatformEventDomain.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/classes/ffllib_IPlatformEventDomain.cls create mode 100644 sfdx-source/apex-extensions/main/logger/classes/ffllib_IPlatformEventDomain.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/layouts/fflib_LogEntry__c-Log Entry Layout.layout-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fflib_LogEntry__c.object-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/ClassName__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/ExecutionContext__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/LineNumber__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/LogLevel__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/Message__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/MethodName__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/fields/User__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All.listView-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Debug_Last_7_days.listView-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Error_Last_7_days.listView-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Last_day.listView-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEntry__c/listViews/All_Warning_Last_7_days.listView-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fflib_LogEvent__e.object-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/ClassName__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/ExecutionContext__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/LineNumber__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/LogLevel__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/Message__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogEvent__e/fields/MethodName__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogLevelFilter__c/fflib_LogLevelFilter__c.object-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/objects/fflib_LogLevelFilter__c/fields/LogLevel__c.field-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/reports/fflib_LogEntryReports.reportFolder-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/reports/fflib_LogEntryReports/LogEntries_Report_Count_per_loglevel_NQR.report-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/reports/fflib_LogEntryReports/Yesterdays_Prio_LogEntries_Report_H7Z.report-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/tabs/fflib_LogEntry__c.tab-meta.xml create mode 100644 sfdx-source/apex-extensions/main/logger/triggers/fflib_LogEventTrigger.trigger create mode 100644 sfdx-source/apex-extensions/main/logger/triggers/fflib_LogEventTrigger.trigger-meta.xml create mode 100644 sfdx-source/apex-extensions/tests/classes/logger/fflib_ALogAppenderFilterTest.cls create mode 100644 sfdx-source/apex-extensions/tests/classes/logger/fflib_ALogAppenderFilterTest.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventAppenderTest.cls create mode 100644 sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventAppenderTest.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventStoreListenerTest.cls create mode 100644 sfdx-source/apex-extensions/tests/classes/logger/fflib_LogEventStoreListenerTest.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/tests/classes/logger/fflib_LoggerTest.cls create mode 100644 sfdx-source/apex-extensions/tests/classes/logger/fflib_LoggerTest.cls-meta.xml 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 +